Auth middlewares in kubernetes CRD uses secrets
This commit is contained in:
parent
6712423dd1
commit
1959e1fd44
11 changed files with 1306 additions and 124 deletions
|
@ -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
|
||||||
|
```
|
||||||
|
|
|
@ -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"
|
||||||
```
|
```
|
||||||
|
@ -22,9 +23,82 @@ metadata:
|
||||||
name: test-auth
|
name: test-auth
|
||||||
spec:
|
spec:
|
||||||
digestAuth:
|
digestAuth:
|
||||||
users:
|
secret: userssecret
|
||||||
- test:traefik:a2688e031edb4be6a3797f3882655c05
|
```
|
||||||
- test2:traefik:518845800f9e2bfb1f1f740ec24f074e
|
|
||||||
|
```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:
|
||||||
|
users:
|
||||||
|
- "test:traefik:a2688e031edb4be6a3797f3882655c05"
|
||||||
|
- "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
|
||||||
|
```
|
||||||
|
|
|
@ -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
|
||||||
|
```
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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(
|
||||||
|
|
65
pkg/provider/kubernetes/crd/fixtures/with_auth.yml
Normal file
65
pkg/provider/kubernetes/crd/fixtures/with_auth.yml
Normal 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
|
|
@ -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
|
||||||
|
|
|
@ -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)",
|
||||||
},
|
},
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue