Reading from a secret in Traefik Middleware - kubernetes

I am working on a middleware using traefik that basically adds a Authorization header and wondering how I can read that header from a secret that already exists. Below is the middleware script
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: middleware-tokenheader
spec:
headers:
customRequestHeaders:
Authorization: {{ .Values.token }}

Related

Is it possible to use RequestAuthentication and AuthenticationPolicy for microservice to microservice communication

We have recently setup istio on our kubernetes cluster and are trying to see if we can use RequestAuthentication and AuthenticationPolicy to enable us to only allow a pod in namespace x to communicate with a pod in namespace y when it has a valid jwt token.
All the examples I have seen online seem to only apply for end user authentication via the gateway rather than internal pod to pod communication.
We have tried a few different options but are yet to have any luck.
We can get AuthenticationPolicy to work for pod to pod traffic using "from" and the source being the IP address of the pod in namespace x:
apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
name: "request-jwt"
namespace: y
spec:
jwtRules:
- issuer: "https://keycloak.example.com/auth/realms/istio"
jwksUri: "https://keycloak.example.com/auth/realms/istio/protocol/openid-connect/certs"
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: "jwt-auth"
namespace: y
spec:
action: ALLOW
rules:
- from:
- source:
ipBlocks: ["10.43.5.175"]
When we add when block for jwt it doesn't work:
apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
name: "request-jwt"
namespace: y
spec:
jwtRules:
- issuer: "https://keycloak.example.com/auth/realms/istio"
jwksUri: "https://keycloak.example.com/auth/realms/istio/protocol/openid-connect/certs"
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: "jwt-auth"
namespace: y
spec:
action: ALLOW
rules:
- from:
- source:
ipBlocks: ["10.43.5.175"]
when:
- key: request.auth.claims[iss]
values: ["https://keycloak.example.com/auth/realms/istio"]
Also tried this but doesn't seem to work either:
apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
name: "request-jwt"
namespace: y
spec:
jwtRules:
- issuer: "https://keycloak.example.com/auth/realms/istio"
jwksUri: "https://keycloak.example.com/auth/realms/istio/protocol/openid-connect/certs"
---
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: "deny-invalid-jwt"
namespace: y
spec:
action: DENY
rules:
- from:
- source:
notRequestPrincipals: ["*"]
Thanks in advance!
Yes, it is possible to use both Authorization Policies and Request Authentications.
But debugging is quite difficult because a lot is based on your environment and the JWT that is being used, and so on.
To troubleshoot these kinds of issues I'd start by setting the rbac scoped logs to debug for the services envoy proxy.
In the rbac debug logs you'll see the data extracted from the JWT and stored into filter metadata.
What you'll frequently find is that:
The issuer in the filter metadata might not match the one in the RequestAuthentication resource, etc.
Learn more about logging scopes here https://istio.io/v1.12/docs/ops/diagnostic-tools/component-logging/#logging-scopes

kubernetes cors errror with oauth2 reverse proxy

I am facing an issue with kubernetes oauth2-proxy CORS policy.
My setup:
ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: supervisor-ingress
namespace: management
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-staging
nginx.ingress.kubernetes.io/auth-url: "https://$host/oauth2/auth"
nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=$escaped_request_uri"
oauth2 proxy ingress:
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: oauth2-proxy
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
I am running react application on localhost
I strongly believe that this issue is oauth proxy related as disabling auth-url works fine.
I have tried multiple headers and cors policies, but it seems they are not applied to oauth proxy
response message:
Access to XMLHttpRequest at '' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

how to customize k8s nginx ingress HTTP headers error

in our cluster, there's a customized error pages backend and a auth service
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/use-regex: 'true'
nginx.ingress.kubernetes.io/auth-url: 'http:/***/auth'
https://kubernetes.github.io/ingress-nginx/user-guide/custom-errors/
https://github.com/kubernetes/ingress-nginx/tree/master/images/custom-error-pages
From above link and the log show in error pages backend from auth service 401, it only have 8 hardcode heades like below.
2020/04/14 03:24:35 request info &{GET /?access_token=pk1.eyJ1Ijoid2ViZXJ0YW8iLCJhIjoiY2pibTdmaWc2MTZqaDJybzFzcm93bGE2eiJ9.cwSE9DYCYP0dIeY4Hhp6Kg HTTP/1.0 1 0 map[Accept:[/] Accept-Encoding:[gzip, deflate, br] Cache-Control:[no-cache] Connection:[close] Postman-Token:[c7d07b51-5e3d-469d-9ec4-73be2cf5cd26] User-Agent:[PostmanRuntime/7.24.0] X-Code:[401] X-Format:[/] X-Ingress-Name:[static-api-ingress] X-Namespace:[default] X-Original-Uri:[/xxxx/-76.9,38.9,15/1000x1000#1x?access_token=pk1.eyJ1Ijoid2ViZXJ0YW8iLCJhIjoiY2pibTdmaWc2MTZqaDJybzFzcm93bGE2eiJ9.cwSE9DYCYP0dIeY4Hhp6Kg] X-Service-Name:[static-api-svc] X-Service-Port:[80]] {} 0 [] true api.staging.versalinks.net map[] map[] map[] 172.20.0.70:11440 /?access_token=pk1.eyJ1Ijoid2ViZXJ0YW8iLCJhIjoiY2pibTdmaWc2MTZqaDJybzFzcm93bGE2eiJ9.cwSE9DYCYP0dIeY4Hhp6Kg 0xc00009e0c0}
Is it possible we can add some customized header X-AUTH-INFO from auth service?
You can use Custom Headers for nginx ingress controller via a ConfigMap to pass a custom list of headers to the upstream server.
You should define ConfigMap with your custom headers:
apiVersion: v1
data:
X-Different-Name: "true"
X-Request-Start: t=${msec}
X-Using-Nginx-Controller: "true"
kind: ConfigMap
metadata:
name: custom-headers
namespace: ingress-nginx
This defines a ConfigMap in the ingress-nginx namespace named custom-headers, holding several custom X-prefixed HTTP headers.
apiVersion: v1
data:
proxy-set-headers: "ingress-nginx/custom-headers"
kind: ConfigMap
metadata:
name: nginx-configuration
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
This defines a ConfigMap in the ingress-nginx namespace named nginx-configuration. This controls the global configuration of the ingress controller, and already exists in a standard installation. The key proxy-set-headers is set to cite the previously-created ingress-nginx/custom-headers ConfigMap.
The nginx ingress controller will read the ingress-nginx/nginx-configuration ConfigMap, find the proxy-set-headers key, read HTTP headers from the ingress-nginx/custom-headers ConfigMap, and include those HTTP headers in all requests flowing from nginx to the backends.

add basic auth with traefik v2 in kubernetes did not popup login form

I am follow this steps to add basic auth to treafik 2.1.6,first create kuberntes(v1.15.2) secret:
openssl rand -base64 32
htpasswd -bc auth dabai-admin hbzwvEbfRGSN4MAiycCVM30stfGjzR6dZPDh9bS5te4=
kubectl create secret generic treafik-secret-name --from-file=auth -n kube-system
create middleware:
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: basic-auth
spec:
basicAuth:
secret: treafik-secret-name
tweak traefik config and add middleware we create:
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: traefik-dashboard-route
annotations:
kubernetes.io/ingress.class: traefik
ingress.kubernetes.io/auth-type: basic
ingress.kubernetes.io/auth-secret: traefik-secret-name
spec:
entryPoints:
- web
routes:
- match: Host(`traefik.example.com`)
kind: Rule
services:
- name: traefik
port: 8080
middlewares:
- name: basic-auth
finally when I access the domain traefik.example.com,it did not pop up login form, what should I do to make it work? I want to add basic auth to my website traefik.example.com.

Kubernetes basic authentication with Traefik

I am trying to configure Basic Authentication on a Nginx example with Traefik as Ingress controller.
I just create the secret "mypasswd" on the Kubernetes secrets.
This is the Ingress I am using:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: nginxingress
annotations:
ingress.kubernetes.io/auth-type: basic
ingress.kubernetes.io/auth-realm: traefik
ingress.kubernetes.io/auth-secret: mypasswd
spec:
rules:
- host: nginx.mycompany.com
http:
paths:
- path: /
backend:
serviceName: nginxservice
servicePort: 80
I check in the Traefik dashboard and it appear, if I access to nginx.mycompany.com I can check the Nginx webpage, but without the basic authentication.
This is my nginx deployment:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
Nginx service:
apiVersion: v1
kind: Service
metadata:
labels:
name: nginxservice
name: nginxservice
spec:
ports:
# The port that this service should serve on.
- port: 80
# Label keys and values that must match in order to receive traffic for this service.
selector:
app: nginx
type: ClusterIP
It is popular to use basic authentication. In reference to Kubernetes documentation, you should be able to protect access to Traefik using the following steps :
Create authentication file using htpasswd tool. You'll be asked for a password for the user:
htpasswd -c ./auth
Now use kubectl to create a secret in the monitoring namespace using the file created by htpasswd.
kubectl create secret generic mysecret --from-file auth
--namespace=monitoring
Enable basic authentication by attaching annotations to Ingress object:
ingress.kubernetes.io/auth-type: "basic"
ingress.kubernetes.io/auth-secret: "mysecret"
So, full example config of basic authentication can looks like:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: prometheus-dashboard
namespace: monitoring
annotations:
kubernetes.io/ingress.class: traefik
ingress.kubernetes.io/auth-type: "basic"
ingress.kubernetes.io/auth-secret: "mysecret"
spec:
rules:
- host: dashboard.prometheus.example.com
http:
paths:
- backend:
serviceName: prometheus
servicePort: 9090
You can apply the example as following:
kubectl create -f prometheus-ingress.yaml -n monitoring
This should work without any issues.
Basic Auth configuration for Kubernetes and Traefik 2 seems to have slightly changed. It took me some time to find the solution, that's why I want to share it. I use k3s btw.
Step 1 + 2 are identical to what #d0bry wrote, create the secret:
printf "my-username:`openssl passwd -apr1`\n" >> my-auth
kubectl create secret generic my-auth --from-file my-auth --namespace my-namespace
Step 3 is to create the ingress object and apply a middleware that will handle the authentication
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: my-auth-middleware
namespace: my-namespace
spec:
basicAuth:
removeHeader: true
secret: my-auth
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
namespace: my-namespace
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/router.middlewares: my-namespace-my-auth-middleware#kubernetescrd
spec:
rules:
- host: my.domain.net
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-service
port:
number: 8080
And then of course apply the configuration
kubectl apply -f my-ingress.yaml
refs:
https://doc.traefik.io/traefik/routing/providers/kubernetes-ingress/
https://doc.traefik.io/traefik/middlewares/http/basicauth/
With the latest traefik (verified with 2.7) it got even simpler. Just create a secret of type kubernetes.io/basic-auth and use that in your middleware. No need to create the username:password string first and create a secret from that.
apiVersion: v1
kind: Secret
metadata:
name: my-auth
namespace: my-namespace
type: kubernetes.io/basic-auth
data:
username: <username in base64>
password: <password in base64>
---
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: my-auth-middleware
namespace: my-namespace
spec:
basicAuth:
removeHeader: true
secret: my-auth
Note that the password is not hashed as it is with htpasswd, but only base64 encoded.
Ref docs