Autentificarea în Kubernetes cu GitHub OAuth și Dex

Vă prezint un tutorial pentru generarea accesului la un cluster Kubernetes cu ajutorul Dex, dex-k8s-authenticator și GitHub.

Autentificarea în Kubernetes cu GitHub OAuth și Dex
Un meme local din chatul în limba rusă Kubernetes în Telegram

Introducere

Folosim Kubernetes pentru a crea medii dinamice pentru echipa de dezvoltare și QA. Astfel, dorim să le oferim acces la cluster atât pentru tablou, cât și pentru kubectl. Spre deosebire de OpenShift, Kubernetes pur nu are autentificare nativă, așa că folosim instrumente externe pentru acest lucru.

În această configurație folosim:

  • dex-k8s-authenticator  — aplicație web pentru generarea configurării kubectl
  • Dex — furnizor OpenID Connect
  • GitHub — pur și simplu pentru că folosim GitHub în compania noastră

Am încercat să folosim Google OIDC, dar din păcate nu ne a reușit să le configurăm cu grupurile, așa că integrarea cu GitHub ne-a satisfăcut pe deplin. Fără maparea grupurilor, nu se vor putea crea politici RBAC bazate pe grupuri.

Așadar, cum funcționează procesul nostru de autorizare în Kubernetes, prezentat vizual:

Autentificarea în Kubernetes cu GitHub OAuth și Dex
Procesul de autentificare

Puțin mai detaliat și pe puncte:

  1. Utilizatorul se conectează la dex-k8s-authenticator (login.k8s.example.com)
  2. dex-k8s-authenticator redirecționează cererea către Dex (dex.k8s.example.com)
  3. Dex redirecționează la pagina de autentificare GitHub
  4. GitHub generează informațiile necesare pentru autorizare și le returnează la Dex
  5. Dex trimite informațiile obținute la dex-k8s-authenticator
  6. Utilizatorul primește token OIDC de la GitHub
  7. dex-k8s-authenticator adaugă tokenul în kubeconfig
  8. kubectl trimite tokenul către KubeAPIServer
  9. KubeAPIServer returnează accesul în kubectl bazat pe tokenul transmis
  10. Utilizatorul primește accesul de la kubectl

Acțiuni pregătitoare

Desigur, avem deja un cluster Kubernetes (k8s.example.com), precum și HELM preinstalat. De asemenea, avem o organizație pe GitHub (super-org).
Dacă nu aveți HELM, instalarea se face foarte simplu.

Mai întâi trebuie să configurăm GitHub.

Accesați pagina de setări a organizației, (https://github.com/organizations/super-org/settings/applications) și creați o aplicație nouă (Aplicație OAuth autorizată):
Autentificarea în Kubernetes cu GitHub OAuth și Dex
Crearea unei noi aplicații în GitHub

Completați câmpurile cu URL-urile necesare, de exemplu:

  • Homepage URL: https://dex.k8s.example.com
  • Authorization callback URL: https://dex.k8s.example.com/callback

Fiți atenți la linkuri, este important să nu pierdeți slash-urile.

Ca răspuns la formularul completat, GitHub va genera ID-ul Clientului și Client secret, salvați-le într-un loc sigur, ne vor fi utile (de exemplu, folosim Vault pentru a stoca secretele):

Client ID: 1ab2c3d4e5f6g7h8
Client secret: 98z76y54x32w1

Pregătiți înregistrările DNS pentru subdomenii login.k8s.example.com și dex.k8s.example.com, precum și certificatele SSL pentru ingressuri.

Vom crea certificate 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 cu numele le-clusterissuer trebuie să existe deja, altfel îl vom crea cu ajutorul 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

Configurarea KubeAPIServer

Pentru a funcționa, kubeAPIServer trebuie configurat OIDC și să actualizăm cluster-ul:

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

Folosim kops pentru desfășurarea cluster-elor, dar funcționează similar și pentru alte manageri de cluster.

Configurarea Dex și dex-k8s-authenticator

Pentru a funcționa, Dex trebuie să aibă un certificat și o cheie de pe masterul Kubernetes, să le extragem de acolo:

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

Vom clona repository-ul dex-k8s-authenticator:

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

Cu ajutorul fișierelor values putem configura variabilele pentru graficele HELM.

Vom descrie configurația pentru Dex:

cat < 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

Și pentru dex-k8s-authenticator:

cat < 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

Vom instala Dex și 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

Să verificăm funcționalitatea serviciilor (Dex ar trebui să returneze codul 400, iar dex-k8s-authenticator — codul 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

Configurație RBAC

Creăm un ClusterRole pentru grup, în cazul nostru cu accesuri read-only:

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

Vom crea configurarea pentru 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

Acum suntem pregătiți pentru testare.

Teste

Accesăm pagina de autentificare (https://login.k8s.example.com) și ne autentificăm cu contul de GitHub:

Autentificarea în Kubernetes cu GitHub OAuth și Dex
Pagina de autentificare

Autentificarea în Kubernetes cu GitHub OAuth și Dex
Pagina de autentificare redirecționată pe GitHub

Autentificarea în Kubernetes cu GitHub OAuth și Dex
 Urmăm instrucțiunile generate pentru a obține permisiunile

După copierea și lipirea de pe pagina web, putem folosi kubectl pentru a gestiona resursele clusterului nostru:

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"

Și funcționează, toți utilizatorii de GitHub din organizația noastră pot vizualiza resursele și pot accesa pod-urile, dar nu au drepturi de modificare.

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster