Auth middlewares in kubernetes CRD uses secrets

This commit is contained in:
Julien Salleyron 2019-09-05 13:42:04 +02:00 committed by Traefiker Bot
parent 6712423dd1
commit 1959e1fd44
11 changed files with 1306 additions and 124 deletions

View file

@ -16,7 +16,7 @@ The BasicAuth middleware is a quick way to restrict access to your services to k
# To create user:password pair, it's possible to use this command: # To create user:password pair, it's possible to use this command:
# echo $(htpasswd -nb user password) | sed -e s/\\$/\\$\\$/g # echo $(htpasswd -nb user password) | sed -e s/\\$/\\$\\$/g
labels: labels:
- "traefik.http.middlewares.test-auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0" - "traefik.http.middlewares.test-auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0"
``` ```
```yaml tab="Kubernetes" ```yaml tab="Kubernetes"
@ -27,9 +27,7 @@ metadata:
name: test-auth name: test-auth
spec: spec:
basicAuth: basicAuth:
users: secret: secretName
- test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/
- test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0
``` ```
```json tab="Marathon" ```json tab="Marathon"
@ -41,7 +39,7 @@ spec:
```yaml tab="Rancher" ```yaml tab="Rancher"
# Declaring the user list # Declaring the user list
labels: labels:
- "traefik.http.middlewares.test-auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0" - "traefik.http.middlewares.test-auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"
``` ```
```toml tab="File (TOML)" ```toml tab="File (TOML)"
@ -79,12 +77,140 @@ Passwords must be encoded using MD5, SHA1, or BCrypt.
The `users` option is an array of authorized users. Each user will be declared using the `name:encoded-password` format. The `users` option is an array of authorized users. Each user will be declared using the `name:encoded-password` format.
!!! Note
- If both `users` and `usersFile` are provided, the two are merged. The contents of `usersFile` have precedence over the values in `users`.
- For security reasons, the field `users` doesn't exist for Kubernetes IngressRoute, and one should use the `secret` field instead.
```yaml tab="Docker"
# Declaring the user list
#
# Note: all dollar signs in the hash need to be doubled for escaping.
# To create user:password pair, it's possible to use this command:
# echo $(htpasswd -nb user password) | sed -e s/\\$/\\$\\$/g
labels:
- "traefik.http.middlewares.test-auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0"
```
```yaml tab="Kubernetes"
# Declaring the user list
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-auth
spec:
basicAuth:
secret: authsecret
---
apiVersion: v1
kind: Secret
metadata:
name: authsecret
namespace: default
data:
users: |2
dGVzdDokYXByMSRINnVza2trVyRJZ1hMUDZld1RyU3VCa1RycUU4d2ovCnRlc3QyOiRhcHIxJGQ5
aHI5SEJCJDRIeHdnVWlyM0hQNEVzZ2dQL1FObzAK
```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.basicauth.users": "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"
}
```
```yaml tab="Rancher"
# Declaring the user list
labels:
- "traefik.http.middlewares.test-auth.basicauth.users=test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/,test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"
```
```toml tab="File (TOML)"
# Declaring the user list
[http.middlewares]
[http.middlewares.test-auth.basicAuth]
users = [
"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/",
"test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0",
]
```
```yaml tab="File (YAML)"
# Declaring the user list
http:
middlewares:
test-auth:
basicAuth:
users:
- "test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"
- "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"
```
### `usersFile` ### `usersFile`
The `usersFile` option is the path to an external file that contains the authorized users for the middleware. The `usersFile` option is the path to an external file that contains the authorized users for the middleware.
The file content is a list of `name:encoded-password`. The file content is a list of `name:encoded-password`.
!!! Note
- If both `users` and `usersFile` are provided, the two are merged. The contents of `usersFile` have precedence over the values in `users`.
- Because it does not make much sense to refer to a file path on Kubernetes, the `usersFile` field doesn't exist for Kubernetes IngressRoute, and one should use the `secret` field instead.
```yaml tab="Docker"
labels:
- "traefik.http.middlewares.test-auth.basicauth.usersfile=/path/to/my/usersfile"
```
```yaml tab="Kubernetes"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-auth
spec:
basicAuth:
secret: authsecret
---
apiVersion: v1
kind: Secret
metadata:
name: authsecret
namespace: default
data:
users: |2
dGVzdDokYXByMSRINnVza2trVyRJZ1hMUDZld1RyU3VCa1RycUU4d2ovCnRlc3QyOiRhcHIxJGQ5
aHI5SEJCJDRIeHdnVWlyM0hQNEVzZ2dQL1FObzAK
```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.basicauth.usersfile": "/path/to/my/usersfile"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.basicauth.usersfile=/path/to/my/usersfile"
```
```toml tab="File (TOML)"
[http.middlewares]
[http.middlewares.test-auth.basicAuth]
usersFile = "/path/to/my/usersfile"
```
```yaml tab="File (YAML)"
http:
middlewares:
test-auth:
basicAuth:
usersFile: "/path/to/my/usersfile"
```
??? example "A file containing test/test and test2/test2" ??? example "A file containing test/test and test2/test2"
```txt ```txt
@ -92,21 +218,57 @@ The file content is a list of `name:encoded-password`.
test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0 test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0
``` ```
!!! Note
If both `users` and `usersFile` are provided, the two are merged. The content of `usersFile` has precedence over `users`.
### `realm` ### `realm`
You can customize the realm for the authentication with the `realm` option. The default value is `traefik`. You can customize the realm for the authentication with the `realm` option. The default value is `traefik`.
```yaml tab="Docker"
labels:
- "traefik.http.middlewares.test-auth.basicauth.realm=MyRealm"
```
```yaml tab="Kubernetes"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-auth
spec:
basicAuth:
realm: MyRealm
```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.basicauth.realm": "MyRealm"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.basicauth.realm=MyRealm"
```
```toml tab="File (TOML)"
[http.middlewares]
[http.middlewares.test-auth.basicAuth]
realm = "MyRealm"
```
```yaml tab="File (YAML)"
http:
middlewares:
test-auth:
basicAuth:
realm: "MyRealm"
```
### `headerField` ### `headerField`
You can define a header field to store the authenticated user using the `headerField`option. You can define a header field to store the authenticated user using the `headerField`option.
```yaml tab="Docker" ```yaml tab="Docker"
labels: labels:
- "traefik.http.middlewares.my-auth.basicauth.headerField=X-WebAuth-User" - "traefik.http.middlewares.my-auth.basicauth.headerField=X-WebAuth-User"
``` ```
```yaml tab="Kubernetes" ```yaml tab="Kubernetes"
@ -144,3 +306,43 @@ http:
### `removeHeader` ### `removeHeader`
Set the `removeHeader` option to `true` to remove the authorization header before forwarding the request to your service. (Default value is `false`.) Set the `removeHeader` option to `true` to remove the authorization header before forwarding the request to your service. (Default value is `false`.)
```yaml tab="Docker"
labels:
- "traefik.http.middlewares.test-auth.basicauth.removeheader=true"
```
```yaml tab="Kubernetes"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-auth
spec:
basicAuth:
removeHeader: true
```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.basicauth.removeheader": "true"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.basicauth.removeheader=true"
```
```toml tab="File (TOML)"
[http.middlewares]
[http.middlewares.test-auth.basicAuth]
removeHeader = true
```
```yaml tab="File (YAML)"
http:
middlewares:
test-auth:
basicAuth:
removeHeader: true
```

View file

@ -10,6 +10,7 @@ The DigestAuth middleware is a quick way to restrict access to your services to
## Configuration Examples ## Configuration Examples
```yaml tab="Docker" ```yaml tab="Docker"
# Declaring the user list
labels: labels:
- "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e" - "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e"
``` ```
@ -21,10 +22,83 @@ kind: Middleware
metadata: metadata:
name: test-auth name: test-auth
spec: spec:
digestAuth:
secret: userssecret
```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.digestauth.users": "test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e"
}
```
```yaml tab="Rancher"
# Declaring the user list
labels:
- "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e"
```
```toml tab="File (TOML)"
# Declaring the user list
[http.middlewares]
[http.middlewares.test-auth.digestAuth]
users = [
"test:traefik:a2688e031edb4be6a3797f3882655c05",
"test2:traefik:518845800f9e2bfb1f1f740ec24f074e",
]
```
```yaml tab="File (YAML)"
# Declaring the user list
http:
middlewares:
test-auth:
digestAuth: digestAuth:
users: users:
- test:traefik:a2688e031edb4be6a3797f3882655c05 - "test:traefik:a2688e031edb4be6a3797f3882655c05"
- test2:traefik:518845800f9e2bfb1f1f740ec24f074e - "test2:traefik:518845800f9e2bfb1f1f740ec24f074e"
```
## Configuration Options
!!! tip
Use `htdigest` to generate passwords.
### `users`
The `users` option is an array of authorized users. Each user will be declared using the `name:realm:encoded-password` format.
!!! Note
- If both `users` and `usersFile` are provided, the two are merged. The contents of `usersFile` have precedence over the values in `users`.
- For security reasons, the field `users` doesn't exist for Kubernetes IngressRoute, and one should use the `secret` field instead.
```yaml tab="Docker"
labels:
- "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e"
```
```yaml tab="Kubernetes"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-auth
spec:
digestAuth:
secret: authsecret
---
apiVersion: v1
kind: Secret
metadata:
name: authsecret
namespace: default
data:
users: |2
dGVzdDokYXByMSRINnVza2trVyRJZ1hMUDZld1RyU3VCa1RycUU4d2ovCnRlc3QyOiRhcHIxJGQ5
aHI5SEJCJDRIeHdnVWlyM0hQNEVzZ2dQL1FObzAK
``` ```
```json tab="Marathon" ```json tab="Marathon"
@ -57,26 +131,69 @@ http:
- "test2:traefik:518845800f9e2bfb1f1f740ec24f074e" - "test2:traefik:518845800f9e2bfb1f1f740ec24f074e"
``` ```
!!! tip
Use `htdigest` to generate passwords.
## Configuration Options
### `users`
The `users` option is an array of authorized users. Each user will be declared using the `name:realm:encoded-password` format.
!!! Note
If both `users` and `usersFile` are provided, the two are merged. The content of `usersFile` has precedence over `users`.
### `usersFile` ### `usersFile`
The `usersFile` option is the path to an external file that contains the authorized users for the middleware. The `usersFile` option is the path to an external file that contains the authorized users for the middleware.
The file content is a list of `name:realm:encoded-password`. The file content is a list of `name:realm:encoded-password`.
!!! Note
- If both `users` and `usersFile` are provided, the two are merged. The contents of `usersFile` have precedence over the values in `users`.
- Because it does not make much sense to refer to a file path on Kubernetes, the `usersFile` field doesn't exist for Kubernetes IngressRoute, and one should use the `secret` field instead.
```yaml tab="Docker"
labels:
- "traefik.http.middlewares.test-auth.digestauth.usersfile=/path/to/my/usersfile"
```
```yaml tab="Kubernetes"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-auth
spec:
digestAuth:
secret: authsecret
---
apiVersion: v1
kind: Secret
metadata:
name: authsecret
namespace: default
data:
users: |2
dGVzdDokYXByMSRINnVza2trVyRJZ1hMUDZld1RyU3VCa1RycUU4d2ovCnRlc3QyOiRhcHIxJGQ5
aHI5SEJCJDRIeHdnVWlyM0hQNEVzZ2dQL1FObzAK
```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.digestauth.usersfile": "/path/to/my/usersfile"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.digestauth.usersfile=/path/to/my/usersfile"
```
```toml tab="File (TOML)"
[http.middlewares]
[http.middlewares.test-auth.digestAuth]
usersFile = "/path/to/my/usersfile"
```
```yaml tab="File (YAML)"
http:
middlewares:
test-auth:
digestAuth:
usersFile: "/path/to/my/usersfile"
```
??? example "A file containing test/test and test2/test2" ??? example "A file containing test/test and test2/test2"
```txt ```txt
@ -84,20 +201,54 @@ The file content is a list of `name:realm:encoded-password`.
test2:traefik:518845800f9e2bfb1f1f740ec24f074e test2:traefik:518845800f9e2bfb1f1f740ec24f074e
``` ```
!!! Note
If both `users` and `usersFile` are provided, the two are merged. The content of `usersFile` has precedence over `users`.
### `realm` ### `realm`
You can customize the realm for the authentication with the `realm` option. The default value is `traefik`. You can customize the realm for the authentication with the `realm` option. The default value is `traefik`.
```yaml tab="Docker"
labels:
- "traefik.http.middlewares.test-auth.digestauth.realm=MyRealm"
```
```yaml tab="Kubernetes"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-auth
spec:
digestAuth:
realm: MyRealm
```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.digestauth.realm": "MyRealm"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.digestauth.realm=MyRealm"
```
```toml tab="File (TOML)"
[http.middlewares]
[http.middlewares.test-auth.digestAuth]
realm = "MyRealm"
```
```yaml tab="File (YAML)"
http:
middlewares:
test-auth:
digestAuth:
realm: "MyRealm"
```
### `headerField` ### `headerField`
You can customize the header field for the authenticated user using the `headerField`option. You can customize the header field for the authenticated user using the `headerField`option.
Example "File -- Passing Authenticated User to Services Via Headers"
```yaml tab="Docker" ```yaml tab="Docker"
labels: labels:
- "traefik.http.middlewares.my-auth.digestauth.headerField=X-WebAuth-User" - "traefik.http.middlewares.my-auth.digestauth.headerField=X-WebAuth-User"
@ -143,3 +294,43 @@ http:
### `removeHeader` ### `removeHeader`
Set the `removeHeader` option to `true` to remove the authorization header before forwarding the request to your service. (Default value is `false`.) Set the `removeHeader` option to `true` to remove the authorization header before forwarding the request to your service. (Default value is `false`.)
```yaml tab="Docker"
labels:
- "traefik.http.middlewares.test-auth.digestauth.removeheader=true"
```
```yaml tab="Kubernetes"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-auth
spec:
digestAuth:
removeHeader: true
```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.digestauth.removeheader": "true"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.digestauth.removeheader=true"
```
```toml tab="File (TOML)"
[http.middlewares]
[http.middlewares.test-auth.digestAuth]
removeHeader = true
```
```yaml tab="File (YAML)"
http:
middlewares:
test-auth:
digestAuth:
removeHeader: true
```

View file

@ -15,12 +15,99 @@ Otherwise, the response from the authentication server is returned.
# Forward authentication to authserver.com # Forward authentication to authserver.com
labels: labels:
- "traefik.http.middlewares.test-auth.forwardauth.address=https://authserver.com/auth" - "traefik.http.middlewares.test-auth.forwardauth.address=https://authserver.com/auth"
- "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders=X-Auth-User, X-Secret" ```
- "traefik.http.middlewares.test-auth.forwardauth.tls.ca=path/to/local.crt"
- "traefik.http.middlewares.test-auth.forwardauth.tls.caOptional=true" ```yaml tab="Kubernetes"
- "traefik.http.middlewares.test-auth.forwardauth.tls.cert=path/to/foo.cert" # Forward authentication to authserver.com
- "traefik.http.middlewares.test-auth.forwardauth.tls.insecureSkipVerify=true" apiVersion: traefik.containo.us/v1alpha1
- "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key" kind: Middleware
metadata:
name: test-auth
spec:
forwardAuth:
address: https://authserver.com/auth
```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.forwardauth.address": "https://authserver.com/auth"
}
```
```yaml tab="Rancher"
# Forward authentication to authserver.com
labels:
- "traefik.http.middlewares.test-auth.forwardauth.address=https://authserver.com/auth"
```
```toml tab="File (TOML)"
# Forward authentication to authserver.com
[http.middlewares]
[http.middlewares.test-auth.forwardAuth]
address = "https://authserver.com/auth"
```
```yaml tab="File (YAML)"
# Forward authentication to authserver.com
http:
middlewares:
test-auth:
forwardAuth:
address: "https://authserver.com/auth"
```
## Configuration Options
### `address`
The `address` option defines the authentication server address.
```yaml tab="Docker"
labels:
- "traefik.http.middlewares.test-auth.forwardauth.address=https://authserver.com/auth"
```
```yaml tab="Kubernetes"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-auth
spec:
forwardAuth:
address: https://authserver.com/auth
```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.forwardauth.address": "https://authserver.com/auth"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.forwardauth.address=https://authserver.com/auth"
```
```toml tab="File (TOML)"
[http.middlewares]
[http.middlewares.test-auth.forwardAuth]
address = "https://authserver.com/auth"
```
```yaml tab="File (YAML)"
http:
middlewares:
test-auth:
forwardAuth:
address: "https://authserver.com/auth"
```
### `trustForwardHeader`
Set the `trustForwardHeader` option to `true` to trust all the existing `X-Forwarded-*` headers.
```yaml tab="Docker"
labels:
- "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader=true" - "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader=true"
``` ```
@ -33,89 +120,381 @@ spec:
forwardAuth: forwardAuth:
address: https://authserver.com/auth address: https://authserver.com/auth
trustForwardHeader: true trustForwardHeader: true
authResponseHeaders:
- X-Auth-User
- X-Secret
tls:
ca: path/to/local.crt
caOptional: true
cert: path/to/foo.cert
key: path/to/foo.key
``` ```
```json tab="Marathon" ```json tab="Marathon"
"labels": { "labels": {
"traefik.http.middlewares.test-auth.forwardauth.address": "https://authserver.com/auth",
"traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders": "X-Auth-User,X-Secret",
"traefik.http.middlewares.test-auth.forwardauth.tls.ca": "path/to/local.crt",
"traefik.http.middlewares.test-auth.forwardauth.tls.caOptional": "true",
"traefik.http.middlewares.test-auth.forwardauth.tls.cert": "path/to/foo.cert",
"traefik.http.middlewares.test-auth.forwardauth.tls.insecureSkipVerify": "true",
"traefik.http.middlewares.test-auth.forwardauth.tls.key": "path/to/foo.key",
"traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader": "true" "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader": "true"
} }
``` ```
```yaml tab="Rancher" ```yaml tab="Rancher"
# Forward authentication to authserver.com
labels: labels:
- "traefik.http.middlewares.test-auth.forwardauth.address=https://authserver.com/auth"
- "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders=X-Auth-User, X-Secret"
- "traefik.http.middlewares.test-auth.forwardauth.tls.ca=path/to/local.crt"
- "traefik.http.middlewares.test-auth.forwardauth.tls.caOptional=true"
- "traefik.http.middlewares.test-auth.forwardauth.tls.cert=path/to/foo.cert"
- "traefik.http.middlewares.test-auth.forwardauth.tls.InisecureSkipVerify=true"
- "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key"
- "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader=true" - "traefik.http.middlewares.test-auth.forwardauth.trustForwardHeader=true"
``` ```
```toml tab="File (TOML)" ```toml tab="File (TOML)"
# Forward authentication to authserver.com
[http.middlewares] [http.middlewares]
[http.middlewares.test-auth.forwardAuth] [http.middlewares.test-auth.forwardAuth]
address = "https://authserver.com/auth" address = "https://authserver.com/auth"
trustForwardHeader = true trustForwardHeader = true
authResponseHeaders = ["X-Auth-User", "X-Secret"]
[http.middlewares.test-auth.forwardAuth.tls]
ca = "path/to/local.crt"
caOptional = true
cert = "path/to/foo.cert"
key = "path/to/foo.key"
``` ```
```yaml tab="File (YAML)" ```yaml tab="File (YAML)"
# Forward authentication to authserver.com
http: http:
middlewares: middlewares:
test-auth: test-auth:
forwardAuth: forwardAuth:
address: "https://authserver.com/auth" address: "https://authserver.com/auth"
trustForwardHeader: true trustForwardHeader: true
authResponseHeaders:
- "X-Auth-User"
- "X-Secret"
tls:
ca: "path/to/local.crt"
caOptional: true
cert: "path/to/foo.cert"
key: "path/to/foo.key"
``` ```
## Configuration Options
### `address`
The `address` option defines the authentication server address.
### `trustForwardHeader`
Set the `trustForwardHeader` option to `true` to trust all the existing `X-Forwarded-*` headers.
### `authResponseHeaders` ### `authResponseHeaders`
The `authResponseHeaders` option is the list of the headers to copy from the authentication server to the request. The `authResponseHeaders` option is the list of the headers to copy from the authentication server to the request.
```yaml tab="Docker"
labels:
- "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders=X-Auth-User, X-Secret"
```
```yaml tab="Kubernetes"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-auth
spec:
forwardAuth:
address: https://authserver.com/auth
authResponseHeaders:
- X-Auth-User
- X-Secret
```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders": "X-Auth-User,X-Secret"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.forwardauth.authResponseHeaders=X-Auth-User, X-Secret"
```
```toml tab="File (TOML)"
[http.middlewares]
[http.middlewares.test-auth.forwardAuth]
address = "https://authserver.com/auth"
authResponseHeaders = ["X-Auth-User", "X-Secret"]
```
```yaml tab="File (YAML)"
http:
middlewares:
test-auth:
forwardAuth:
address: "https://authserver.com/auth"
authResponseHeaders:
- "X-Auth-User"
- "X-Secret"
```
### `tls` ### `tls`
The `tls` option is the TLS configuration from Traefik to the authentication server. The `tls` option is the TLS configuration from Traefik to the authentication server.
#### `tls.ca`
TODO
```yaml tab="Docker"
labels:
- "traefik.http.middlewares.test-auth.forwardauth.tls.ca=path/to/local.crt"
```
```yaml tab="Kubernetes"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-auth
spec:
forwardAuth:
address: https://authserver.com/auth
tls:
caSecret: mycasercret
---
apiVersion: v1
kind: Secret
metadata:
name: mycasercret
namespace: default
data:
ca: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0=
```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.forwardauth.tls.ca": "path/to/local.crt"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.forwardauth.tls.ca=path/to/local.crt"
```
```toml tab="File (TOML)"
[http.middlewares]
[http.middlewares.test-auth.forwardAuth]
address = "https://authserver.com/auth"
[http.middlewares.test-auth.forwardAuth.tls]
ca = "path/to/local.crt"
```
```yaml tab="File (YAML)"
http:
middlewares:
test-auth:
forwardAuth:
address: "https://authserver.com/auth"
tls:
ca: "path/to/local.crt"
```
#### `tls.caOptional`
TODO
```yaml tab="Docker"
labels:
- "traefik.http.middlewares.test-auth.forwardauth.tls.caOptional=true"
```
```yaml tab="Kubernetes"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-auth
spec:
forwardAuth:
address: https://authserver.com/auth
tls:
caOptional: true
```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.forwardauth.tls.caOptional": "true"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.forwardauth.tls.caOptional=true"
```
```toml tab="File (TOML)"
[http.middlewares]
[http.middlewares.test-auth.forwardAuth]
address = "https://authserver.com/auth"
[http.middlewares.test-auth.forwardAuth.tls]
caOptional = true
```
```yaml tab="File (YAML)"
http:
middlewares:
test-auth:
forwardAuth:
address: "https://authserver.com/auth"
tls:
caOptional: true
```
#### `tls.cert`
TODO
```yaml tab="Docker"
labels:
- "traefik.http.middlewares.test-auth.forwardauth.tls.cert=path/to/foo.cert"
- "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key"
```
```yaml tab="Kubernetes"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-auth
spec:
forwardAuth:
address: https://authserver.com/auth
tls:
certSecret: mytlscert
---
apiVersion: v1
kind: Secret
metadata:
name: mytlscert
namespace: default
data:
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0=
tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0=
```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.forwardauth.tls.cert": "path/to/foo.cert",
"traefik.http.middlewares.test-auth.forwardauth.tls.key": "path/to/foo.key"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.forwardauth.tls.cert=path/to/foo.cert"
- "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key"
```
```toml tab="File (TOML)"
[http.middlewares]
[http.middlewares.test-auth.forwardAuth]
address = "https://authserver.com/auth"
[http.middlewares.test-auth.forwardAuth.tls]
cert = "path/to/foo.cert"
key = "path/to/foo.key"
```
```yaml tab="File (YAML)"
http:
middlewares:
test-auth:
forwardAuth:
address: "https://authserver.com/auth"
tls:
cert: "path/to/foo.cert"
key: "path/to/foo.key"
```
!!! Note
For security reasons, the field doesn't exist for Kubernetes IngressRoute, and one should use the `secret` field instead.
#### `tls.key`
TODO
```yaml tab="Docker"
labels:
- "traefik.http.middlewares.test-auth.forwardauth.tls.cert=path/to/foo.cert"
- "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key"
```
```yaml tab="Kubernetes"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-auth
spec:
forwardAuth:
address: https://authserver.com/auth
tls:
certSecret: mytlscert
---
apiVersion: v1
kind: Secret
metadata:
name: mytlscert
namespace: default
data:
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0=
tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0=
```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.forwardauth.tls.cert": "path/to/foo.cert",
"traefik.http.middlewares.test-auth.forwardauth.tls.key": "path/to/foo.key"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.forwardauth.tls.cert=path/to/foo.cert"
- "traefik.http.middlewares.test-auth.forwardauth.tls.key=path/to/foo.key"
```
```toml tab="File (TOML)"
[http.middlewares]
[http.middlewares.test-auth.forwardAuth]
address = "https://authserver.com/auth"
[http.middlewares.test-auth.forwardAuth.tls]
cert = "path/to/foo.cert"
key = "path/to/foo.key"
```
```yaml tab="File (YAML)"
http:
middlewares:
test-auth:
forwardAuth:
address: "https://authserver.com/auth"
tls:
cert: "path/to/foo.cert"
key: "path/to/foo.key"
```
!!! Note
For security reasons, the field doesn't exist for Kubernetes IngressRoute, and one should use the `secret` field instead.
#### `tls.insecureSkipVerify`
TODO
```yaml tab="Docker"
labels:
- "traefik.http.middlewares.test-auth.forwardauth.tls.insecureSkipVerify=true"
```
```yaml tab="Kubernetes"
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: test-auth
spec:
forwardAuth:
address: https://authserver.com/auth
insecureSkipVerify: true
```
```json tab="Marathon"
"labels": {
"traefik.http.middlewares.test-auth.forwardauth.tls.insecureSkipVerify": "true"
}
```
```yaml tab="Rancher"
labels:
- "traefik.http.middlewares.test-auth.forwardauth.tls.InsecureSkipVerify=true"
```
```toml tab="File (TOML)"
[http.middlewares]
[http.middlewares.test-auth.forwardAuth]
address = "https://authserver.com/auth"
insecureSkipVerify: true
```
```yaml tab="File (YAML)"
http:
middlewares:
test-auth:
forwardAuth:
address: "https://authserver.com/auth"
insecureSkipVerify: true
```

View file

@ -157,9 +157,9 @@ accessLog:
headers: headers:
defaultMode: keep defaultMode: keep
names: names:
- User-Agent: redact User-Agent: redact
- Authorization: drop Authorization: drop
- Content-Type: keep Content-Type: keep
``` ```
```bash tab="CLI" ```bash tab="CLI"

View file

@ -24,7 +24,7 @@ type buffer struct {
func New(ctx context.Context, next http.Handler, config dynamic.Buffering, name string) (http.Handler, error) { func New(ctx context.Context, next http.Handler, config dynamic.Buffering, name string) (http.Handler, error) {
logger := middlewares.GetLogger(ctx, name, typeName) logger := middlewares.GetLogger(ctx, name, typeName)
logger.Debug("Creating middleware") logger.Debug("Creating middleware")
logger.Debug("Setting up buffering: request limits: %d (mem), %d (max), response limits: %d (mem), %d (max) with retry: '%s'", logger.Debugf("Setting up buffering: request limits: %d (mem), %d (max), response limits: %d (mem), %d (max) with retry: '%s'",
config.MemRequestBodyBytes, config.MaxRequestBodyBytes, config.MemResponseBodyBytes, config.MaxResponseBodyBytes, config.RetryExpression) config.MemRequestBodyBytes, config.MaxRequestBodyBytes, config.MemResponseBodyBytes, config.MaxResponseBodyBytes, config.RetryExpression)
oxyBuffer, err := oxybuffer.New( oxyBuffer, err := oxybuffer.New(

View file

@ -0,0 +1,65 @@
apiVersion: v1
kind: Secret
metadata:
name: authsecret
namespace: default
data:
users: |2
dGVzdDokYXByMSRINnVza2trVyRJZ1hMUDZld1RyU3VCa1RycUU4d2ovCnRlc3QyOiRhcHIxJGQ5
aHI5SEJCJDRIeHdnVWlyM0hQNEVzZ2dQL1FObzAK
---
apiVersion: v1
kind: Secret
metadata:
name: casecret
namespace: default
data:
ca: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0=
---
apiVersion: v1
kind: Secret
metadata:
name: tlssecret
namespace: default
data:
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0=
tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0=
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: basicauth
namespace: default
spec:
basicAuth:
secret: authsecret
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: digestauth
namespace: default
spec:
digestAuth:
secret: authsecret
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: forwardauth
namespace: default
spec:
forwardAuth:
address: test.com
tls:
certSecret: tlssecret
caSecret: casecret

View file

@ -1,6 +1,8 @@
package crd package crd
import ( import (
"bufio"
"bytes"
"context" "context"
"crypto/sha256" "crypto/sha256"
"fmt" "fmt"
@ -149,6 +151,25 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client)
for _, middleware := range client.GetMiddlewares() { for _, middleware := range client.GetMiddlewares() {
id := makeID(middleware.Namespace, middleware.Name) id := makeID(middleware.Namespace, middleware.Name)
ctxMid := log.With(ctx, log.Str(log.MiddlewareName, id)) ctxMid := log.With(ctx, log.Str(log.MiddlewareName, id))
basicAuth, err := createBasicAuthMiddleware(client, middleware.Namespace, middleware.Spec.BasicAuth)
if err != nil {
log.FromContext(ctxMid).Errorf("Error while reading basic auth middleware: %v", err)
continue
}
digestAuth, err := createDigestAuthMiddleware(client, middleware.Namespace, middleware.Spec.DigestAuth)
if err != nil {
log.FromContext(ctxMid).Errorf("Error while reading digest auth middleware: %v", err)
continue
}
forwardAuth, err := createForwardAuthMiddleware(client, middleware.Namespace, middleware.Spec.ForwardAuth)
if err != nil {
log.FromContext(ctxMid).Errorf("Error while reading forward auth middleware: %v", err)
continue
}
conf.HTTP.Middlewares[id] = &dynamic.Middleware{ conf.HTTP.Middlewares[id] = &dynamic.Middleware{
AddPrefix: middleware.Spec.AddPrefix, AddPrefix: middleware.Spec.AddPrefix,
StripPrefix: middleware.Spec.StripPrefix, StripPrefix: middleware.Spec.StripPrefix,
@ -162,9 +183,9 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client)
RateLimit: middleware.Spec.RateLimit, RateLimit: middleware.Spec.RateLimit,
RedirectRegex: middleware.Spec.RedirectRegex, RedirectRegex: middleware.Spec.RedirectRegex,
RedirectScheme: middleware.Spec.RedirectScheme, RedirectScheme: middleware.Spec.RedirectScheme,
BasicAuth: middleware.Spec.BasicAuth, BasicAuth: basicAuth,
DigestAuth: middleware.Spec.DigestAuth, DigestAuth: digestAuth,
ForwardAuth: middleware.Spec.ForwardAuth, ForwardAuth: forwardAuth,
InFlightReq: middleware.Spec.InFlightReq, InFlightReq: middleware.Spec.InFlightReq,
Buffering: middleware.Spec.Buffering, Buffering: middleware.Spec.Buffering,
CircuitBreaker: middleware.Spec.CircuitBreaker, CircuitBreaker: middleware.Spec.CircuitBreaker,
@ -178,6 +199,175 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client)
return conf return conf
} }
func createForwardAuthMiddleware(k8sClient Client, namespace string, auth *v1alpha1.ForwardAuth) (*dynamic.ForwardAuth, error) {
if auth == nil {
return nil, nil
}
if len(auth.Address) == 0 {
return nil, fmt.Errorf("forward authentication requires an address")
}
forwardAuth := &dynamic.ForwardAuth{
Address: auth.Address,
TrustForwardHeader: auth.TrustForwardHeader,
AuthResponseHeaders: auth.AuthResponseHeaders,
}
if auth.TLS == nil {
return forwardAuth, nil
}
forwardAuth.TLS = &dynamic.ClientTLS{
CAOptional: auth.TLS.CAOptional,
InsecureSkipVerify: auth.TLS.InsecureSkipVerify,
}
if len(auth.TLS.CASecret) > 0 {
caSecret, err := loadCASecret(namespace, auth.TLS.CASecret, k8sClient)
if err != nil {
return nil, fmt.Errorf("failed to load auth ca secret: %v", err)
}
forwardAuth.TLS.CA = caSecret
}
if len(auth.TLS.CertSecret) > 0 {
authSecretCert, authSecretKey, err := loadAuthTLSSecret(namespace, auth.TLS.CertSecret, k8sClient)
if err != nil {
return nil, fmt.Errorf("failed to load auth secret: %s", err)
}
forwardAuth.TLS.Cert = authSecretCert
forwardAuth.TLS.Key = authSecretKey
}
return forwardAuth, nil
}
func loadCASecret(namespace, secretName string, k8sClient Client) (string, error) {
secret, ok, err := k8sClient.GetSecret(namespace, secretName)
if err != nil {
return "", fmt.Errorf("failed to fetch secret '%s/%s': %s", namespace, secretName, err)
}
if !ok {
return "", fmt.Errorf("secret '%s/%s' not found", namespace, secretName)
}
if secret == nil {
return "", fmt.Errorf("data for secret '%s/%s' must not be nil", namespace, secretName)
}
if len(secret.Data) != 1 {
return "", fmt.Errorf("found %d elements for secret '%s/%s', must be single element exactly", len(secret.Data), namespace, secretName)
}
for _, v := range secret.Data {
return string(v), nil
}
return "", nil
}
func loadAuthTLSSecret(namespace, secretName string, k8sClient Client) (string, string, error) {
secret, exists, err := k8sClient.GetSecret(namespace, secretName)
if err != nil {
return "", "", fmt.Errorf("failed to fetch secret '%s/%s': %s", namespace, secretName, err)
}
if !exists {
return "", "", fmt.Errorf("secret '%s/%s' does not exist", namespace, secretName)
}
if secret == nil {
return "", "", fmt.Errorf("data for secret '%s/%s' must not be nil", namespace, secretName)
}
if len(secret.Data) != 2 {
return "", "", fmt.Errorf("found %d elements for secret '%s/%s', must be two elements exactly", len(secret.Data), namespace, secretName)
}
return getCertificateBlocks(secret, namespace, secretName)
}
func createBasicAuthMiddleware(client Client, namespace string, basicAuth *v1alpha1.BasicAuth) (*dynamic.BasicAuth, error) {
if basicAuth == nil {
return nil, nil
}
credentials, err := getAuthCredentials(client, basicAuth.Secret, namespace)
if err != nil {
return nil, err
}
return &dynamic.BasicAuth{
Users: credentials,
Realm: basicAuth.Realm,
RemoveHeader: basicAuth.RemoveHeader,
HeaderField: basicAuth.HeaderField,
}, nil
}
func createDigestAuthMiddleware(client Client, namespace string, digestAuth *v1alpha1.DigestAuth) (*dynamic.DigestAuth, error) {
if digestAuth == nil {
return nil, nil
}
credentials, err := getAuthCredentials(client, digestAuth.Secret, namespace)
if err != nil {
return nil, err
}
return &dynamic.DigestAuth{
Users: credentials,
Realm: digestAuth.Realm,
RemoveHeader: digestAuth.RemoveHeader,
HeaderField: digestAuth.HeaderField,
}, nil
}
func getAuthCredentials(k8sClient Client, authSecret, namespace string) ([]string, error) {
if authSecret == "" {
return nil, fmt.Errorf("auth secret must be set")
}
auth, err := loadAuthCredentials(namespace, authSecret, k8sClient)
if err != nil {
return nil, fmt.Errorf("failed to load auth credentials: %s", err)
}
return auth, nil
}
func loadAuthCredentials(namespace, secretName string, k8sClient Client) ([]string, error) {
secret, ok, err := k8sClient.GetSecret(namespace, secretName)
if err != nil {
return nil, fmt.Errorf("failed to fetch secret '%s/%s': %s", namespace, secretName, err)
}
if !ok {
return nil, fmt.Errorf("secret '%s/%s' not found", namespace, secretName)
}
if secret == nil {
return nil, fmt.Errorf("data for secret '%s/%s' must not be nil", namespace, secretName)
}
if len(secret.Data) != 1 {
return nil, fmt.Errorf("found %d elements for secret '%s/%s', must be single element exactly", len(secret.Data), namespace, secretName)
}
var firstSecret []byte
for _, v := range secret.Data {
firstSecret = v
break
}
var credentials []string
scanner := bufio.NewScanner(bytes.NewReader(firstSecret))
for scanner.Scan() {
if cred := scanner.Text(); len(cred) > 0 {
credentials = append(credentials, cred)
}
}
if err := scanner.Err(); err != nil {
return nil, fmt.Errorf("error reading secret for %v/%v: %v", namespace, secretName, err)
}
if len(credentials) == 0 {
return nil, fmt.Errorf("secret '%s/%s' does not contain any credentials", namespace, secretName)
}
return credentials, nil
}
func createChainMiddleware(ctx context.Context, namespace string, chain *v1alpha1.Chain) *dynamic.Chain { func createChainMiddleware(ctx context.Context, namespace string, chain *v1alpha1.Chain) *dynamic.Chain {
if chain == nil { if chain == nil {
return nil return nil

View file

@ -1461,6 +1461,43 @@ func TestLoadIngressRoutes(t *testing.T) {
}, },
}, },
}, },
{
desc: "Simple Ingress Route, with basic auth middleware",
paths: []string{"services.yml", "with_auth.yml"},
expected: &dynamic.Configuration{
TLS: &dynamic.TLSConfiguration{},
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{},
Services: map[string]*dynamic.TCPService{},
},
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{},
Middlewares: map[string]*dynamic.Middleware{
"default/basicauth": {
BasicAuth: &dynamic.BasicAuth{
Users: dynamic.Users{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"},
},
},
"default/digestauth": {
DigestAuth: &dynamic.DigestAuth{
Users: dynamic.Users{"test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/", "test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0"},
},
},
"default/forwardauth": {
ForwardAuth: &dynamic.ForwardAuth{
Address: "test.com",
TLS: &dynamic.ClientTLS{
CA: "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----",
Cert: "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----",
Key: "-----BEGIN PRIVATE KEY-----\n-----END PRIVATE KEY-----",
},
},
},
},
Services: map[string]*dynamic.Service{},
},
},
},
{ {
desc: "port selected by name (TODO)", desc: "port selected by name (TODO)",
}, },

View file

@ -18,29 +18,29 @@ type Middleware struct {
// +k8s:deepcopy-gen=true // +k8s:deepcopy-gen=true
// Middleware holds the Middleware configuration. // MiddlewareSpec holds the Middleware configuration.
type MiddlewareSpec struct { type MiddlewareSpec struct {
AddPrefix *dynamic.AddPrefix `json:"addPrefix,omitempty" toml:"addPrefix,omitempty" yaml:"addPrefix,omitempty"` AddPrefix *dynamic.AddPrefix `json:"addPrefix,omitempty"`
StripPrefix *dynamic.StripPrefix `json:"stripPrefix,omitempty" toml:"stripPrefix,omitempty" yaml:"stripPrefix,omitempty"` StripPrefix *dynamic.StripPrefix `json:"stripPrefix,omitempty"`
StripPrefixRegex *dynamic.StripPrefixRegex `json:"stripPrefixRegex,omitempty" toml:"stripPrefixRegex,omitempty" yaml:"stripPrefixRegex,omitempty"` StripPrefixRegex *dynamic.StripPrefixRegex `json:"stripPrefixRegex,omitempty"`
ReplacePath *dynamic.ReplacePath `json:"replacePath,omitempty" toml:"replacePath,omitempty" yaml:"replacePath,omitempty"` ReplacePath *dynamic.ReplacePath `json:"replacePath,omitempty"`
ReplacePathRegex *dynamic.ReplacePathRegex `json:"replacePathRegex,omitempty" toml:"replacePathRegex,omitempty" yaml:"replacePathRegex,omitempty"` ReplacePathRegex *dynamic.ReplacePathRegex `json:"replacePathRegex,omitempty"`
Chain *Chain `json:"chain,omitempty" toml:"chain,omitempty" yaml:"chain,omitempty"` Chain *Chain `json:"chain,omitempty"`
IPWhiteList *dynamic.IPWhiteList `json:"ipWhiteList,omitempty" toml:"ipWhiteList,omitempty" yaml:"ipWhiteList,omitempty"` IPWhiteList *dynamic.IPWhiteList `json:"ipWhiteList,omitempty"`
Headers *dynamic.Headers `json:"headers,omitempty" toml:"headers,omitempty" yaml:"headers,omitempty"` Headers *dynamic.Headers `json:"headers,omitempty"`
Errors *dynamic.ErrorPage `json:"errors,omitempty" toml:"errors,omitempty" yaml:"errors,omitempty"` Errors *dynamic.ErrorPage `json:"errors,omitempty"`
RateLimit *dynamic.RateLimit `json:"rateLimit,omitempty" toml:"rateLimit,omitempty" yaml:"rateLimit,omitempty"` RateLimit *dynamic.RateLimit `json:"rateLimit,omitempty"`
RedirectRegex *dynamic.RedirectRegex `json:"redirectRegex,omitempty" toml:"redirectRegex,omitempty" yaml:"redirectRegex,omitempty"` RedirectRegex *dynamic.RedirectRegex `json:"redirectRegex,omitempty"`
RedirectScheme *dynamic.RedirectScheme `json:"redirectScheme,omitempty" toml:"redirectScheme,omitempty" yaml:"redirectScheme,omitempty"` RedirectScheme *dynamic.RedirectScheme `json:"redirectScheme,omitempty"`
BasicAuth *dynamic.BasicAuth `json:"basicAuth,omitempty" toml:"basicAuth,omitempty" yaml:"basicAuth,omitempty"` BasicAuth *BasicAuth `json:"basicAuth,omitempty"`
DigestAuth *dynamic.DigestAuth `json:"digestAuth,omitempty" toml:"digestAuth,omitempty" yaml:"digestAuth,omitempty"` DigestAuth *DigestAuth `json:"digestAuth,omitempty"`
ForwardAuth *dynamic.ForwardAuth `json:"forwardAuth,omitempty" toml:"forwardAuth,omitempty" yaml:"forwardAuth,omitempty"` ForwardAuth *ForwardAuth `json:"forwardAuth,omitempty"`
InFlightReq *dynamic.InFlightReq `json:"inFlightReq,omitempty" toml:"inFlightReq,omitempty" yaml:"inFlightReq,omitempty"` InFlightReq *dynamic.InFlightReq `json:"inFlightReq,omitempty"`
Buffering *dynamic.Buffering `json:"buffering,omitempty" toml:"buffering,omitempty" yaml:"buffering,omitempty"` Buffering *dynamic.Buffering `json:"buffering,omitempty"`
CircuitBreaker *dynamic.CircuitBreaker `json:"circuitBreaker,omitempty" toml:"circuitBreaker,omitempty" yaml:"circuitBreaker,omitempty"` CircuitBreaker *dynamic.CircuitBreaker `json:"circuitBreaker,omitempty"`
Compress *dynamic.Compress `json:"compress,omitempty" toml:"compress,omitempty" yaml:"compress,omitempty" label:"allowEmpty"` Compress *dynamic.Compress `json:"compress,omitempty"`
PassTLSClientCert *dynamic.PassTLSClientCert `json:"passTLSClientCert,omitempty" toml:"passTLSClientCert,omitempty" yaml:"passTLSClientCert,omitempty"` PassTLSClientCert *dynamic.PassTLSClientCert `json:"passTLSClientCert,omitempty"`
Retry *dynamic.Retry `json:"retry,omitempty" toml:"retry,omitempty" yaml:"retry,omitempty"` Retry *dynamic.Retry `json:"retry,omitempty"`
} }
// +k8s:deepcopy-gen=true // +k8s:deepcopy-gen=true
@ -50,6 +50,43 @@ type Chain struct {
Middlewares []MiddlewareRef `json:"middlewares,omitempty"` Middlewares []MiddlewareRef `json:"middlewares,omitempty"`
} }
// +k8s:deepcopy-gen=true
// BasicAuth holds the HTTP basic authentication configuration.
type BasicAuth struct {
Secret string `json:"secret,omitempty"`
Realm string `json:"realm,omitempty"`
RemoveHeader bool `json:"removeHeader,omitempty"`
HeaderField string `json:"headerField,omitempty"`
}
// +k8s:deepcopy-gen=true
// DigestAuth holds the Digest HTTP authentication configuration.
type DigestAuth struct {
Secret string `json:"secret,omitempty"`
RemoveHeader bool `json:"removeHeader,omitempty"`
Realm string `json:"realm,omitempty"`
HeaderField string `json:"headerField,omitempty"`
}
// +k8s:deepcopy-gen=true
// ForwardAuth holds the http forward authentication configuration.
type ForwardAuth struct {
Address string `json:"address,omitempty"`
TrustForwardHeader bool `json:"trustForwardHeader,omitempty"`
AuthResponseHeaders []string `json:"authResponseHeaders,omitempty"`
TLS *ClientTLS `json:"tls,omitempty"`
}
type ClientTLS struct {
CASecret string `json:"caSecret,omitempty"`
CAOptional bool `json:"caOptional,omitempty"`
CertSecret string `json:"certSecret,omitempty"`
InsecureSkipVerify bool `json:"insecureSkipVerify,omitempty"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// MiddlewareList is a list of Middleware resources. // MiddlewareList is a list of Middleware resources.

View file

@ -33,6 +33,22 @@ import (
runtime "k8s.io/apimachinery/pkg/runtime" runtime "k8s.io/apimachinery/pkg/runtime"
) )
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *BasicAuth) DeepCopyInto(out *BasicAuth) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BasicAuth.
func (in *BasicAuth) DeepCopy() *BasicAuth {
if in == nil {
return nil
}
out := new(BasicAuth)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Chain) DeepCopyInto(out *Chain) { func (in *Chain) DeepCopyInto(out *Chain) {
*out = *in *out = *in
@ -75,6 +91,64 @@ func (in *ClientAuth) DeepCopy() *ClientAuth {
return out return out
} }
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClientTLS) DeepCopyInto(out *ClientTLS) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClientTLS.
func (in *ClientTLS) DeepCopy() *ClientTLS {
if in == nil {
return nil
}
out := new(ClientTLS)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DigestAuth) DeepCopyInto(out *DigestAuth) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DigestAuth.
func (in *DigestAuth) DeepCopy() *DigestAuth {
if in == nil {
return nil
}
out := new(DigestAuth)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ForwardAuth) DeepCopyInto(out *ForwardAuth) {
*out = *in
if in.AuthResponseHeaders != nil {
in, out := &in.AuthResponseHeaders, &out.AuthResponseHeaders
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.TLS != nil {
in, out := &in.TLS, &out.TLS
*out = new(ClientTLS)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ForwardAuth.
func (in *ForwardAuth) DeepCopy() *ForwardAuth {
if in == nil {
return nil
}
out := new(ForwardAuth)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *HealthCheck) DeepCopyInto(out *HealthCheck) { func (in *HealthCheck) DeepCopyInto(out *HealthCheck) {
*out = *in *out = *in
@ -425,17 +499,17 @@ func (in *MiddlewareSpec) DeepCopyInto(out *MiddlewareSpec) {
} }
if in.BasicAuth != nil { if in.BasicAuth != nil {
in, out := &in.BasicAuth, &out.BasicAuth in, out := &in.BasicAuth, &out.BasicAuth
*out = new(dynamic.BasicAuth) *out = new(BasicAuth)
(*in).DeepCopyInto(*out) **out = **in
} }
if in.DigestAuth != nil { if in.DigestAuth != nil {
in, out := &in.DigestAuth, &out.DigestAuth in, out := &in.DigestAuth, &out.DigestAuth
*out = new(dynamic.DigestAuth) *out = new(DigestAuth)
(*in).DeepCopyInto(*out) **out = **in
} }
if in.ForwardAuth != nil { if in.ForwardAuth != nil {
in, out := &in.ForwardAuth, &out.ForwardAuth in, out := &in.ForwardAuth, &out.ForwardAuth
*out = new(dynamic.ForwardAuth) *out = new(ForwardAuth)
(*in).DeepCopyInto(*out) (*in).DeepCopyInto(*out)
} }
if in.InFlightReq != nil { if in.InFlightReq != nil {

View file

@ -177,6 +177,13 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string
continue continue
} }
if routerConfig.Rule == "" {
err := errors.New("router has no rule")
routerConfig.AddError(err, true)
logger.Error(err)
continue
}
handler, err := m.serviceManager.BuildTCP(ctxRouter, routerConfig.Service) handler, err := m.serviceManager.BuildTCP(ctxRouter, routerConfig.Service)
if err != nil { if err != nil {
routerConfig.AddError(err, true) routerConfig.AddError(err, true)
@ -188,7 +195,7 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string
if err != nil { if err != nil {
routerErr := fmt.Errorf("unknown rule %s", routerConfig.Rule) routerErr := fmt.Errorf("unknown rule %s", routerConfig.Rule)
routerConfig.AddError(routerErr, true) routerConfig.AddError(routerErr, true)
logger.Debug(routerErr) logger.Error(routerErr)
continue continue
} }