Published on

Thiết lập SSO cho Kuberentes dashboard dùng Oauth2 Proxy

Giới thiệu

Bài viết này sẽ giới thiệu cách mà mình thiết lập để có thể đăng nhập vào Kubernetes Dashboard bằng phương thức SSO.

Kubernetes dashboard

Kubernetes dashboard ứng dụng WebUI cho phép chúng ta quản lý cluster của mình một cách trực quan. Trên thị trường có nhiều app tương tự như Open lens,... Tuy nhiên mình thấy K8s Dashboard là đủ trong phạm vi học tập, nghiên cứu.

Để deploy dashboard lên cluster thì khá đơn giản, chỉ cần

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml

Chi tiết hơn bạn có thể đọc thêm Deploying the Dashboard UI

Azure AD OIDC

Trong ví dụ này mình sử dụng OIDC của Azure AD. Điều kiện đầu tiên là bạn phải đăng ký app trên Azure AD, chi tiết có thể xem hướng dẫn này Quickstart: Register an application with the Microsoft identity platform. Các thông tin quan trọng cần phải lưu ý:

  • Application (client) ID: <Client-ID>
  • Client secret: <Client secret>
  • Directory (tenant) ID: <Tenant-ID>
  • Redirect URIs: https://your-dashboard-domain.com/oauth2/callback

Lưu ý:

Để biết cách thiết lập 1 App trên Azure AD vui lòng xem thêm tại bài viết Thiết lập Jenkins SSO dùng Azure AD

OAuth2 Proxy

Deployment

oauth2-proxy-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
     app.kubernetes.io/name: oauth2-proxy
  name: oauth2-proxy
  namespace: kubernetes-dashboard
spec:
  selector:
    matchLabels:
       app.kubernetes.io/name: oauth2-proxy
  template:
    metadata:
      labels:
         app.kubernetes.io/name: oauth2-proxy
    spec:
      containers:
        - args:
            - --provider=oidc
            - --azure-tenant=<Tenant-ID> # Azure AD OAuth2 Proxy application Tenant ID
            - --cookie-name=_proxycookie # this can be any name of your choice which you would like OAuth2 Proxy to use for the session cookie
            - --email-domain=*
            - --upstream=file:///dev/null
            - --http-address=0.0.0.0:4180
            - --oidc-issuer-url=https://sts.windows.net/<Tenant-ID>/
            - --set-xauthrequest=true
            - --pass-access-token=true
            - --set-authorization-header=true
          env:
            - name: OAUTH2_PROXY_CLIENT_ID
              valueFrom:
                secretKeyRef:
                  name: proxy-secrets
                  key: OAUTH2_PROXY_CLIENT_ID
            - name: OAUTH2_PROXY_CLIENT_SECRET
              valueFrom:
                secretKeyRef:
                  name: proxy-secrets
                  key: OAUTH2_PROXY_CLIENT_SECRET
            - name: OAUTH2_PROXY_COOKIE_SECRET
              valueFrom:
                secretKeyRef:
                  name: proxy-secrets
                  key: OAUTH2_PROXY_COOKIE_SECRET
          image: quay.io/oauth2-proxy/oauth2-proxy:v7.4.0
          imagePullPolicy: Always
          name: oauth2-proxy
          ports:
            - containerPort: 4180
              protocol: TCP
          resources:
            limits:
              cpu: 100m
              memory: 128Mi
            requests:
              cpu: 100m
              memory: 128Mi

Với manifest ở trên, có 3 thông tin chúng ta nên để ở dạng Secrets:

  • OAUTH2_PROXY_CLIENT_ID
  • OAUTH2_PROXY_CLIENT_SECRET
  • OAUTH2_PROXY_COOKIE_SECRET: có thể tạo bằng lệnh sau: python -c 'import secrets,base64; print(base64.b64encode(base64.b64encode(secrets.token_bytes(16))));'
kubectl -n kubernetes-dashboard create secret generic proxy-secrets \
    --from-literal=OAUTH2_PROXY_CLIENT_ID='<Client-ID>' \
    --from-literal=OAUTH2_PROXY_CLIENT_SECRET='<Client-secret>' \
    --from-literal=OAUTH2_PROXY_COOKIE_SECRET='<cookie-secret>'

Sau khi đã khởi tạo được các secrets thì chúng ta tiến hành deploy Oauth2 proxy

kubectl -n kubernetes-dashboard apply -f oauth2-proxy-deployment.yaml

Service

oauth2-proxy-service.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
     app.kubernetes.io/name: oauth2-proxy
  name: oauth2-proxy
  namespace: kubernetes-dashboard
spec:
  ports:
    - name: http
      port: 4180
      protocol: TCP
      targetPort: 4180
  selector:
     app.kubernetes.io/name: oauth2-proxy

Deploy service cho oauth2-proxy

kubectl apply -f oauth2-proxy-service.yaml

Ingress

Ở đây mình dùng ingress-nginx

dashboard-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: azure-auth-oauth2
  namespace: kubernetes-dashboard
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/auth-url: "https://$host/oauth2/auth"
    nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=https://$host$request_uri$is_args$args"
    nginx.ingress.kubernetes.io/auth-response-headers: 'Authorization'
    # Proxy Authentication header to Dashboard
    nginx.ingress.kubernetes.io/configuration-snippet: |
      auth_request_set $token $upstream_http_authorization;
      proxy_set_header Authorization $token;
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
  ingressClassName: nginx
  rules:
    - host: your-dashboard-domain.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: kubernetes-dashboard
                port:
                  number: 443
  tls:
    - hosts:
        - your-dashboard-domain.com
      secretName: ssl-your-dashboard-domain
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/proxy-buffer-size: "64k"
    nginx.ingress.kubernetes.io/proxy-buffers-number: "4"
  name: oauth2-proxy
  namespace: kubernetes-dashboard
spec:
  ingressClassName: nginx
  rules:
    - host: your-dashboard-domain.com
      http:
        paths:
          - path: /oauth2
            pathType: Prefix
            backend:
              service:
                name: oauth2-proxy
                port:
                  number: 4180
  tls:
    - hosts:
        - your-dashboard-domain.com
      secretName: ssl-your-dashboard-domain

Ở line số 7 và 28 là cấu hình ssl của domain, chi tiết có thể xem thêm bài viết Tạo chứng chỉ Let’s Encrypt trên Kubernetes

Để deploy

kubectl apply -f dashboard-ingress.yaml

Kubernetes API Server

Bước tiếp theo chúng ta sẽ cấu hình kube API server để cho phép authentication qua OIDC

sudo nano /etc/kubernetes/manifests/kube-apiserver.yaml
...
  - --oidc-issuer-url=https://sts.windows.net/<Tenant-ID>/
  - --oidc-client-id=<client-id>
  - --oidc-username-claim=email
  - --oidc-groups-claim=groups

Lưu nó lại và Kuberbetes cluster sẽ tự load config mới.

RBAC

Cuối cùng, chúng ta sẽ phân quyền cho account login bằng OIDC

oidc-user.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
    namespace: kubernetes-dashboard
  - apiGroup: rbac.authorization.k8s.io
    kind: User
    name: "my-email@company.com"
kubectl apply -f oidc-user.yaml