Ziel des Artikels ist es, die notwendigen Schritte zum Absichern eines Dienstes im Kubernetes Clusters mittels OAuth zu dokumentieren.
Keycloak installieren
Als Identity Provider kommt Keycloak zum Einsatz.
Basierend https://www.openshift.com/blog/adding-authentication-to-your-kubernetes-web-applications-with-keycloak
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 helm repo add codecentric https://codecentric.github.io/helm-charts curl https://raw.githubusercontent.com/codecentric/helm-charts/master/charts/keycloak/values.yaml -o values.yaml patch <<EOF @@ -240,12 +240,12 @@ keycloak: ## Ingress configuration. ## ref: https://kubernetes.io/docs/user-guide/ingress/ ingress: - enabled: false + enabled: true path: / - annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" + annotations: + kubernetes.io/ingress.class: nginx + kubernetes.io/tls-acme: "true" # ingress.kubernetes.io/affinity: cookie labels: {} @@ -253,13 +253,13 @@ keycloak: ## List of hosts for the ingress hosts: - - keycloak.example.com + - xxx.mydomain.com ## TLS configuration - tls: [] - # - hosts: - # - keycloak.example.com - # secretName: tls-keycloak + tls: + - hosts: + - xxx.mydomain.com + secretName: tls-keycloak ## OpenShift route configuration. ## ref: https://docs.openshift.com/container-platform/3.11/architecture/networking/routes.html @@ -287,10 +287,10 @@ keycloak: ## Persistence configuration persistence: # If true, the Postgres chart is deployed - deployPostgres: false + deployPostgres: true # The database vendor. Can be either "postgres", "mysql", "mariadb", or "h2" - dbVendor: h2 + dbVendor: postgres ## The following values only apply if "deployPostgres" is set to "false" dbName: keycloak EOF kubectl create namespace keycloak helm upgrade -i -n keycloak keycloak codecentric/keycloak -f values.yaml
Keycloak konfigurieren
Basierend auf https://kubernetes.github.io/ingress-nginx/examples/auth/oauth-external-auth/ und https://oauth2-proxy.github.io/oauth2-proxy/auth-configuration#keycloak-auth-provider
Neuen Realm anlegen, z.B. local
Neuen Client anlegen, z.B. k8s-ingress
Access Type auf confidential
Valid redirect URL auf https://*
Credentials -> Secret notieren
Neuen Mapper anlegen per Create
:
Name groups
Mapper Type Group Membership
Token Claim Name groups
Neue Gruppe anlegen, z.B. admin
Neuen User anlegen
Email eintragen
Email bestätigen
Gruppe beitreten
bei Bedarf OTP aktivieren
Credentials setzen
Dienst anpassen und schützen
Am Beispiel Kubernetes Dashboard:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 cat <<EOF > enable-oauth.yaml apiVersion: extensions/v1beta1 kind: Ingress metadata: annotations: kubernetes.io/ingress.class: nginx kubernetes.io/tls-acme: "true" ingress.kubernetes.io/ssl-redirect: "true" ingress.kubernetes.io/use-port-in-redirects: "true" nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" nginx.ingress.kubernetes.io/auth-url: "https://$host/oauth2/auth" nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=$escaped_request_uri" name: dashboard namespace: kube-dashboard spec: tls: - hosts: - xxx.mydomain.com secretName: xxx.mydomain.com-tls rules: - host: xxx.mydomain.com http: paths: - backend: serviceName: kubernetes-dashboard servicePort: 8443 path: / --- apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: oauth2-proxy namespace: kube-dashboard spec: rules: - host: xxx.mydomain.com http: paths: - backend: serviceName: oauth2-proxy servicePort: 4180 path: /oauth2 tls: - hosts: - xxx.mydomain.com secretName: xxx.mydomain.com-tls --- apiVersion: apps/v1 kind: Deployment metadata: labels: k8s-app: oauth2-proxy name: oauth2-proxy namespace: kube-dashboard spec: replicas: 1 selector: matchLabels: k8s-app: oauth2-proxy template: metadata: labels: k8s-app: oauth2-proxy spec: containers: - args: - --provider=keycloak - --client-id=k8s-ingress - --client-secret=5e656d5b-xxxx-xxxx-8845-xxxxxxxxxxxx - --login-url=https://keycloak.mydomain.com/auth/realms/local/protocol/openid-connect/auth - --redeem-url=https://keycloak.mydomain.com/auth/realms/local/protocol/openid-connect/token - --validate-url=https://keycloak.mydomain.com/auth/realms/local/protocol/openid-connect/userinfo - --keycloak-group=/admin - --email-domain=* - --http-address=0.0.0.0:4180 env: - name: OAUTH2_PROXY_COOKIE_SECRET value: xxxxxxxxxxxxxxxxxxxxxxxxxxxxx image: quay.io/pusher/oauth2_proxy:latest imagePullPolicy: Always name: oauth2-proxy ports: - containerPort: 4180 protocol: TCP --- apiVersion: v1 kind: Service metadata: labels: k8s-app: oauth2-proxy name: oauth2-proxy namespace: kube-dashboard spec: ports: - name: http port: 4180 protocol: TCP targetPort: 4180 selector: k8s-app: oauth2-proxy EOF
Credits
Photo by Markus Winkler on Unsplash
Permanentlink: https://joachim-wilke.de/blog/2020/04/24/Dienste-im-Kubernetes-Cluster-mit-Keycloak-und-OAuth-schutzen/