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:

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


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
- Create Audit Policy
sudo mkdir -p /etc/kubernetes/audit
sudo mkdir -o /var/log/kubernetes/audit
- 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"]
- 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