Аутентификация в Kubernetes с помощта на GitHub OAuth и Dex

Представям ви урок за генериране на достъп до Kubernetes клъстери с помощта на Dex, dex-k8s-authenticator и GitHub.

Аутентификация в Kubernetes с помощта на GitHub OAuth и Dex
Локален мем от рускоговорящия чат на Kubernetes в Телеграм

Въведение

Използваме Kubernetes за създаване на динамични среди за екипа от разработчици и QA. По този начин искаме да им предоставим достъп до клъстера както за дашборда, така и за kubectl. За разлика от OpenShift, ваниловият Kubernetes няма вградена автентикация, затова използваме външни инструменти за тази цел.

В тази конфигурация използваме:

  • dex-k8s-authenticator  — уеб приложение за генериране на конфигурация за kubectl
  • Dex — доставчик на OpenID Connect
  • GitHub — просто защото използваме GitHub в нашата компания

Опитахме се да използваме Google OIDC, но за съжаление не успяхме да го свържем с групи, затова интеграцията с GitHub ни устройва напълно. Без мапинг на групи не можем да създадем RBAC политики основани на групи. И така, как работи нашият процес на удостоверяване в Kubernetes в визуализация:

Няколко подробности и по точки:

Аутентификация в Kubernetes с помощта на GitHub OAuth и Dex
Процес на авторизация

Потребителят се вписва в dex-k8s-authenticator (

  1. login.k8s.example.comdex-k8s-authenticator пренасочва заявката към Dex ()
  2. dex.k8s.example.comDex пренасочва към страницата за удостоверяване в GitHub)
  3. GitHub генерира необходимата информация за удостоверяване и я връща на Dex
  4. Dex предава получената информация на dex-k8s-authenticator
  5. Потребителят получава OIDC токен от GitHub
  6. dex-k8s-authenticator добавя токена в kubeconfig
  7. kubectl предава токена на KubeAPIServer
  8. KubeAPIServer на база на предадения токен връща достъп до kubectl
  9. Потребителят получава достъп от kubectl
  10. Подготовителни действия

Разбира се, вече имаме инсталиран Kubernetes клъстер (

k8s.example.com), както и предварително инсталиран HELM. Също така имаме организация в GitHub (super-org).Ако нямате HELM, инсталацията е
много проста Първо е необходимо да настроим GitHub..

Прехвърлете на страницата с настройки на организацията, (

) и създайте ново приложение (Authorized OAuth App):https://github.com/organizations/super-org/settings/applicationsСъздаване на ново приложение в GitHub
Аутентификация в Kubernetes с помощта на GitHub OAuth и Dex
Попълнете полетата с необходимите URL адреси, например:

Homepage URL:

  • Authorization callback URL: https://dex.k8s.example.com
  • Внимавайте с линковете, важно е да не загубите слешовете. https://dex.k8s.example.com/callback

В отговор на попълнената форма, GitHub ще генерира

Client secret Client ID и , запазете ги на безопасно място, те ще ни трябват (например, ние използвамеза съхранение на тайни): Vault Client ID: 1ab2c3d4e5f6g7h8 Client secret: 98z76y54x32w1

Подгответе DNS записи за субдомените

, както и SSL сертификати за ингресите. dex-k8s-authenticator пренасочва заявката към Dex ( и Dex пренасочва към страницата за удостоверяване в GitHub, както и SSL сертификати за ингресите.

Ще създадем SSL сертификати:

cat <<EOF | kubectl create -f -
apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
  name: cert-auth-dex
  namespace: kube-system
spec:
  secretName: cert-auth-dex
  dnsNames:
    - dex.k8s.example.com
  acme:
    config:
    - http01:
        ingressClass: nginx
      domains:
      - dex.k8s.example.com
  issuerRef:
    name: le-clusterissuer
    kind: ClusterIssuer
---
apiVersion: certmanager.k8s.io/v1alpha1
kind: Certificate
metadata:
  name: cert-auth-login
  namespace: kube-system
spec:
  secretName: cert-auth-login
  dnsNames:
    - login.k8s.example.com
  acme:
    config:
    - http01:
        ingressClass: nginx
      domains:
      - login.k8s.example.com
  issuerRef:
    name: le-clusterissuer
    kind: ClusterIssuer
EOF
kubectl describe certificates cert-auth-dex -n kube-system
kubectl describe certificates cert-auth-login -n kube-system

ClusterIssuer с име le-clusterissuer вече трябва да съществува, а ако не — ще го създадем с HELM:

helm install --namespace kube-system -n cert-manager stable/cert-manager
cat << EOF | kubectl create -f -
apiVersion: certmanager.k8s.io/v1alpha1
kind: ClusterIssuer
metadata:
  name: le-clusterissuer
  namespace: kube-system
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: k8s-admin@example.com
    privateKeySecretRef:
      name: le-clusterissuer
    http01: {}
EOF

Конфигурация на KubeAPIServer

За да работи kubeAPIServer, е необходимо да конфигурирате OIDC и да актуализирате кластера:

kops edit cluster
...
  kubeAPIServer:
    anonymousAuth: false
    authorizationMode: RBAC
    oidcClientID: dex-k8s-authenticator
    oidcGroupsClaim: groups
    oidcIssuerURL: https://dex.k8s.example.com/
    oidcUsernameClaim: email
kops update cluster --yes
kops rolling-update cluster --yes

Използваме kops за разгръщане на клъстери, но аналогично работи и за други мениджъри на клъстери.

Конфигурация на Dex и dex-k8s-authenticator

За да работи Dex, е необходимо да имате сертификат и ключ от Kubernetes сървъра, ще го вземем оттам:

sudo cat /srv/kubernetes/ca.{crt,key}
-----BEGIN CERTIFICATE-----
AAAAAAAAAAABBBBBBBBBBCCCCCC
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
DDDDDDDDDDDEEEEEEEEEEFFFFFF
-----END RSA PRIVATE KEY-----

Ще клонираме репозитория dex-k8s-authenticator:

git clone git@github.com:mintel/dex-k8s-authenticator.git
cd dex-k8s-authenticator/

С помощта на values файлове можем гъвкаво да конфигурираме променливи за нашите HELM чартове.

Нека опишем конфигурацията за Dex:

cat << EOF values-dex.yml
global:
  deployEnv: prod
tls:
  certificate: |-
    -----BEGIN CERTIFICATE-----
    AAAAAAAAAAABBBBBBBBBBCCCCCC
    -----END CERTIFICATE-----
  key: |-
    -----BEGIN RSA PRIVATE KEY-----
    DDDDDDDDDDDEEEEEEEEEEFFFFFF
    -----END RSA PRIVATE KEY-----
ingress:
  enabled: true
  annotations:
    kubernetes.io/ingress.class: nginx
    kubernetes.io/tls-acme: "true"
  path: /
  hosts:
    - dex.k8s.example.com
  tls:
    - secretName: cert-auth-dex
      hosts:
        - dex.k8s.example.com
serviceAccount:
  create: true
  name: dex-auth-sa
config: |
  issuer: https://dex.k8s.example.com/
  storage: # https://github.com/dexidp/dex/issues/798
    type: sqlite3
    config:
      file: /var/dex.db
  web:
    http: 0.0.0.0:5556
  frontend:
    theme: "coreos"
    issuer: "Example Co"
    issuerUrl: "https://example.com"
    logoUrl: https://example.com/images/logo-250x25.png
  expiry:
    signingKeys: "6h"
    idTokens: "24h"
  logger:
    level: debug
    format: json
  oauth2:
    responseTypes: ["code", "token", "id_token"]
    skipApprovalScreen: true
  connectors:
  - type: github
    id: github
    name: GitHub
    config:
      clientID: $GITHUB_CLIENT_ID
      clientSecret: $GITHUB_CLIENT_SECRET
      redirectURI: https://dex.k8s.example.com/callback
      orgs:
      - name: super-org
        teams:
        - team-red
  staticClients:
  - id: dex-k8s-authenticator
    name: dex-k8s-authenticator
    secret: generatedLongRandomPhrase
    redirectURIs:
      - https://login.k8s.example.com/callback/
envSecrets:
  GITHUB_CLIENT_ID: "1ab2c3d4e5f6g7h8"
  GITHUB_CLIENT_SECRET: "98z76y54x32w1"
EOF

И за dex-k8s-authenticator:

cat << EOF values-auth.yml
global:
  deployEnv: prod
dexK8sAuthenticator:
  clusters:
  - name: k8s.example.com
    short_description: "k8s cluster"
    description: "Kubernetes cluster"
    issuer: https://dex.k8s.example.com/
    k8s_master_uri: https://api.k8s.example.com
    client_id: dex-k8s-authenticator
    client_secret: generatedLongRandomPhrase
    redirect_uri: https://login.k8s.example.com/callback/
    k8s_ca_pem: |
      -----BEGIN CERTIFICATE-----
      AAAAAAAAAAABBBBBBBBBBCCCCCC
      -----END CERTIFICATE-----
ingress:
  enabled: true
  annotations:
    kubernetes.io/ingress.class: nginx
    kubernetes.io/tls-acme: "true"
  path: /
  hosts:
    - login.k8s.example.com
  tls:
    - secretName: cert-auth-login
      hosts:
        - login.k8s.example.com
EOF

Нека инсталираме Dex и dex-k8s-authenticator:

helm install -n dex --namespace kube-system --values values-dex.yml charts/dex
helm install -n dex-auth --namespace kube-system --values values-auth.yml charts/dex-k8s-authenticator

Нека проверим работоспособността на услугите (Dex трябва да върне код 400, а dex-k8s-authenticator — код 200):

curl -sI https://dex.k8s.example.com/callback | head -1
HTTP/2 400
curl -sI https://login.k8s.example.com/ | head -1
HTTP/2 200

RBAC конфигурация

Създаваме ClusterRole за групата, в нашия случай с права само за четене:

cat << EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster-read-all
rules:
  -
    apiGroups:
      - ""
      - apps
      - autoscaling
      - batch
      - extensions
      - policy
      - rbac.authorization.k8s.io
      - storage.k8s.io
    resources:
      - componentstatuses
      - configmaps
      - cronjobs
      - daemonsets
      - deployments
      - events
      - endpoints
      - horizontalpodautoscalers
      - ingress
      - ingresses
      - jobs
      - limitranges
      - namespaces
      - nodes
      - pods
      - pods/log
      - pods/exec
      - persistentvolumes
      - persistentvolumeclaims
      - resourcequotas
      - replicasets
      - replicationcontrollers
      - serviceaccounts
      - services
      - statefulsets
      - storageclasses
      - clusterroles
      - roles
    verbs:
      - get
      - watch
      - list
  - nonResourceURLs: ["*"]
    verbs:
      - get
      - watch
      - list
  - apiGroups: [""]
    resources: ["pods/exec"]
    verbs: ["create"]
EOF

Нека създадем конфигурация за ClusterRoleBinding:

cat <<EOF | kubectl create -f -
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: dex-cluster-auth
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-read-all
subjects:
  kind: Group
  name: "super-org:team-red"
EOF

Сега сме готови за тестване.

Тестове

Преминете на страницата за вход (https://login.k8s.example.com) и влезте с вашия GitHub акаунт:

Аутентификация в Kubernetes с помощта на GitHub OAuth и Dex
Страница за удостоверяване

Аутентификация в Kubernetes с помощта на GitHub OAuth и Dex
Страница за удостоверяване, пренасочена към GitHub

Аутентификация в Kubernetes с помощта на GitHub OAuth и Dex
 Следвайте генерираната инструкция, за да получите достъп

След като копираме текста от уеб страницата, можем да използваме kubectl за управление на ресурсите на нашия клъстер:

kubectl get po
NAME                READY   STATUS    RESTARTS   AGE
mypod               1/1     Running   0          3d

kubectl delete po mypod
Error from server (Forbidden): pods "mypod" is forbidden: User "amet@example.com" cannot delete pods in the namespace "default"

И това работи, всички потребители на GitHub в нашата организация могат да виждат ресурси и да влизат в подовете, но нямат права за тяхното изменение.

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster