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:
|
||||
# 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"
|
||||
- "traefik.http.middlewares.test-auth.basicauth.users=test:$$apr1$$H6uskkkW$$IgXLP6ewTrSuBkTrqE8wj/,test2:$$apr1$$d9hr9HBB$$4HxwgUir3HP4EsggP/QNo0"
|
||||
```
|
||||
|
||||
```yaml tab="Kubernetes"
|
||||
|
@ -27,9 +27,7 @@ metadata:
|
|||
name: test-auth
|
||||
spec:
|
||||
basicAuth:
|
||||
users:
|
||||
- test:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/
|
||||
- test2:$apr1$d9hr9HBB$4HxwgUir3HP4EsggP/QNo0
|
||||
secret: secretName
|
||||
```
|
||||
|
||||
```json tab="Marathon"
|
||||
|
@ -41,7 +39,7 @@ spec:
|
|||
```yaml tab="Rancher"
|
||||
# Declaring the user list
|
||||
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)"
|
||||
|
@ -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.
|
||||
|
||||
!!! 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`
|
||||
|
||||
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`.
|
||||
|
||||
!!! 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"
|
||||
|
||||
```txt
|
||||
|
@ -92,21 +218,57 @@ The file content is a list of `name:encoded-password`.
|
|||
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`
|
||||
|
||||
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`
|
||||
|
||||
You can define a header field to store the authenticated user using the `headerField`option.
|
||||
|
||||
```yaml tab="Docker"
|
||||
labels:
|
||||
- "traefik.http.middlewares.my-auth.basicauth.headerField=X-WebAuth-User"
|
||||
- "traefik.http.middlewares.my-auth.basicauth.headerField=X-WebAuth-User"
|
||||
```
|
||||
|
||||
```yaml tab="Kubernetes"
|
||||
|
@ -144,3 +306,43 @@ http:
|
|||
### `removeHeader`
|
||||
|
||||
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
|
||||
|
||||
```yaml tab="Docker"
|
||||
# Declaring the user list
|
||||
labels:
|
||||
- "traefik.http.middlewares.test-auth.digestauth.users=test:traefik:a2688e031edb4be6a3797f3882655c05,test2:traefik:518845800f9e2bfb1f1f740ec24f074e"
|
||||
```
|
||||
|
@ -22,9 +23,82 @@ metadata:
|
|||
name: test-auth
|
||||
spec:
|
||||
digestAuth:
|
||||
users:
|
||||
- test:traefik:a2688e031edb4be6a3797f3882655c05
|
||||
- test2:traefik:518845800f9e2bfb1f1f740ec24f074e
|
||||
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:
|
||||
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"
|
||||
|
@ -57,26 +131,69 @@ http:
|
|||
- "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`
|
||||
|
||||
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`.
|
||||
|
||||
!!! 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"
|
||||
|
||||
```txt
|
||||
|
@ -84,20 +201,54 @@ The file content is a list of `name:realm:encoded-password`.
|
|||
test2:traefik:518845800f9e2bfb1f1f740ec24f074e
|
||||
```
|
||||
|
||||
!!! Note
|
||||
|
||||
If both `users` and `usersFile` are provided, the two are merged. The content of `usersFile` has precedence over `users`.
|
||||
|
||||
### `realm`
|
||||
|
||||
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`
|
||||
|
||||
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"
|
||||
labels:
|
||||
- "traefik.http.middlewares.my-auth.digestauth.headerField=X-WebAuth-User"
|
||||
|
@ -143,3 +294,43 @@ http:
|
|||
### `removeHeader`
|
||||
|
||||
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
|
||||
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"
|
||||
```
|
||||
|
||||
```yaml tab="Kubernetes"
|
||||
# Forward authentication to authserver.com
|
||||
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"
|
||||
# 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"
|
||||
```
|
||||
|
||||
|
@ -33,89 +120,381 @@ spec:
|
|||
forwardAuth:
|
||||
address: https://authserver.com/auth
|
||||
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"
|
||||
"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"
|
||||
}
|
||||
```
|
||||
|
||||
```yaml tab="Rancher"
|
||||
# Forward authentication to authserver.com
|
||||
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"
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
# Forward authentication to authserver.com
|
||||
[http.middlewares]
|
||||
[http.middlewares.test-auth.forwardAuth]
|
||||
address = "https://authserver.com/auth"
|
||||
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)"
|
||||
# Forward authentication to authserver.com
|
||||
http:
|
||||
middlewares:
|
||||
test-auth:
|
||||
forwardAuth:
|
||||
address: "https://authserver.com/auth"
|
||||
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`
|
||||
|
||||
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`
|
||||
|
||||
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:
|
||||
defaultMode: keep
|
||||
names:
|
||||
- User-Agent: redact
|
||||
- Authorization: drop
|
||||
- Content-Type: keep
|
||||
User-Agent: redact
|
||||
Authorization: drop
|
||||
Content-Type: keep
|
||||
```
|
||||
|
||||
```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) {
|
||||
logger := middlewares.GetLogger(ctx, name, typeName)
|
||||
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)
|
||||
|
||||
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
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
|
@ -149,6 +151,25 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client)
|
|||
for _, middleware := range client.GetMiddlewares() {
|
||||
id := makeID(middleware.Namespace, middleware.Name)
|
||||
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{
|
||||
AddPrefix: middleware.Spec.AddPrefix,
|
||||
StripPrefix: middleware.Spec.StripPrefix,
|
||||
|
@ -162,9 +183,9 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client)
|
|||
RateLimit: middleware.Spec.RateLimit,
|
||||
RedirectRegex: middleware.Spec.RedirectRegex,
|
||||
RedirectScheme: middleware.Spec.RedirectScheme,
|
||||
BasicAuth: middleware.Spec.BasicAuth,
|
||||
DigestAuth: middleware.Spec.DigestAuth,
|
||||
ForwardAuth: middleware.Spec.ForwardAuth,
|
||||
BasicAuth: basicAuth,
|
||||
DigestAuth: digestAuth,
|
||||
ForwardAuth: forwardAuth,
|
||||
InFlightReq: middleware.Spec.InFlightReq,
|
||||
Buffering: middleware.Spec.Buffering,
|
||||
CircuitBreaker: middleware.Spec.CircuitBreaker,
|
||||
|
@ -178,6 +199,175 @@ func (p *Provider) loadConfigurationFromCRD(ctx context.Context, client Client)
|
|||
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 {
|
||||
if chain == 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)",
|
||||
},
|
||||
|
|
|
@ -18,29 +18,29 @@ type Middleware struct {
|
|||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Middleware holds the Middleware configuration.
|
||||
// MiddlewareSpec holds the Middleware configuration.
|
||||
type MiddlewareSpec struct {
|
||||
AddPrefix *dynamic.AddPrefix `json:"addPrefix,omitempty" toml:"addPrefix,omitempty" yaml:"addPrefix,omitempty"`
|
||||
StripPrefix *dynamic.StripPrefix `json:"stripPrefix,omitempty" toml:"stripPrefix,omitempty" yaml:"stripPrefix,omitempty"`
|
||||
StripPrefixRegex *dynamic.StripPrefixRegex `json:"stripPrefixRegex,omitempty" toml:"stripPrefixRegex,omitempty" yaml:"stripPrefixRegex,omitempty"`
|
||||
ReplacePath *dynamic.ReplacePath `json:"replacePath,omitempty" toml:"replacePath,omitempty" yaml:"replacePath,omitempty"`
|
||||
ReplacePathRegex *dynamic.ReplacePathRegex `json:"replacePathRegex,omitempty" toml:"replacePathRegex,omitempty" yaml:"replacePathRegex,omitempty"`
|
||||
Chain *Chain `json:"chain,omitempty" toml:"chain,omitempty" yaml:"chain,omitempty"`
|
||||
IPWhiteList *dynamic.IPWhiteList `json:"ipWhiteList,omitempty" toml:"ipWhiteList,omitempty" yaml:"ipWhiteList,omitempty"`
|
||||
Headers *dynamic.Headers `json:"headers,omitempty" toml:"headers,omitempty" yaml:"headers,omitempty"`
|
||||
Errors *dynamic.ErrorPage `json:"errors,omitempty" toml:"errors,omitempty" yaml:"errors,omitempty"`
|
||||
RateLimit *dynamic.RateLimit `json:"rateLimit,omitempty" toml:"rateLimit,omitempty" yaml:"rateLimit,omitempty"`
|
||||
RedirectRegex *dynamic.RedirectRegex `json:"redirectRegex,omitempty" toml:"redirectRegex,omitempty" yaml:"redirectRegex,omitempty"`
|
||||
RedirectScheme *dynamic.RedirectScheme `json:"redirectScheme,omitempty" toml:"redirectScheme,omitempty" yaml:"redirectScheme,omitempty"`
|
||||
BasicAuth *dynamic.BasicAuth `json:"basicAuth,omitempty" toml:"basicAuth,omitempty" yaml:"basicAuth,omitempty"`
|
||||
DigestAuth *dynamic.DigestAuth `json:"digestAuth,omitempty" toml:"digestAuth,omitempty" yaml:"digestAuth,omitempty"`
|
||||
ForwardAuth *dynamic.ForwardAuth `json:"forwardAuth,omitempty" toml:"forwardAuth,omitempty" yaml:"forwardAuth,omitempty"`
|
||||
InFlightReq *dynamic.InFlightReq `json:"inFlightReq,omitempty" toml:"inFlightReq,omitempty" yaml:"inFlightReq,omitempty"`
|
||||
Buffering *dynamic.Buffering `json:"buffering,omitempty" toml:"buffering,omitempty" yaml:"buffering,omitempty"`
|
||||
CircuitBreaker *dynamic.CircuitBreaker `json:"circuitBreaker,omitempty" toml:"circuitBreaker,omitempty" yaml:"circuitBreaker,omitempty"`
|
||||
Compress *dynamic.Compress `json:"compress,omitempty" toml:"compress,omitempty" yaml:"compress,omitempty" label:"allowEmpty"`
|
||||
PassTLSClientCert *dynamic.PassTLSClientCert `json:"passTLSClientCert,omitempty" toml:"passTLSClientCert,omitempty" yaml:"passTLSClientCert,omitempty"`
|
||||
Retry *dynamic.Retry `json:"retry,omitempty" toml:"retry,omitempty" yaml:"retry,omitempty"`
|
||||
AddPrefix *dynamic.AddPrefix `json:"addPrefix,omitempty"`
|
||||
StripPrefix *dynamic.StripPrefix `json:"stripPrefix,omitempty"`
|
||||
StripPrefixRegex *dynamic.StripPrefixRegex `json:"stripPrefixRegex,omitempty"`
|
||||
ReplacePath *dynamic.ReplacePath `json:"replacePath,omitempty"`
|
||||
ReplacePathRegex *dynamic.ReplacePathRegex `json:"replacePathRegex,omitempty"`
|
||||
Chain *Chain `json:"chain,omitempty"`
|
||||
IPWhiteList *dynamic.IPWhiteList `json:"ipWhiteList,omitempty"`
|
||||
Headers *dynamic.Headers `json:"headers,omitempty"`
|
||||
Errors *dynamic.ErrorPage `json:"errors,omitempty"`
|
||||
RateLimit *dynamic.RateLimit `json:"rateLimit,omitempty"`
|
||||
RedirectRegex *dynamic.RedirectRegex `json:"redirectRegex,omitempty"`
|
||||
RedirectScheme *dynamic.RedirectScheme `json:"redirectScheme,omitempty"`
|
||||
BasicAuth *BasicAuth `json:"basicAuth,omitempty"`
|
||||
DigestAuth *DigestAuth `json:"digestAuth,omitempty"`
|
||||
ForwardAuth *ForwardAuth `json:"forwardAuth,omitempty"`
|
||||
InFlightReq *dynamic.InFlightReq `json:"inFlightReq,omitempty"`
|
||||
Buffering *dynamic.Buffering `json:"buffering,omitempty"`
|
||||
CircuitBreaker *dynamic.CircuitBreaker `json:"circuitBreaker,omitempty"`
|
||||
Compress *dynamic.Compress `json:"compress,omitempty"`
|
||||
PassTLSClientCert *dynamic.PassTLSClientCert `json:"passTLSClientCert,omitempty"`
|
||||
Retry *dynamic.Retry `json:"retry,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
@ -50,6 +50,43 @@ type Chain struct {
|
|||
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
|
||||
|
||||
// MiddlewareList is a list of Middleware resources.
|
||||
|
|
|
@ -33,6 +33,22 @@ import (
|
|||
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.
|
||||
func (in *Chain) DeepCopyInto(out *Chain) {
|
||||
*out = *in
|
||||
|
@ -75,6 +91,64 @@ func (in *ClientAuth) DeepCopy() *ClientAuth {
|
|||
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.
|
||||
func (in *HealthCheck) DeepCopyInto(out *HealthCheck) {
|
||||
*out = *in
|
||||
|
@ -425,17 +499,17 @@ func (in *MiddlewareSpec) DeepCopyInto(out *MiddlewareSpec) {
|
|||
}
|
||||
if in.BasicAuth != nil {
|
||||
in, out := &in.BasicAuth, &out.BasicAuth
|
||||
*out = new(dynamic.BasicAuth)
|
||||
(*in).DeepCopyInto(*out)
|
||||
*out = new(BasicAuth)
|
||||
**out = **in
|
||||
}
|
||||
if in.DigestAuth != nil {
|
||||
in, out := &in.DigestAuth, &out.DigestAuth
|
||||
*out = new(dynamic.DigestAuth)
|
||||
(*in).DeepCopyInto(*out)
|
||||
*out = new(DigestAuth)
|
||||
**out = **in
|
||||
}
|
||||
if in.ForwardAuth != nil {
|
||||
in, out := &in.ForwardAuth, &out.ForwardAuth
|
||||
*out = new(dynamic.ForwardAuth)
|
||||
*out = new(ForwardAuth)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.InFlightReq != nil {
|
||||
|
|
|
@ -177,6 +177,13 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string
|
|||
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)
|
||||
if err != nil {
|
||||
routerConfig.AddError(err, true)
|
||||
|
@ -188,7 +195,7 @@ func (m *Manager) buildEntryPointHandler(ctx context.Context, configs map[string
|
|||
if err != nil {
|
||||
routerErr := fmt.Errorf("unknown rule %s", routerConfig.Rule)
|
||||
routerConfig.AddError(routerErr, true)
|
||||
logger.Debug(routerErr)
|
||||
logger.Error(routerErr)
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue