управление_доступом_в_kubernetes

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
управление_доступом_в_kubernetes [2025/12/09 10:37]
val [Перезапуск вебинара]
управление_доступом_в_kubernetes [2025/12/19 09:44] (current)
val [Шаг 7. Использование OpenID Connect]
Line 15: Line 15:
   * [[https://​medium.com/​@subhampradhan966/​implementing-and-verifying-kubernetes-service-accounts-a-step-by-step-guide-c43b727260b2|Implementing and Verifying Kubernetes Service Accounts: A Step-by-Step Guide]]   * [[https://​medium.com/​@subhampradhan966/​implementing-and-verifying-kubernetes-service-accounts-a-step-by-step-guide-c43b727260b2|Implementing and Verifying Kubernetes Service Accounts: A Step-by-Step Guide]]
  
- +  * [[https://​medium.com/​@amirhosseineidy/​kubernetes-authentication-with-keycloak-oidc-63571eaeed61|Kubernetes authentication with keycloak oidc]] 
 +  * [[https://​vlasov.pro/​ru/​p/​kubernetes-oidc/​|Kubernetes авторизация через OIDC]] 
 +  * [[https://​timeweb.cloud/​docs/​k8s/​connect-oidc-provider-to-cluster|Подключение OIDC-провайдера к кластеру]] 
 +  * [[https://​www.talkingquickly.co.uk/​setting-up-oidc-login-kubernetes-kubectl-with-keycloak|OIDC Login to Kubernetes and Kubectl with Keycloak]] 
 +  * [[https://​github.com/​int128/​kubelogin|kubelogin - This is a kubectl plugin for Kubernetes OpenID Connect]]
  
 ===== Реклама ===== ===== Реклама =====
Line 49: Line 52:
 ==== Вариант 2.1 Использование сертификатов ==== ==== Вариант 2.1 Использование сертификатов ====
  
-  * [[Пакет OpenSSL#​Создание приватного ключа пользователя]] +<​code>​ 
-  * [[Пакет OpenSSL#Создание запроса на сертификат]]+kube1:~cat ~/​.kube/​config
  
-<​code>​ +kube1:~# echo LS0tLS1CR...LS0tLS0K ​| base64 -d
-user1@client1:~$ cat user1.req | base64 -w0+
 </​code>​ </​code>​
-  * [[https://​stackoverflow.com/​questions/​75735249/​what-do-the-values-in-certificatesigningrequest-spec-usages-mean|What do the values in CertificateSigningRequest.spec.usages mean?]] 
-<​code>​ 
-kube1:​~/​users#​ kubectl explain csr.spec.usages 
  
-kube1:~/users# cat user1.req.yaml +  * [[https://www.sslshopper.com/certificate-decoder.html|Certificate Decoder]]
-</code><​code>​ +
-apiVersion: certificates.k8s.io/v1 +
-kind: CertificateSigningRequest +
-metadata: +
-  name: user1 +
-spec: +
-  request: LS0t...S0tCg== +
-  signerName: kubernetes.io/​kube-apiserver-client +
-  expirationSeconds:​ 8640000 ​ # 100 * one day +
-  usages: +
-#  - digital signature +
-#  - key encipherment +
-  - client auth +
-</​code><​code>​ +
-kube1:​~/​users#​ kubectl apply -f user1.req.yaml+
  
-kube1:~/users# kubectl ​describe csr/user1+<​code>​ 
 +kube1:~# kubectl ​auth whoami 
 +</code>
  
-kube1:​~/​userskubectl certificate approve user1 +  * [[Система Kubernetes#Использование сертификатов]]
- +
-kube1:​~/​users#​ kubectl get csr +
- +
-kube1:​~/​users#​ kubectl get csr/user1 -o yaml +
- +
-kube1:​~/​users#​ kubectl get csr/user1 -o jsonpath="​{.status.certificate}"​ | base64 -d | tee user1.crt +
- +
-user1@client1:​~$ scp root@kube1:​users/​user1.crt . +
- +
-kube1:​~/​users#​ kubectl delete csr user1 +
-</​code>​+
  
 ==== Вариант 2.2 Использование ServiceAccount ==== ==== Вариант 2.2 Использование ServiceAccount ====
Line 105: Line 80:
 ===== Шаг 3. Использование Role и RoleBinding ===== ===== Шаг 3. Использование Role и RoleBinding =====
  
-==== Предоставление доступа к services/​proxy в Namespace ​====+  * [[Система Kubernetes#Предоставление доступа к services/​proxy в Namespace]]
  
-  * Cloud native distributed block storage for Kubernetes ​[[Система Kubernetes#longhorn]] +  * [[Система Kubernetes#​Предоставление полного доступа к Namespace]]
- +
-<​code>​ +
-kube1:~# kubectl api-resources -o wide | less +
-APIVERSION = <​group>​ + "/"​ + <version of the API> +
- +
-kube1:​~/​users#​ cat lh-svc-proxy-role.yaml +
-</​code><​code>​ +
-apiVersion: rbac.authorization.k8s.io/​v1 +
-kind: Role +
-metadata: +
-  namespace: longhorn-system +
-  name: lh-svc-proxy-role +
-rules: +
-- apiGroups: [""​] +
-  resources: ["​services/​proxy"​] +
-  verbs: ["​get"​] +
-</​code><​code>​ +
-kube1:​~/​users#​ cat user1-lh-svc-proxy-rolebinding.yaml +
-</​code><​code>​ +
-apiVersion: rbac.authorization.k8s.io/​v1 +
-kind: RoleBinding +
-metadata: +
-  name: user1-lh-svc-proxy-rolebinding +
-  namespace: longhorn-system +
-subjects: +
-- kind: User +
-  name: user1 +
-  apiGroup: rbac.authorization.k8s.io +
-roleRef: +
-  kind: Role +
-  name: lh-svc-proxy-role +
-  apiGroup: rbac.authorization.k8s.io +
-</​code><​code>​ +
-kube1:​~/​users#​ kubectl apply -f lh-svc-proxy-role.yaml,​user1-lh-svc-proxy-rolebinding.yaml +
- +
-student@client1:​~$ kubectl proxy +
- +
-student@client1:​~$ curl http://​localhost:​8001/​api/​v1/​namespaces/​longhorn-system/​services/​longhorn-frontend:​80/​proxy/​ +
- +
-student@client1:​~$ curl http://​localhost:​8001/​api/​v1/​namespaces/​kubernetes-dashboard/​services/​https:​kubernetes-dashboard:/​proxy/​ +
- +
-kube1:​~/​users#​ kubectl delete -f lh-svc-proxy-role.yaml,​user1-lh-svc-proxy-rolebinding.yaml +
-</​code>​ +
-==== Предоставление полного доступа к Namespace ​==== +
- +
-<​code>​ +
-kube1:​~/​users#​ cat ns-full-access.yaml +
-</​code><​code>​ +
---- +
-kind: Role +
-apiVersion: rbac.authorization.k8s.io/​v1 +
-metadata: +
-  name: ns-full-access +
-  namespace: my-ns +
-rules: +
-- apiGroups: ["​*"​] +
-  resources: ["​*"​] +
-  verbs: ["​*"​] +
---- +
-kind: RoleBinding +
-apiVersion: rbac.authorization.k8s.io/​v1 +
-metadata: +
-  name: ns-full-access-rolebinding +
-  namespace: my-ns +
-subjects: +
-- apiGroup: rbac.authorization.k8s.io +
-  kind: Group +
-  name: cko +
-  #kind: User +
-  #name: user1 +
-roleRef: +
-  kind: Role +
-  name: ns-full-access +
-  apiGroup: rbac.authorization.k8s.io +
-#roleRef: +
-  #apiGroup: rbac.authorization.k8s.io +
-  #kind: ClusterRole +
-  #name: admin +
-</​code><​code>​ +
-kube1:​~/​users#​ kubectl apply -f ns-full-access.yaml +
-</​code>​+
  
   * Запускаем pod my-debian ([[Система Kubernetes#​Базовые объекты k8s]]) в my-ns (создать,​ если нет)   * Запускаем pod my-debian ([[Система Kubernetes#​Базовые объекты k8s]]) в my-ns (создать,​ если нет)
  
 +  * [[Система Kubernetes#​Поиск предоставленных ролей для учетной записи]]
  
-==== Поиск предоставленных ролей для учетной записи ==== 
-<​code>​ 
-kube1:​~/​users#​ kubectl get rolebindings --all-namespaces -o=json | jq '​.items[] | select(.subjects[]?​.name == "​user1"​)'​ 
- 
-kube1:​~/​users#​ kubectl get rolebindings --all-namespaces -o=json | jq '​.items[] | select(.subjects[]?​.name == "​cko"​)'​ 
- 
-kube1:​~/​users#​ kubectl delete -f ns-full-access.yaml 
-  ИЛИ 
-kube1:​~/​users#​ kubectl -n my-ns delete rolebindings ns-full-access-rolebinding 
-kube1:​~/​users#​ kubectl -n my-ns delete role ns-full-access 
-</​code>​ 
 ===== Шаг 4. Использование ClusterRole и ClusterRoleBinding ===== ===== Шаг 4. Использование ClusterRole и ClusterRoleBinding =====
  
-==== Предоставление доступа к services/​port-forward в Cluster ​====+  * [[Система Kubernetes#Предоставление доступа к services/​port-forward в Cluster]]
  
-<​code>​ +  ​* [[Система Kubernetes#​Предоставление полного доступа к Kubernetes Cluster]]
-kube1:​~/​users#​ cat svc-pfw-role.yaml +
-</​code><​code>​ +
-apiVersion: rbac.authorization.k8s.io/​v1 +
-kind: ClusterRole +
-#kind: Role +
-metadata: +
-  name: svc-pfw-role +
-#  namespace: my-pgcluster-ns +
-rules: +
-- apiGroups: [""​] +
-  resources: ["​services"​] +
-  verbs: ["​get"​] +
-- apiGroups: [""​] +
-  resources: ["​pods"​] +
-  verbs: ["​get",​ "​list"​] +
-- apiGroups: [""​] +
-  resources: ["​pods/​portforward"​] +
-  verbs: ["​create"​] +
-</​code><​code>​ +
-kube1:​~/​users#​ cat user1-svc-pfw-rolebinding.yaml +
-</​code><​code>​ +
-apiVersion: rbac.authorization.k8s.io/​v1 +
-kind: ClusterRoleBinding +
-#kind: RoleBinding +
-metadata: +
-  name: user1-svc-pfw-rolebinding +
-#  namespace: my-pgcluster-ns +
-subjects: +
-- kind: User +
-  name: user1 +
-  apiGroup: rbac.authorization.k8s.io +
-roleRef: +
-  kind: ClusterRole +
-#  kind: Role +
-  name: svc-pfw-role +
-  apiGroup: rbac.authorization.k8s.io +
-</​code><​code>​ +
-kube1:​~/​users#​ kubectl apply -f svc-pfw-role.yaml,​user1-svc-pfw-rolebinding.yaml +
- +
-student@client1:​~$ kubectl port-forward -n my-pgcluster-ns services/​my-pgcluster-rw 5432:5432 +
- +
-student@client1:​~$ psql postgres://​keycloak:​strongpassword@127.0.0.1:​5432/​keycloak +
-</​code>​ +
- +
-  ​Доступ через proxy к [[Система Kubernetes#Kubernetes Dashboard]] +
- +
-<​code>​ +
-kube1:​~/​users#​ kubectl delete -f svc-pfw-role.yaml,​user1-svc-pfw-rolebinding.yaml +
-</​code>​ +
-==== Предоставление полного доступа к Kubernetes Cluster ​==== +
- +
-<​code>​ +
-kube1:​~/​users#​ kubectl get clusterroles | less +
- +
-kube1:​~/​users#​ kubectl get clusterrole cluster-admin -o yaml +
- +
-kube1:​~/​users#​ kubectl get clusterrolebindings | less +
- +
-kube1:​~/​users#​ kubectl get clusterrolebindings cluster-admin -o yaml +
- +
-kube1:​~/​users#​ cat user1-cluster-admin.yaml +
-</​code><​code>​ +
-apiVersion: rbac.authorization.k8s.io/​v1 +
-kind: ClusterRoleBinding +
-metadata: +
-  name: user1-cluster-admin +
-subjects: +
-- kind: User +
-  name: user1 +
-#  name: user1@corp13.un ​  +
-  apiGroup: rbac.authorization.k8s.io +
-roleRef: +
-  kind: ClusterRole +
-  name: cluster-admin +
-  apiGroup: rbac.authorization.k8s.io +
-</​code><​code>​ +
-kube1:​~/​users#​ kubectl apply -f user1-cluster-admin.yaml +
- +
-student@client1:​~$ kubectl get nodes +
-</​code>​ +
- +
-==== Поиск предоставленных кластерных ролей для учетной записи ==== +
-<​code>​ +
-kube1:​~/​users#​ kubectl get clusterrolebindings -o=json | jq '​.items[| select(.subjects[]?.name == "​kubeadm:​cluster-admins"​)'​+
  
-kube1:​~/​users#​ kubectl get clusterrolebindings -o=json | jq '​.items[] | select(.subjects[]?.name == "​user1"​)'​ +  * [[Система Kubernetes#Поиск предоставленных кластерных ролей для учетной записи]]
- +
-kube1:​~/​userskubectl get clusterrolebindings -o=json | jq '​.items[| select(.subjects[]?.name == "​default"​)'​ +
- +
-kube1:​~/​users#​ kubectl delete -f user1-cluster-admin.yaml +
-  ИЛИ +
-kube1:​~/​users#​ kubectl delete clusterrolebindings user1-cluster-admin +
-</​code>​+
  
 ===== Шаг 5. Использование JSON Web Token (JWT) для доступа в Kubernetes ===== ===== Шаг 5. Использование JSON Web Token (JWT) для доступа в Kubernetes =====
Line 308: Line 101:
  
 <​code>​ <​code>​
 +kube1:​~/​users#​ kubectl delete clusterrolebindings admin-user
 +
 kube1:​~/​users#​ kubectl delete serviceaccounts admin-user kube1:​~/​users#​ kubectl delete serviceaccounts admin-user
 +
 +user1@client1:​~$ rm -rf .kube/
 </​code>​ </​code>​
 ===== Шаг 6. Использование Service Accounts в приложениях ===== ===== Шаг 6. Использование Service Accounts в приложениях =====
Line 353: Line 150:
 </​code>​ </​code>​
  
-===== Вопросы? =====+===== Шаг 7. Использование OpenID Connect ​=====
  
-===== Домашнее задание =====+  * Сервис Keycloak [[Сервис Keycloak#​Аутентификация пользователей WEB приложения]]
  
-  - Куда и через сколько исчезает "​kubectl get csr" после "​approve"​ ?  
- 
-===== Перезапуск вебинара ===== 
 <​code>​ <​code>​
-user1@client1:​~$ rm -v user1* 
- 
-user1@client1:​~$ rm -rfv .kube/ 
- 
-kube1:​~/​users#​ kubectl delete -f ns-full-access.yaml 
- 
-kube1:~# rm -rfv users/ 
-</​code>​ 
- 
-===== Дополнительные материалы ===== 
- 
-==== oidc ==== 
-<​code>​ 
-https://​medium.com/​@amirhosseineidy/​kubernetes-authentication-with-keycloak-oidc-63571eaeed61 
- 
-https://​vlasov.pro/​ru/​p/​kubernetes-oidc/​ 
- 
-https://​github.com/​int128/​kubelogin 
- 
-https://​timeweb.cloud/​docs/​k8s/​connect-oidc-provider-to-cluster 
- 
-? https://​www.talkingquickly.co.uk/​setting-up-oidc-login-kubernetes-kubectl-with-keycloak 
- 
-Email verified 
- 
 kube1:​~/​users#​ vim /​etc/​kubernetes/​manifests/​kube-apiserver.yaml kube1:​~/​users#​ vim /​etc/​kubernetes/​manifests/​kube-apiserver.yaml
 +</​code><​code>​
 ... ...
 spec: spec:
Line 392: Line 162:
   - command:   - command:
     - kube-apiserver     - kube-apiserver
-    - --oidc-issuer-url=https://​keycloak.corp13.un/realms/corp13+    - --oidc-issuer-url=https://​keycloak.corpX.un/realms/corpX
     #- --oidc-client-id=account     #- --oidc-client-id=account
     - --oidc-client-id=any-client     - --oidc-client-id=any-client
Line 399: Line 169:
     - --oidc-groups-claim=groups     - --oidc-groups-claim=groups
 ... ...
 +</​code><​code>​
 +kube1:~# ps ax | grep kube-apiserver
  
 kube1:​~/​users#​ kubectl -n kube-system logs Pod/​kube-apiserver-kube1 kube1:​~/​users#​ kubectl -n kube-system logs Pod/​kube-apiserver-kube1
Line 404: Line 176:
 E1203 05:​22:​46.412571 ​      1 authentication.go:​73] "​Unable to authenticate the request"​ err="​[invalid bearer token, oidc: verify token: oidc: expected audience \"​any-client\"​ got [\"​account\"​]]"​ E1203 05:​22:​46.412571 ​      1 authentication.go:​73] "​Unable to authenticate the request"​ err="​[invalid bearer token, oidc: verify token: oidc: expected audience \"​any-client\"​ got [\"​account\"​]]"​
 ... ...
 +E1218 10:​36:​21.105422 ​      1 authentication.go:​75] "​Unable to authenticate the request"​ err="​[invalid bearer token, oidc: email not verified]"​
 +...
 +</​code>​
 +
 +  * [[Сервис Keycloak#​Проверка получения токена]] Keycloak ​
 +  * [[Система Kubernetes#​Создание файла конфигурации kubectl]] c полученным токеном
 +
 +<​code>​
 +client1:~# wget https://​github.com/​int128/​kubelogin/​releases/​download/​v1.35.0/​kubelogin_linux_amd64.zip
 +
 +client1:~# unzip kubelogin_linux_amd64.zip
 +
 +client1:~# mv kubelogin /​usr/​local/​bin/​
  
 user1@client1:​~$ cat .kube/​config user1@client1:​~$ cat .kube/​config
-apiVersion: v1 +</​code><​code>​ 
-clusters: +...
-- cluster: +
-    certificate-authority-data: ​... +
-    server: https://​192.168.13.221:​6443 +
-  name: cluster.local +
-contexts: +
-- context: +
-    cluster: cluster.local +
-    user: user1 +
-  name: default-context +
-current-context:​ default-context +
-kind: Config +
-preferences:​ {}+
 users: users:
 - name: user1 - name: user1
Line 432: Line 205:
         #​refresh-token: ​         #​refresh-token: ​
       name: oidc       name: oidc
 +</​code><​code>​
 +user1@client1:​~$ kubelogin
  
 +user1@client1:​~$ kubectl auth whoami
 </​code>​ </​code>​
-==== Auditing ====+ 
 +  * [[Система Kubernetes#​Предоставление полного доступа к Kubernetes Cluster]] 
 + 
 +===== Вопросы?​ ===== 
 + 
 +===== Домашнее задание ===== 
 + 
 +  - Куда и через сколько исчезает "​kubectl get csr" после "​approve"​ ?  
 + 
 +===== Перезапуск вебинара ===== 
 +<​code>​ 
 +user1@client1:​~$ rm -v user1* 
 + 
 +user1@client1:​~$ rm -rfv .kube/ 
 + 
 +kube1:~# rm -rfv users/ 
 +</​code>​ 
 + 
 +===== Дополнительные материалы ===== 
 + 
 +==== Черновик ​Auditing ====
 <​code>​ <​code>​
 https://​habr.com/​ru/​companies/​slurm/​articles/​711868/​|Журналы аудита Kubernetes: лучшие практики и настройка https://​habr.com/​ru/​companies/​slurm/​articles/​711868/​|Журналы аудита Kubernetes: лучшие практики и настройка
Line 486: Line 282:
  
 user1@client1:​~$ kubectl -n my-apwebd-ns delete pod my-webd-<​TAB>​ user1@client1:​~$ kubectl -n my-apwebd-ns delete pod my-webd-<​TAB>​
 +</​code>​
 +
 +==== Черновик DEX ====
 +
 +=== Описание ===
 +<​code>​
 +Создаём группы и пользователей под Kubernetes
 +У нас уже есть настроенная Freeipa
 +FreeIPA — это серверная система для централизованного управления пользователями,​ группами,​ доступами,​ сертификатами и DNS в инфраструктуре.
 +Заходим на freeipa, через web интерфейс или же можно воспользоваться консолью
 +https://​ipa-server-1.teach.local/​
 +ssh root@192.168.100.252
 +Мы воспользуемся консолью чтобы сэкономить время
 +Но предварительно на web проверим что нет групп для ​ кубернетис
 +Используем команду kinit чтобы получить билет Kerberos и введем команды для создания
 +
 +ipa group-add k8s-cluster-admins \
 +  --desc="​Kubernetes cluster admins"​
 +
 +ipa group-add k8s-ns-core-test-view \
 +  --desc="​View access to core-test namespace"​
 +
 +ipa group-add k8s-ns-core-test-admin \
 +  --desc="​Admin access to core-test namespace"​
 +ipa group-add k8s-ns \
 +--desc="​Access only view all ns"
 +
 +Теперь обновим страницу с группами и увидим созданные нами группы
 +Далее Создаём тестового пользователя
 +ipa user-add ivan \
 +  --first=Ivan \
 +  --last=Petrov \
 +  --password
 +
 +ipa user-add sergey \
 +  --first=Sergey \
 +  --last=Admin \
 +  --password
 +
 +
 +ipa user-add kirill \
 +  --first=Kirill \
 +  --last=Viewer \
 +  --password
 +ipa user-add ira \
 +  --first=Irina\
 +  --last=Viewer \
 +  --password
 +
 +
 +Далее попросят ввести пароль
 +Вводим пароль 123456
 +И подтверждаем
 +Конечно такой пароль только для демонстрации а не для продового использования
 +Добавляем пользователя в группу
 +
 +ipa group-add-member k8s-ns-core-test-view --users=ivan
 +ipa group-add-member k8s-ns-core-test-admin --users=kirill
 +ipa group-add-member k8s-ns --users=ira
 +ipa group-add-member k8s-cluster-admins --users=sergey
 +
 +Далее Аккаунт для Dex в FreeIPA (LDAP bind user)
 +Dex должен логиниться в LDAP FreeIPA с каким-то пользователем.
 +
 +ipa user-add dex-bind \
 +  --first=Dex \
 +  --last=Bind \
 +  --password
 +
 +Проверяем LDAP-доступ к FreeIPA
 +Чтобы ​ убедится что dex сможет залогинется
 +
 +
 +Зайдем на сервер c которого будем управлять k8s и выполнил поиск нашего пользователя
 +ssh root@192.168.100.249
 +
 +ldapsearch -x   -H ldap://​192.168.100.252:​389 ​  -D "​uid=dex-bind,​cn=users,​cn=accounts,​dc=teach,​dc=local" ​  ​-W ​  -b "​cn=users,​cn=accounts,​dc=teach
 +,​dc=local" ​  "​(uid=ivan)"​
 +
 +Подключимся пользователем dex-bind
 +И поищем созданного нами пользователя ivan
 +Видим что все ок данные получаем
 +
 +Далее настроим установим и настроим dex
 +Для этого будем использовать helm
 +Helm — это менеджер пакетов для Kubernetes, грубо говоря:​
 +«apt/yum для Kubernetes
 +
 +
 +Нам понадобится серт мэнеджер для выпуска сетификатов и ингресс контроллер
 +
 +
 +helm repo add jetstack https://​charts.jetstack.io
 +helm repo update
 +
 +helm install cert-manager jetstack/​cert-manager \
 +  --namespace cert-manager \
 +  --create-namespace \
 +  --set crds.enabled=true
 +
 +
 +helm repo add ingress-nginx https://​kubernetes.github.io/​ingress-nginx
 +helm repo update
 +
 +helm install ingress-nginx ingress-nginx/​ingress-nginx \
 +  -n ingress-nginx --create-namespace \
 +  --set controller.ingressClassResource.name=nginx \
 +  --set controller.ingressClassByName=true \
 +  --set controller.hostNetwork=true \
 +  --set controller.dnsPolicy=ClusterFirstWithHostNet \
 +  --set controller.kind=DaemonSet \
 +  --set controller.service.type=NodePort
 +
 +
 +Перезагружаем сервера
 +
 +
 +
 +Начиная с новых версий FreeIPA, в нём есть ACME-сервер
 +ACME-server — это “серверная сторона автоматики сертификатов”.
 +ACME (Automatic Certificate Management Environment) — это протокол,​ по которому:​
 +клиент (cert-manager,​ acme.sh, lego, certbot и т.п.)
 +общается с CA (центром сертификации) через ACME-server
 +чтобы автоматически выпускать и обновлять TLS-сертификаты.
 +Примеры ACME-серверов:​
 +Let’s Encrypt (самый известный;​ их сервер — Boulder)
 +
 +
 +
 +ipa-acme-manage enable
 +ipa-acme-manage status
 +
 +
 +появится эндпоинт
 +
 +https://​ipa-server-1.teach.local/​acme/​directory
 +
 +curl -vk https://​ipa-server-1.teach.local/​acme/​directory
 +
 +далее получаем сертифкат freeipa корневой
 +идем на сервер freeipa
 +
 +sudo cat /​etc/​ipa/​ca.crt > ipa-ca.crt
 +далее переводим в base64
 +base64 -w0 ipa-ca.crt > ipa-ca.b64
 +
 +затем нам нужен ClusterIssuer
 +
 +ClusterIssuer — это кластерный “поставщик сертификатов” в cert-manager,​ который виден во всех неймспейсах Kubernetes.
 +Говоря по-человечески:​
 +cert-manager — это оператор,​ который умеет автоматически выпускать и обновлять сертификаты.
 +ClusterIssuer/​Issuer — это “настройка,​ куда идти за сертификатом и как его получать”.
 +
 +Файл issuser.txt
 +И caBundle ПОДСТАВЬ_ЗДЕСЬ_СТРОКУ_ИЗ_ipa-ca.b64
 +
 +
 +apiVersion: cert-manager.io/​v1
 +kind: ClusterIssuer
 +metadata:
 +  name: freeipa-acme
 +spec:
 +  acme:
 +    email: admin@teach.local
 +    server: https://​ipa-server-1.teach.local/​acme/​directory
 +    privateKeySecretRef:​
 +      name: freeipa-acme-account-key
 +
 +    # ВАЖНО: одна длинная строка из ipa-ca.b64
 +    caBundle: ПОДСТАВЬ_ЗДЕСЬ_СТРОКУ_ИЗ_ipa-ca.b64
 +
 +    solvers:
 +      - http01:
 +          ingress:
 +            ingressClassName:​ nginx
 +
 +
 +1. Выпускаем сертификат для Dex
 +Сделаем Certificate,​ который:​
 +использует твой ClusterIssuer freeipa-acme;​
 +кладёт сертификат в Secret dex-tls в namespace dex.
 +
 +
 +Для начала нам нужна dns запись
 +Посмотрим какие ip у серверов k8s
 +kubectl get nodes -o wide
 +В freeipa
 +
 +ipa dnsrecord-add teach.local dex --a-rec=192.168.100.229
 +это адрес одной из наших нод
 +
 +Создаем нейаспейс
 +kubectl create ns dex
 +
 +затем применяем файл ​ с запросом сетификата
 +файл certificate.txt
 +
 +apiVersion: cert-manager.io/​v1
 +kind: Certificate
 +metadata:
 +  name: dex-cert
 +  namespace: dex
 +spec:
 +  secretName: dex-tls
 +  dnsNames:
 +    - dex.teach.local
 +  issuerRef:
 +    name: freeipa-acme
 +    kind: ClusterIssuer
 +
 +Добавляем репозиторий ​ с dex
 +
 +
 +helm repo add dex https://​charts.dexidp.io
 +helm repo update
 +
 +Качаем локально хелм чарт
 +helm pull dex/dex
 +
 +У нас скачивается архив с helm чартом
 +ls
 +далее распаковываем архив
 +tar -xvf dex-0.24.0.tgz
 +переходим в каталог
 +cd dex
 +
 +
 +и тут нас интересует файл values.yaml
 +vi values.yml
 +открываем файл и редактируем берем пример из файла config.txt
 +нужно сгенерить секрет
 +openssl rand -hex 32
 +и заменить SUPER-SECRET-STRING на полученный секрет
 +Создаем секрет
 +
 +kubectl -n dex create secret generic dex-ldap-bind \
 +  --from-literal=DEX_LDAP_BIND_DN='​uid=dex-bind,​cn=users,​cn=accounts,​dc=teach,​dc=local'​ \
 +  --from-literal=DEX_LDAP_BIND_PW='​123456'​
 +
 +
 +сохраняем и применяем
 +helm upgrade --install dex .   -n dex   -f values.yaml
 +Тест с любой машины,​ где dex.teach.local резолвится в IP ноды:
 +curl -vk https://​dex.teach.local/​dex/​.well-known/​openid-configuration
 +Кладём CA FreeIPA на мастер
 +Переходим на мастер ноду
 +ssh root@192.168.100.230
 +scp root@ipa-server-1.teach.local:/​etc/​ipa/​ca.crt /​root/​ipa-ca.crt
 +sudo cp /​root/​ipa-ca.crt /​etc/​kubernetes/​ssl/​dex-ca.crt
 +
 +Затем правим настройки kubeapi
 +
 +vi /​etc/​kubernetes/​manifests/​kube-apiserver.yaml
 +
 +Добавляем
 +
 +- --oidc-issuer-url=https://​dex.teach.local/​dex
 +- --oidc-client-id=dex-k8s-authenticator
 +- --oidc-username-claim=email
 +- --oidc-groups-claim=groups
 +- --oidc-ca-file=/​etc/​kubernetes/​ssl/​dex-ca.crt
 +
 +Kubeapi сам перезагрузится
 +
 +Если все ок то в браузере перейдя по ссылке увидим ответ от dex
 +https://​dex.teach.local/​dex/​.well-known/​openid-configuration
 +
 +отлично dex установлен но Dex сам по себе — только ​ (OIDC-провайдер).
 +Страничку,​ где после логина рисуется готовый kubeconfig, делает другой сервис — dex-k8s-authenticator.
 +
 +
 +kubectl create namespace dex-auth
 +
 +
 +Добавляем на freeipa dns запись
 +
 +ipa dnsrecord-add teach.local auth --a-ip-address=192.168.100.229
 +ipa dnsrecord-show teach.local auth
 +выпускаем сертификат для web интерфейса
 +kubectl apply -f ../​certificate-auth.yaml
 +
 +Ставим dex-k8s-authenticator
 +
 +helm repo add wiremind https://​wiremind.github.io/​wiremind-helm-charts
 +helm repo update
 +helm pull wiremind/​dex-k8s-authenticator
 +
 +tar -xvf  dex-k8s-authenticator-1.7.0.tgz
 +
 +cd dex-k8s-authenticator
 +
 +vi values.yaml
 +
 +в вэлюсах указываем наши данные
 +вначале копируем содержимое файла certificate-auth.txt
 +
 +secret: тут должен совпадать с секретов в values dex
 +далее добавить CA Freeipa в файл конфига
 +caCerts:
 +  enabled: true
 +  secrets:
 +    - name: ipa-ca
 +      filename: ipa-ca.crt
 +      value: |-
 +
 +
 +идем на сервер Freeipa
 +выполняем команду чтобы получить серт в base64
 +cat /​etc/​ipa/​ca.crt | base64 -w0 > ipa-ca.b64
 +
 +
 +в k8s_ca_pem:
 +указываем CA кубернетис
 +идем на ноду мастера k8s
 +
 +cat /​etc/​kubernetes/​ssl/​ca.crt
 +
 +helm upgrade --install dex-auth .   -n dex-auth ​  -f values.yaml
 +
 +Теперь нас необходимо связать группы в k8s и freeipa
 +Применяем манифесты для добавления кластер ролей
 +
 +kubectl create ns core-test-admin
 +kubectl create ns core-test-view
 +
 +проверяем заходим на https://​auth.teach.local/​
 +
 +пробуем залогинится под польз кто админ
 +
 +Заходим на другой сервер и проверяем команды которые нам дал dex
 +
 +ssh root@192.168.100.227
 +
 +Вводим команды из web интерфейса
 +
 +И пробуем подключиться
 +
 +Далее запускаем тестовые поды в наших ns
 +
 +Применяем файл ​ test-pod.txt
 +
 +И тестируем права
 +
 +Пробуем заходить разными польз
 +
 +Если не пускает польз когда у него права только на один ns то надо дать права на просмотр.
 +</​code>​
 +
 +=== Файлы ===
 +<​code>​
 +=== role.txt ===
 +apiVersion: rbac.authorization.k8s.io/​v1
 +kind: ClusterRoleBinding
 +metadata:
 +  name: k8s-admins
 +subjects:
 +  - kind: Group
 +    name: k8s-cluster-admins ​        # ИМЯ ГРУППЫ из FreeIPA
 +    apiGroup: rbac.authorization.k8s.io
 +roleRef:
 +  kind: ClusterRole
 +  name: cluster-admin
 +  apiGroup: rbac.authorization.k8s.io
 +---
 +# 1) Админы НС core-test-admin
 +apiVersion: rbac.authorization.k8s.io/​v1
 +kind: RoleBinding
 +metadata:
 +  name: core-test-admin-admins
 +  namespace: core-test-admin
 +subjects:
 +  - kind: Group
 +    name: k8s-ns-core-test-admin ​         # ГРУППА из токена Dex / FreeIPA
 +    apiGroup: rbac.authorization.k8s.io
 +roleRef:
 +  kind: ClusterRole
 +  name: admin                             # встроенная роль с полным доступом в ns
 +  apiGroup: rbac.authorization.k8s.io
 +---
 +# 2) Вьюеры НС core-test-view
 +apiVersion: rbac.authorization.k8s.io/​v1
 +kind: RoleBinding
 +metadata:
 +  name: core-test-view-viewers
 +  namespace: core-test-view
 +subjects:
 +  - kind: Group
 +    name: k8s-ns-core-test-view ​          # ГРУППА для read-only в этом ns
 +    apiGroup: rbac.authorization.k8s.io
 +roleRef:
 +  kind: ClusterRole
 +  name: view                              # встроенная read-only роль для ns
 +  apiGroup: rbac.authorization.k8s.io
 +---
 +# 3) Read-only по всему кластеру для группы k8s-ns
 +apiVersion: rbac.authorization.k8s.io/​v1
 +kind: ClusterRoleBinding
 +metadata:
 +  name: k8s-ns-read-all
 +subjects:
 +  - kind: Group
 +    name: k8s-ns ​                          # ГРУППА "​общие зрители k8s"
 +    apiGroup: rbac.authorization.k8s.io
 +roleRef:
 +  kind: ClusterRole
 +  name: view                               # cluster-wide view
 +  apiGroup: rbac.authorization.k8s.io
 +
 +
 +kubectl apply -f k8s-admins-rbac.yaml
 +kubectl get clusterrolebinding k8s-admins -o yaml
 +
 +=== issuer.txt ===
 +apiVersion: cert-manager.io/​v1
 +kind: ClusterIssuer
 +metadata:
 +  name: freeipa-acme
 +spec:
 +  acme:
 +    email: admin@teach.local
 +    server: https://​ipa-server-1.teach.local/​acme/​directory
 +    privateKeySecretRef:​
 +      name: freeipa-acme-account-key
 +
 +    # ВАЖНО: одна длинная строка из ipa-ca.b64
 +    caBundle: ПОДСТАВЬ_ЗДЕСЬ_СТРОКУ_ИЗ_ipa-ca.b64
 +
 +    solvers:
 +      - http01:
 +          ingress:
 +            ingressClassName:​ nginx
 +
 +=== dex-auth-values.txt ===
 +global:
 +  deployEnv: dev
 +
 +image:
 +  repository: mintel/​dex-k8s-authenticator
 +  tag: 1.4.0
 +  pullPolicy: Always
 +
 +dexK8sAuthenticator:​
 +  port: 5555
 +  debug: true
 +  web_path_prefix:​ /
 +  clusters:
 +    - name: teach-cluster
 +      short_description:​ "​Учебный кластер"​
 +      description:​ "​Kubespray кластер teach.local"​
 +
 +      # ДОЛЖНО совпадать с issuer у Dex и --oidc-issuer-url у kube-apiserver
 +      issuer: https://​dex.teach.local/​dex
 +
 +      # Адрес API-сервера кластера
 +      k8s_master_uri:​ https://​192.168.100.230:​6443
 +
 +      # Те же client_id / secret, что в staticClients Dex
 +      client_id: dex-k8s-authenticator
 +      client_secret:​ 9f3b2e3a7a8d14d0a5ff4b1b8e92c3de0b6b7f21a4e59bd8c1f3d2e7c8a9b0c1
 +
 +      # ДОЛЖНО 1-в-1 совпадать с redirectURIs в Dex для этого клиента
 +  ​
 +      redirect_uri:​ https://​auth.teach.local/​callback
 +
 +      k8s_ca_pem: |
 +        -----BEGIN CERTIFICATE-----
 +        ТУТ ЦЕЛИКОМ СОДЕРЖИМОЕ /​etc/​kubernetes/​ssl/​ca.crt
 +        БЕЗ base64, как есть
 +        -----END CERTIFICATE-----
 +
 +service:
 +  type: ClusterIP
 +  port: 5555
 +
 +ingress:
 +  enabled: true
 +  ingressClassName:​ nginx
 +  annotations:​ {}
 +  labels: {}
 +
 +  # В ЭТОМ чарте path один, для всех хостов:​
 +  path: /
 +
 +  # hosts — это СПИСОК СТРОК, а не объектов:​
 +  hosts:
 +    - auth.teach.local
 +
 +  tls:
 +    - secretName: dex-auth-tls
 +      hosts:
 +        - auth.teach.local
 +
 +# Чтобы убрать x509: unknown authority для Dex (FreeIPA CA)
 +caCerts:
 +  enabled: true
 +  secrets:
 +    - name: ipa-ca
 +      filename: ipa-ca.crt
 +      value: |-
 +        ТУТ_ОДНА_СТРОКА_BASE64_ОТ /​etc/​ipa/​ca.crt
 +   
 +=== config.txt ===
 +replicaCount:​ 1
 +
 +image:
 +  repository: ghcr.io/​dexidp/​dex
 +  tag: v2.44.0
 +  pullPolicy: IfNotPresent
 +
 +service:
 +  type: ClusterIP
 +  ports:
 +    http:
 +      port: 5556
 +
 +https:
 +  enabled: false
 +
 +grpc:
 +  enabled: false
 +
 +rbac:
 +  create: true
 +
 +podDisruptionBudget:​
 +  enabled: false
 +
 +networkPolicy:​
 +  enabled: false
 +
 +autoscaling:​
 +  enabled: false
 +
 +ingress:
 +  enabled: true
 +  className: nginx
 +  hosts:
 +    - host: dex.teach.local
 +      paths:
 +        - path: /dex/
 +          pathType: ImplementationSpecific
 +  tls:
 +    - secretName: dex-tls ​         # СЕКРЕТ,​ который делает cert-manager/​FreeIPA
 +      hosts:
 +        - dex.teach.local
 +
 +configSecret:​
 +  create: true
 +
 +serviceMonitor:​
 +  enabled: false
 +
 +serviceAccount:​
 +  create: true        # или false, если не нужен отдельный SA
 +  name: "" ​           # пусто = helm сам сгенерит имя по release
 +  annotations:​ {}
 +
 +config:
 +  issuer: https://​dex.teach.local/​dex
 +
 +  storage:
 +    type: kubernetes
 +    config:
 +      inCluster: true
 +    type: memory
 +
 +  web:
 +    http: 0.0.0.0:​5556
 +
 +  logger:
 +    level: debug
 +    format: text
 +
 +  oauth2:
 +    skipApprovalScreen:​ true
 +
 +  staticClients:​
 +    - id: example-app
 +      name: Example App
 +      secret: example-app-secret
 +      redirectURIs:​
 +        - http://​127.0.0.1:​5555/​callback
 +    - id: dex-k8s-authenticator
 +      name: Dex K8s Authenticator
 +      secret: SUPER-SECRET-STRING ​
 +      redirectURIs:​
 +        - https://​auth.teach.local/​callback
 +
 +
 +  connectors:
 +    - type: ldap
 +      id: freeipa
 +      name: FreeIPA
 +      config:
 +        host: 192.168.100.252:​389
 +        insecureNoSSL:​ true
 +        startTLS: false
 +
 +        bindDN: "​uid=dex-bind,​cn=users,​cn=accounts,​dc=teach,​dc=local"​
 +        bindPW: "​123456"​
 +
 +        userSearch:
 +          baseDN: "​cn=users,​cn=accounts,​dc=teach,​dc=local"​
 +          filter: "​(objectClass=person)"​
 +          emailAttr: "​mail"​
 +          idAttr: "​uid"​
 +          nameAttr: "​cn"​
 +          username: "​uid"​
 +
 +        groupSearch:​
 +          baseDN: "​cn=groups,​cn=accounts,​dc=teach,​dc=local"​
 +          filter: "​(objectClass=groupofnames)"​
 +          userAttr: "​dn"​
 +          groupAttr: "​member"​
 +          nameAttr: "​cn"​
 +
 +
 +=== certificate-auth.txt ===
 +apiVersion: cert-manager.io/​v1
 +kind: Certificate
 +metadata:
 +  name: dex-auth-cert
 +  namespace: dex-auth
 +spec:
 +  secretName: dex-auth-tls
 +  dnsNames:
 +    - auth.teach.local
 +  issuerRef:
 +    name: freeipa-acme
 +    kind: ClusterIssuer
 +
 +=== certificate.txt ===
 +apiVersion: cert-manager.io/​v1
 +kind: Certificate
 +metadata:
 +  name: dex-cert
 +  namespace: dex
 +spec:
 +  secretName: dex-tls
 +  dnsNames:
 +    - dex.teach.local
 +  issuerRef:
 +    name: freeipa-acme
 +    kind: ClusterIssuer
 +
 +=== test-pod.txt ===
 +apiVersion: v1
 +kind: Pod
 +metadata:
 +  name: admin-nginx
 +  namespace: core-test-admin
 +  labels:
 +    app: admin-nginx
 +spec:
 +  containers:
 +    - name: nginx
 +      image: nginx:1.27
 +      ports:
 +        - containerPort:​ 80
 +---
 +apiVersion: v1
 +kind: Pod
 +metadata:
 +  name: view-nginx
 +  namespace: core-test-view
 +  labels:
 +    app: view-nginx
 +spec:
 +  containers:
 +    - name: nginx
 +      image: nginx:1.27
 +      ports:
 +        - containerPort:​ 80
 </​code>​ </​code>​
управление_доступом_в_kubernetes.1765265868.txt.gz · Last modified: 2025/12/09 10:37 by val