Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
k8s-ingress
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
3
Merge Requests
3
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
uplex-varnish
k8s-ingress
Commits
65ab4547
Commit
65ab4547
authored
Feb 07, 2019
by
Geoff Simmons
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Auth config uses the same conditions array as for ACLs.
Closes #22
parent
6af60a42
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
198 additions
and
186 deletions
+198
-186
varnishcfg-crd.yaml
deploy/varnishcfg-crd.yaml
+22
-9
ref-varnish-cfg.md
docs/ref-varnish-cfg.md
+68
-70
README.md
examples/authentication/README.md
+26
-15
basic-auth.yaml
examples/authentication/basic-auth.yaml
+14
-6
types.go
pkg/apis/varnishingress/v1alpha1/types.go
+5
-13
zz_generated.deepcopy.go
pkg/apis/varnishingress/v1alpha1/zz_generated.deepcopy.go
+4
-20
ingress.go
pkg/controller/ingress.go
+30
-21
auth.tmpl
pkg/varnish/vcl/auth.tmpl
+2
-5
spec.go
pkg/varnish/vcl/spec.go
+4
-16
auth.golden
pkg/varnish/vcl/testdata/auth.golden
+2
-2
vcl_test.go
pkg/varnish/vcl/vcl_test.go
+21
-9
No files found.
deploy/varnishcfg-crd.yaml
View file @
65ab4547
...
...
@@ -79,13 +79,26 @@ spec:
type
:
string
utf8
:
type
:
boolean
condition
:
conditions
:
type
:
array
minItems
:
1
items
:
type
:
object
required
:
-
comparand
-
value
properties
:
url-match
:
comparand
:
type
:
string
minLength
:
1
host-match
:
pattern
:
"
^req
\\
.(url|http
\\
.[a-zA-Z0-9!#$%&'*+.^_`|~-]+)$"
compare
:
enum
:
-
equal
-
not-equal
-
match
-
not-match
type
:
string
value
:
type
:
string
minLength
:
1
acl
:
...
...
docs/ref-varnish-cfg.md
View file @
65ab4547
...
...
@@ -191,26 +191,56 @@ These fields in the elements of ``auth`` are optional:
encoding is used for the username/password (see
[
RFC 7617 2.1
](
https://tools.ietf.org/html/rfc7617#section-2.1
)
).
By default,
``charset``
is
``false``
.
*
``condition``
: conditions under which the authentication protocol is
*
``condition
s
``
: conditions under which the authentication protocol is
to be executed.
If the
``condition
``
object is present, it may have either or both of
these
fields:
If the
``condition
s``
array is present, then it MUST have at least one
element, and each element must specify at least these two
fields:
*
``url-match``
(regular expression): pattern to match against the
URL path of the request
*
``host-match``
(regular expression): pattern to match against the
``Host``
request header
*
``comparand``
(string): either
``req.url``
or
``req.http.$HEADER``
,
where
``$HEADER``
is the name of a client request header.
*
``value``
(string): the value against which the
``comparand``
is compared
``conditions``
may also have this optional field:
*
``compare``
: one of the following (default
``equal``
):
* ``equal`` for string equality
If either or both of these two fields are present, then the
authentication protocol is executed for matching requests. If the
``condition``
is left out, then the authentication is required for
every client request. The patterns in
``url-match``
and
``host-match``
are implemented as
* ``not-equal`` for string inequality
* ``match`` for regex match
* ``not-match`` for regex non-match
If
``compare``
is
``equal``
or
``not-equal``
, then
``value``
is
interpreted as a fixed string, and
``comparand``
is tested for
(in)equality with
``value``
. Otherwise,
``value``
is interpreted as a
regular expression, and the
``comparand``
is tested for
(non-)match. Regexen are implemented as
[
VCL regular expressions
](
https://varnish-cache.org/docs/6.1/reference/vcl.html#regular-expressions
)
,
and hence have the syntax and semantics of
[
PCRE
](
https://www.pcre.org/original/doc/html/
)
.
The authentication protocol is executed only if all of the
``conditions``
succeed; in other words, the
``conditions``
are the
boolean AND of all of the match terms.
For example, these
``conditions``
specify that authentication is
executed when the URL begins with "/tea", and the Host header is
exactly "cafe.example.com":
```
conditions:
- comparand: req.url
compare: match
value: ^/tea(/|$)
- comparand: req.http.Host
value: cafe.example.com
```
Validation for
``VarnishConfig``
reports errors at apply time if:
*
the
``auth``
array is empty
...
...
@@ -218,10 +248,10 @@ Validation for ``VarnishConfig`` reports errors at apply time if:
*
any of the string fields are empty
*
``type``
has an illegal value (neither of
``basic``
or
``proxy``
)
Other errors, in particular illegal regex syntax for
``
url-match``
or
``host-match``
, are not reported until VCL load time. Check the
controller log and Events generated for the Varnish Service for error
messages from the
VCL compiler.
Other errors, in particular illegal regex syntax for
``
conditions``
,
are not reported until VCL load time. Check the controller log and
Events generated for the Varnish Service for error messages from the
VCL compiler.
Examples:
```
...
...
@@ -237,9 +267,13 @@ spec:
secretName: coffee-creds
type: basic
utf8: true
condition:
host-match: ^cafe\.example\.com$
url-match: ^/coffee($|/)
conditions:
- comparand: req.http.Host
value: cafe.example.com
compare: equal
- comparand: req.url
value: ^/coffee($|/)
compare: match
# For the tea Service, require authentication for the realm "tea"
# when the Host is "cafe.example.com" and the URL path begins with
...
...
@@ -248,9 +282,13 @@ spec:
# left out.
- realm: tea
secretName: tea-creds
condition:
host-match: ^cafe\.example\.com$
url-match: ^/tea($|/)
conditions:
- comparand: req.http.Host
value: cafe.example.com
compare: equal
- comparand: req.url
value: ^/tea($|/)
compare: match
```
```
spec:
...
...
@@ -288,8 +326,10 @@ Optional fields for ``acl`` are:
is matched, as detailed below; default
``client.ip``
*
``conditions``
: array of conditions under which the ACL match is
executed, as detailed below. By default,
``conditions``
is empty,
in which case the match is executed for every client request.
executed. The
``conditions``
field has the same syntax and semantics
as specified above for
``spec.auth``
(Basic and Proxy
Authentication). By default,
``conditions``
is empty, in which case
the match is executed for every client request.
*
``result-header``
: specifies a client request header and values to
set for the header when the failure status is or is not invoked for
...
...
@@ -414,52 +454,10 @@ X-Forwarded-For: 192.0.2.47, 203.0.113.11
``xff-2ndlast``
specifies a match against 203.0.113.11.
If
``conditions``
are specified for an ACL, they define restrictions
for executing the match. Each element of
``conditions``
must specify
these two required fields:
*
``comparand``
(string): either
``req.url``
or
``req.http.$HEADER``
,
where
``$HEADER``
is the name of a client request header.
*
``value``
(string): the value against which the
``comparand``
is compared
``conditions``
may also have this optional field:
*
``compare``
: one of the following (default
``equal``
):
* ``equal`` for string equality
* ``not-equal`` for string inequality
* ``match`` for regex match
* ``not-match`` for regex non-match
If
``compare``
is
``equal``
or
``not-equal``
, then
``value``
is
interpreted as a fixed string, and
``comparand``
is tested for
(in)equality with
``value``
. Otherwise,
``value``
is interpreted as a
regular expression, and the
``comparand``
is tested for
(non-)match. Regexen are implemented as
[
VCL regular expressions
](
https://varnish-cache.org/docs/6.1/reference/vcl.html#regular-expressions
)
,
and hence have the syntax and semantics of
[
PCRE
](
https://www.pcre.org/original/doc/html/
)
.
The ACL match is executed only if all of the
``conditions``
succeed;
in other words, the
``conditions``
are the boolean AND of all of the
match terms.
For example, these
``conditions``
specify that the match is executed
when the URL begins with "/tea", and the Host header is exactly
"cafe.example.com":
```
conditions:
- comparand: req.url
compare: match
value: ^/tea(/|$)
- comparand: req.http.Host
value: cafe.example.com
```
for executing the match; the ACL match is executed only if all of the
``conditions``
succeed. The
``conditions``
field for ACLs has the same
syntax and semantics as specified above for Basic and Proxy
Authentication.
The
``result-header``
field specifies a client request header that is
set with a value for the "fail" or "success" results of the ACL
...
...
examples/authentication/README.md
View file @
65ab4547
...
...
@@ -69,15 +69,22 @@ from the ``coffee-creds`` Secret:
secretName: coffee-creds
type: basic
utf8: true
condition:
host-match: ^cafe\.example\.com$
url-match: ^/coffee($|/)
```
``type: basic``
specifies Basic Authentication, and the
``host-match``
and
``url-match``
fields require authentication in the "coffee" realm
when the Host is exactly equal to "cafe.example.com", and the URL path
begins with "/coffee".
conditions:
- comparand: req.http.Host
value: cafe.example.com
compare: equal
- comparand: req.url
value: ^/coffee($|/)
compare: match
```
``type: basic``
specifies Basic Authentication, and the
``conditions``
array requires authentication when a request is routed to the
coffee-svc Service. The first element of
``comparand``
specifies that
the Host header is exactly equal to "cafe.example.com", and the second
specifies that the URL path begins with "/coffee". The Basic
Authentication protocol configured here is only executed when all of
the
``conditions``
are met.
The
``utf8: true``
setting means that the field
``charset="UTF-8"``
field is appended to the
``WWW-Authenticate``
response header when
...
...
@@ -93,9 +100,13 @@ from the ``tea-creds`` Secret when the URL path begins with "/tea":
```
- realm: tea
secretName: tea-creds
condition:
host-match: ^cafe\.example\.com$
url-match: ^/tea($|/)
conditions:
- comparand: req.http.Host
value: cafe.example.com
compare: equal
- comparand: req.url
value: ^/tea($|/)
compare: match
```
Not that
``type: basic``
was left out here, since
``basic``
is the
...
...
@@ -175,9 +186,9 @@ unconditionally to all requests:
```
As with Basic Authentication, it is also possible to use the
``condition
.host-match``
and
``condition.url-match``
fields to
restrict the requests for which the authentication is required (but
Proxy Authentication typically applies
to all requests).
``condition
s``
array to restrict the requests for which the
authentication is required (but Proxy Authentication typically applies
to all requests).
To verify with curl, we use the
``-x``
(or
``--proxy``
) argument to
specify
``$ADDR:$PORT``
as the proxy, and send the request with an
...
...
examples/authentication/basic-auth.yaml
View file @
65ab4547
...
...
@@ -22,9 +22,13 @@ spec:
secretName
:
coffee-creds
type
:
basic
utf8
:
true
condition
:
host-match
:
^cafe\.example\.com$
url-match
:
^/coffee($|/)
conditions
:
-
comparand
:
req.http.Host
value
:
cafe.example.com
compare
:
equal
-
comparand
:
req.url
value
:
^/coffee($|/)
compare
:
match
# For the tea Service, require authentication for the realm "tea"
# when the Host is "cafe.example.com" and the URL path begins with
...
...
@@ -33,6 +37,10 @@ spec:
# left out.
-
realm
:
tea
secretName
:
tea-creds
condition
:
host-match
:
^cafe\.example\.com$
url-match
:
^/tea($|/)
conditions
:
-
comparand
:
req.http.Host
value
:
cafe.example.com
compare
:
equal
-
comparand
:
req.url
value
:
^/tea($|/)
compare
:
match
pkg/apis/varnishingress/v1alpha1/types.go
View file @
65ab4547
...
...
@@ -82,8 +82,8 @@ type AuthSpec struct {
Realm
string
`json:"realm"`
SecretName
string
`json:"secretName"`
Type
AuthType
`json:"type,omitempty"`
Condition
*
AuthCondition
`json:"condition,omitempty"`
UTF8
bool
`json:"utf8,omitempty"`
Conditions
[]
Condition
`json:"conditions,omitempty"`
}
// AuthType classifies the protocol for an AuthSpec.
...
...
@@ -96,14 +96,6 @@ const (
Proxy
=
"proxy"
)
// AuthCondition specifies a condition under which an authentication
// protocol must be executed -- the URL path or the Host must match a
// pattern (or both).
type
AuthCondition
struct
{
URLRegex
string
`json:"url-match,omitempty"`
HostRegex
string
`json:"host-match,omitempty"`
}
// ACLSpec specifies whitelisting or blacklisting IP addresses against
// an access control list.
type
ACLSpec
struct
{
...
...
pkg/apis/varnishingress/v1alpha1/zz_generated.deepcopy.go
View file @
65ab4547
...
...
@@ -93,29 +93,13 @@ func (in *ACLSpec) DeepCopy() *ACLSpec {
return
out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func
(
in
*
AuthCondition
)
DeepCopyInto
(
out
*
AuthCondition
)
{
*
out
=
*
in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthCondition.
func
(
in
*
AuthCondition
)
DeepCopy
()
*
AuthCondition
{
if
in
==
nil
{
return
nil
}
out
:=
new
(
AuthCondition
)
in
.
DeepCopyInto
(
out
)
return
out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func
(
in
*
AuthSpec
)
DeepCopyInto
(
out
*
AuthSpec
)
{
*
out
=
*
in
if
in
.
Condition
!=
nil
{
in
,
out
:=
&
in
.
Condition
,
&
out
.
Condition
*
out
=
new
(
AuthCondition
)
**
out
=
**
in
if
in
.
Condition
s
!=
nil
{
in
,
out
:=
&
in
.
Condition
s
,
&
out
.
Conditions
*
out
=
make
([]
Condition
,
len
(
*
in
)
)
copy
(
*
out
,
*
in
)
}
return
}
...
...
pkg/controller/ingress.go
View file @
65ab4547
...
...
@@ -326,6 +326,33 @@ func (worker *NamespaceWorker) configSharding(spec *vcl.Spec,
return
nil
}
func
configConditions
(
vclConds
[]
vcl
.
MatchTerm
,
vcfgConds
[]
vcr_v1alpha1
.
Condition
)
{
if
len
(
vclConds
)
!=
len
(
vcfgConds
)
{
panic
(
"configConditions: unequal slice lengths"
)
}
for
i
,
cond
:=
range
vcfgConds
{
vclMatch
:=
vcl
.
MatchTerm
{
Comparand
:
cond
.
Comparand
,
Value
:
cond
.
Value
,
}
switch
cond
.
Compare
{
case
vcr_v1alpha1
.
Equal
:
vclMatch
.
Compare
=
vcl
.
Equal
case
vcr_v1alpha1
.
NotEqual
:
vclMatch
.
Compare
=
vcl
.
NotEqual
case
vcr_v1alpha1
.
Match
:
vclMatch
.
Compare
=
vcl
.
Match
case
vcr_v1alpha1
.
NotMatch
:
vclMatch
.
Compare
=
vcl
.
NotMatch
default
:
vclMatch
.
Compare
=
vcl
.
Equal
}
vclConds
[
i
]
=
vclMatch
}
}
func
(
worker
*
NamespaceWorker
)
configAuth
(
spec
*
vcl
.
Spec
,
vcfg
*
vcr_v1alpha1
.
VarnishConfig
)
error
{
...
...
@@ -357,6 +384,7 @@ func (worker *NamespaceWorker) configAuth(spec *vcl.Spec,
vclAuth
:=
vcl
.
Auth
{
Realm
:
auth
.
Realm
,
Credentials
:
make
([]
string
,
0
,
len
(
secret
.
Data
)),
Conditions
:
make
([]
vcl
.
MatchTerm
,
len
(
auth
.
Conditions
)),
UTF8
:
auth
.
UTF8
,
}
if
auth
.
Type
==
""
||
auth
.
Type
==
vcr_v1alpha1
.
Basic
{
...
...
@@ -372,10 +400,7 @@ func (worker *NamespaceWorker) configAuth(spec *vcl.Spec,
vcfg
.
Name
,
cred
,
vclAuth
.
Realm
)
vclAuth
.
Credentials
=
append
(
vclAuth
.
Credentials
,
cred
)
}
if
auth
.
Condition
!=
nil
{
vclAuth
.
Condition
.
URLRegex
=
auth
.
Condition
.
URLRegex
vclAuth
.
Condition
.
HostRegex
=
auth
.
Condition
.
HostRegex
}
configConditions
(
vclAuth
.
Conditions
,
auth
.
Conditions
)
worker
.
log
.
Debugf
(
"VarnishConfig %s/%s add VCL auth config: "
+
"%+v"
,
vcfg
.
Namespace
,
vcfg
.
Name
,
vclAuth
)
spec
.
Auths
=
append
(
spec
.
Auths
,
vclAuth
)
...
...
@@ -426,23 +451,7 @@ func (worker *NamespaceWorker) configACL(spec *vcl.Spec,
}
vclACL
.
Addresses
[
j
]
=
vclAddr
}
for
j
,
cond
:=
range
acl
.
Conditions
{
vclMatch
:=
vcl
.
MatchTerm
{
Comparand
:
cond
.
Comparand
,
Value
:
cond
.
Value
,
}
switch
cond
.
Compare
{
case
vcr_v1alpha1
.
Equal
:
vclMatch
.
Compare
=
vcl
.
Equal
case
vcr_v1alpha1
.
NotEqual
:
vclMatch
.
Compare
=
vcl
.
NotEqual
case
vcr_v1alpha1
.
Match
:
vclMatch
.
Compare
=
vcl
.
Match
case
vcr_v1alpha1
.
NotMatch
:
vclMatch
.
Compare
=
vcl
.
NotMatch
}
vclACL
.
Conditions
[
j
]
=
vclMatch
}
configConditions
(
vclACL
.
Conditions
,
acl
.
Conditions
)
if
acl
.
ResultHdr
!=
nil
{
worker
.
log
.
Debugf
(
"ACL %s: ResultHdr=%+v"
,
acl
.
Name
,
*
acl
.
ResultHdr
)
...
...
pkg/varnish/vcl/auth.tmpl
View file @
65ab4547
...
...
@@ -14,11 +14,8 @@ sub vcl_init {
sub vcl_recv {
{{- range .Auths}}
if (
{{- if ne .Condition.HostRegex ""}}
req.http.Host ~ "{{.Condition.HostRegex}}" &&
{{- end}}
{{- if ne .Condition.URLRegex ""}}
req.url ~ "{{.Condition.URLRegex}}" &&
{{- range $cond := .Conditions}}
{{$cond.Comparand}} {{cmpRelation .Compare}} "{{.Value}}" &&
{{- end}}
{{- if eq .Status 401}}
!{{credsMatcher .Realm}}.match(req.http.Authorization)
...
...
pkg/varnish/vcl/spec.go
View file @
65ab4547
...
...
@@ -242,16 +242,6 @@ func (shard ShardCluster) hash(hash hash.Hash) {
hash
.
Write
([]
byte
(
shard
.
MaxSecondaryTTL
))
}
// Condition specifies conditions under which an authentication
// protocols must be executed -- the URL path or the Host must match
// patterns, the request must be received from a TLS offloader, or any
// combination of the three.
type
Condition
struct
{
URLRegex
string
HostRegex
string
TLS
bool
}
// AuthStatus is the response code to be sent for authentication
// failures, and serves to distinguish the protocols.
type
AuthStatus
uint16
...
...
@@ -266,10 +256,10 @@ const (
// Auth specifies Basic or Proxy Authentication, derived from an
// AuthSpec in a VarnishConfig resource.
type
Auth
struct
{
Realm
string
Conditions
[]
MatchTerm
Credentials
[]
string
Realm
string
Status
AuthStatus
Condition
Condition
UTF8
bool
}
...
...
@@ -281,10 +271,8 @@ func (auth Auth) hash(hash hash.Hash) {
statusBytes
:=
make
([]
byte
,
2
)
binary
.
BigEndian
.
PutUint16
(
statusBytes
,
uint16
(
auth
.
Status
))
hash
.
Write
(
statusBytes
)
hash
.
Write
([]
byte
(
auth
.
Condition
.
URLRegex
))
hash
.
Write
([]
byte
(
auth
.
Condition
.
HostRegex
))
if
auth
.
Condition
.
TLS
{
hash
.
Write
([]
byte
(
"TLS"
))
for
_
,
cond
:=
range
auth
.
Conditions
{
cond
.
hash
(
hash
)
}
if
auth
.
UTF8
{
hash
.
Write
([]
byte
(
"UTF8"
))
...
...
pkg/varnish/vcl/testdata/auth.golden
View file @
65ab4547
...
...
@@ -42,7 +42,7 @@ sub vcl_recv {
return(synth(60000 + 407));
}
if (
req.http.Host
~ "^baz\.com$
" &&
req.http.Host
== "baz.com
" &&
!vk8s_baz_auth.match(req.http.Authorization)
) {
set req.http.VK8S-Authenticate =
...
...
@@ -58,7 +58,7 @@ sub vcl_recv {
return(synth(60000 + 407));
}
if (
req.http.Host
~ "^url\.regex\.org$
" &&
req.http.Host
== "url.regex.org
" &&
req.url ~ "^/secret/path" &&
!vk8s_urlhost_auth.match(req.http.Authorization)
) {
...
...
pkg/varnish/vcl/vcl_test.go
View file @
65ab4547
...
...
@@ -244,9 +244,11 @@ var auths = Spec{
"dXNlcjpwYXNzd29yZDE="
,
"bmFtZTpzZWNyZXQ="
,
},
Condition
:
Condition
{
HostRegex
:
`^baz\.com$`
,
},
Conditions
:
[]
MatchTerm
{{
Comparand
:
"req.http.Host"
,
Value
:
`baz.com`
,
Compare
:
Equal
,
}},
UTF8
:
true
,
},
{
...
...
@@ -256,9 +258,11 @@ var auths = Spec{
"YmVudXR6ZXI6Z2VoZWlt"
,
"QWxiZXJ0IEFkZGluOm9wZW4gc2V6IG1l"
,
},
Condition
:
Condition
{
URLRegex
:
"^/baz/quux"
,
},
Conditions
:
[]
MatchTerm
{{
Comparand
:
"req.url"
,
Value
:
"^/baz/quux"
,
Compare
:
Match
,
}},
UTF8
:
true
,
},
{
...
...
@@ -268,9 +272,17 @@ var auths = Spec{
"dXJsOmhvc3Q="
,
"YWRtaW46c3VwZXJwb3dlcnM="
,
},
Condition
:
Condition
{
HostRegex
:
`^url\.regex\.org$`
,
URLRegex
:
"^/secret/path"
,
Conditions
:
[]
MatchTerm
{
{
Comparand
:
"req.http.Host"
,
Value
:
"url.regex.org"
,
Compare
:
Equal
,
},
{
Comparand
:
"req.url"
,
Value
:
"^/secret/path"
,
Compare
:
Match
,
},
},
},
},
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment