0

Tích hợp công cụ kubectl với keycloak kết hợp MFA

Hướng dẫn tích hợp công cụ kubectl với keycloak làm MFA

Để tích hợp công cụ kubectl với keycloak làm MFA và quản lý user thông qua LDAP hoặc userlocal cần các công cụ : kubectl, keycloak, kubelogin plugin

Lưu ý: K8s cluster mình sử dụng kubeadm

Cài đặt

Cài đặt thành phần keycloak trên K8s, do môi trường lab nên cài đặt luôn thành phần postgres trên K8s và sử dụng công cụ openssl gen cert để cài đặt thành phần keycloak dùng HTTPS

kubectl create ns keycloak

1. Install PostgresDB

kubectl create \
  -f https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/main/releases/cnpg-1.27.0.yaml

Tạo file postgres.yaml thực hiện cài đặt postgres trên k8s

---
apiVersion: v1
kind: Secret
metadata:
  name: postgres
  namespace: keycloak
type: kubernetes.io/basic-auth
stringData:
  username: postgres
  password: admin123

---
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: postgres
  namespace: keycloak
spec:
  instances: 1
  enablePDB: false
  enableSuperuserAccess: true
  superuserSecret:
    name: postgres
  storage:
    size: 1Gi
kubectl apply -f postgres.yaml -n keycloak

2. Install Keycloak using HelmChart

Gen cert phục vụ triển khai keycloak. Sử dụng công cụ Openssl

openssl	req	-x509	-newkey	rsa:2048	-sha256	-days	3650	-nodes	\-keyout	keycloak.key	-out	keycloak.crt	\-subj	"/CN=keycloak.local"	\-addext	"subjectAltName=DNS:keycloak.local,IP:<NODE_IP>

Create secrets từ cert

kubectl	create	secret	generic	keycloak-tls	\-n	keycloak	\--from-file=tls.crt=keycloak.crt	
helm repo add codecentric https://codecentric.github.io/helm-charts
helm repo update codecentric
helm search repo codecentric/keycloakx --versions
helm fetch codecentric/keycloakx --version 7.1.9 --untar
helm	upgrade	--install	keycloak	codecentric/keycloakx	-n	keycloak	-f	override.yaml

Thực hiện copy CA cert sang master node hoặc VM có cài đặt công cụ kubectl có kết nối đển K8s cluster

scp keycloak.crt master-node:/etc/kubernetes/pki/keycloak-ca.crt

3. Setup Keycloak enable MFA

3.1. Tạo Realm và Client cho kubectl
  • Tạo realm mới: k8s

  • Tạo client:

    • Client ID: kubectl
    • Client type: OpenID Connect
    • Client authentication: On
    • Standard flow: Enable
    • Valid redirect URI: http://localhost:8080/* và urn:ief:wg:oauth:2.0:oob
  • Lấy Client Secret tại tab Credentials

    3.2. Tạo Group và Mapper cho claim

Tạo group: k8s-admins và add user test vào group

Vào Clients -> kubectl -> Client scopes -> kubectl-dedicated -> Add mapper -> By configuration -> Group Membership

  • Token Claim Name: groups

  • Full group path: Off

  • Add to ID token: On

  • Add to access token: On

    3.3. Enable MFA (OTP)

Authentication -> Required Actions -> Enable Configure OTP, set Default Action = On

4. Install kubectl + kubelogin

Install krew

(
set	-x;	cd	"$(mktemp	-d)"	&&
OS="$(uname	|	tr	'[:upper:]'	'[:lower:]')"	&&
ARCH="$(uname	-m	|	sed	-e	's/x86_64/amd64/'	-e	's/\(arm\)\(64\)\?.*/\1\2/'	-e	's/aarch64$/arm64/')"	&&
KREW="krew-${OS}_${ARCH}"	&&
curl	-fsSLO	"https://github.com/kubernetes-sigs/krew/releases/latest/download/${KREW}.tar.gz"	&&
tar	zxvf	"${KREW}.tar.gz"	&&
./"${KREW}"	install	krew
)
echo	'export	PATH="

Install plugin oidc-login

kubectl krew install oidc-login
kubectl oidc-login version

5. Config kubeconfig

kubectl config set-credentials viewer-oidc \
  --exec-api-version=client.authentication.k8s.io/v1beta1 \
  --exec-command=kubectl \
  --exec-arg=oidc-login \
  --exec-arg=get-token \
  --exec-arg=--oidc-issuer-url=https://<endpoint-keycloak>/auth/realms/k8s \
  --exec-arg=--oidc-client-id=kubectl \
  --exec-arg=--oidc-client-secret=<CLIENT_SECRET> \
  --exec-arg=--certificate-authority=/etc/kubernetes/pki/keycloak-ca.crt \
  --exec-arg=--grant-type=authcode-keyboard \
  --exec-arg=--oidc-redirect-url=urn:ietf:wg:oauth:2.0:oob

6. Tạo kube config context

kubectl config get-contexts 

kubectl config set-context keycloak-context  \
    --cluster=kubernetes \
    --user=keycloak-user
    
kubectl config use-context keycloak-context

7. Config kube-apiserver

Thêm đoạn cấu hình sau vào /etc/kubernets/manifest/kube-apiserver.yaml

    - --oidc-issuer-url=https://<endpoint-keycloak>/auth/realms/k8s
    - --oidc-client-id=kubectl
    - --oidc-username-claim=preferred_username
    - --oidc-groups-claim=groups
    - "--oidc-username-prefix=oidc:"
    - "--oidc-groups-prefix=oidc:"
    - --oidc-ca-file=/etc/kubernetes/pki/keycloak-ca.crt

Demo

Trên giao diện keycloak thực hiện tạo Group, User và assign user vào group. Ví dụ tên group là: k8s-admins

Sau đó tạo ClusterRoleBinding theo group. Ví dụ:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: keycloak-admins-binding
subjects:
  - kind: Group
    name: "oidc:k8s-admins"
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io

Như vậy mỗi user được assign vào group k8s-admins thì đều có quyển cluster admin của K8s cluster

Trên terminal master node thực hiện lệnh kubectl bình thường -> sau đó xuất hiện link trỏ đến keycloak:

image.png

Thực hiện login và nhập mã OTP để login và lấy code sau đó paste vào terminal là xong.

image.png

image.png

Có thể tạo Group cho phép các user chỉ có quyển view vào 1 namesapce nhất định. Phù hợp với use-case phân quyền cho Dev vào view các object trong namespace deploy ứng dụng

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: keycloak-viewers-orders
  namespace: openebs
subjects:
  - kind: Group
    name: "oidc:k8s-viewer-openebs"
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: view
  apiGroup: rbac.authorization.k8s.io

Cấu hình đẩy Audit-logs

Do quản lý user thông qua keycloak nên với use-case phù hợp với việc audit-logs. Vì vậy mình có setup đẩy audit logs ra để dễ dàng truy xuất khi cần về sau

  1. Create Audit Policy
sudo mkdir -p /etc/kubernetes/audit
sudo mkdir -o /var/log/kubernetes/audit
  1. Create /etc/kubernetes/audit/audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
omitStages:
  - "RequestReceived"   # bỏ qua giai đoạn "nhận request" (log thừa, log kết quả là đủ)

rules:

  # Log ĐẦY ĐỦ (kèm nội dung request/response) mọi hành động ghi/sửa/xóa của user qua OIDC
  # -> đây là phần quan trọng nhất để truy vết "ai làm gì"
  - level: RequestResponse
    verbs: ["create", "update", "patch", "delete"]
    userGroups: ["oidc:k8s-admins", "oidc:k8s-operators"]

  - level: RequestResponse
    resources:
      - group: ""
        resources: ["pods/exec", "pods/attach", "pods/portforward"]

  1. Thêm các flags sau vào kube-apiserver và mount policy audit logs
    - --audit-policy-file=/etc/kubernetes/audit/audit-policy.yaml
    - --audit-log-path=/var/log/kubernetes/audit/audit.log
    - --audit-log-maxage=30
    - --audit-log-maxbackup=10
    - --audit-log-maxsize=100
    - --audit-log-format=json
    volumeMounts:
    - mountPath: /etc/kubernetes/audit/audit-policy.yaml
      name: audit-policy
    - mountPath: /var/log/kubernetes/audit/
      name: audit-log
  volumes:
  - name: audit-policy
    hostPath:
      path: /etc/kubernetes/audit/audit-policy.yaml
      type: File
  - name: audit-log
    hostPath:
      path: /var/log/kubernetes/audit/
      type: DirectoryOrCreate

All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí