Authentifizierung in Kubernetes mit GitHub OAuth und Dex

Ich prÀsentiere Ihnen ein Tutorial zur Generierung von ZugÀngen zu einem Kubernetes-Cluster mit Dex, dex-k8s-authenticator und GitHub.

Authentifizierung in Kubernetes mit GitHub OAuth und Dex
Ein lokales Meme aus dem russischsprachigen Kubernetes-Chat in Telegram

EinfĂŒhrung

Wir nutzen Kubernetes, um dynamische Umgebungen fĂŒr unser Entwickler- und QA-Team zu schaffen. Daher möchten wir ihnen sowohl fĂŒr das Dashboard als auch fĂŒr kubectl Zugang zum Cluster gewĂ€hren. Im Gegensatz zu OpenShift verfĂŒgt Vanilla Kubernetes nicht ĂŒber eine native Authentifizierung, weshalb wir Drittanbieter-Tools einsetzen.

In dieser Konfiguration verwenden wir:

  • dex-k8s-authenticator  — eine Webanwendung zur Erstellung der kubectl-Konfiguration
  • Dex — ein OpenID Connect-Anbieter
  • GitHub — einfach, weil wir GitHub in unserem Unternehmen verwenden

Wir haben versucht, Google OIDC zu verwenden, aber leider ist es uns nicht gelungen sie mit Gruppen einzurichten, daher war die Integration mit GitHub fĂŒr uns völlig ausreichend. Ohne Gruppenzuordnungen können keine RBAC-Richtlinien basierend auf Gruppen erstellt werden.

Wie funktioniert also unser Authentifizierungsprozess in Kubernetes visuell dargestellt:

Authentifizierung in Kubernetes mit GitHub OAuth und Dex
Der Autorisierungsprozess

Ein wenig mehr Details und Punkt fĂŒr Punkt:

  1. Der Benutzer meldet sich beim dex-k8s-authenticator an (login.k8s.example.com)
  2. Der dex-k8s-authenticator leitet die Anfrage an Dex weiter (dex.k8s.example.com)
  3. Dex leitet zur Anmeldeseite in GitHub weiter
  4. GitHub generiert die erforderlichen Anmeldeinformationen und gibt sie an Dex zurĂŒck
  5. Dex ĂŒbertrĂ€gt die erhaltenen Informationen an den dex-k8s-authenticator
  6. Der Benutzer erhÀlt ein OIDC-Token von GitHub
  7. dex-k8s-authenticator fĂŒgt das Token zur kubeconfig hinzu
  8. kubectl ĂŒbertrĂ€gt das Token an den KubeAPIServer
  9. Der KubeAPIServer gibt basierend auf dem ĂŒbermittelten Token Zugriffsrechte an kubectl zurĂŒck
  10. Der Benutzer erhÀlt die Zugriffsrechte von kubectl

Vorbereitende Schritte

NatĂŒrlich haben wir bereits ein Kubernetes-Cluster eingerichtet (k8s.example.com), und auch HELM ist bereits installiert. Außerdem haben wir eine Organisation in GitHub (super-org).
Falls Sie HELM nicht haben, ist die Installation ganz einfach sehr unkompliziert.

Zuerst mĂŒssen wir GitHub konfigurieren.

Gehen Sie zur Einstellungsseite der Organisation, (https://github.com/organizations/super-org/settings/applications) und erstellen Sie eine neue Anwendung (Authorized OAuth App):
Authentifizierung in Kubernetes mit GitHub OAuth und Dex
Erstellen einer neuen Anwendung in GitHub

FĂŒllen Sie die erforderlichen Felder mit den entsprechenden URLs aus, zum Beispiel:

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

Achten Sie auf die Links, wichtig ist, dass die Slashes nicht verloren gehen.

Als Antwort auf das ausgefĂŒllte Formular generiert GitHub Client-Geheimnis und Client Secret, bewahren Sie diese an einem sicheren Ort auf, wir werden sie benötigen (wir verwenden beispielsweise Vault zum Speichern von Geheimnissen):

Client ID: 1ab2c3d4e5f6g7h8
Client secret: 98z76y54x32w1

Bereiten Sie die DNS-EintrĂ€ge fĂŒr Subdomains vor login.k8s.example.com und dex.k8s.example.com, sowie SSL-Zertifikate fĂŒr Ingresses.

Lassen Sie uns SSL-Zertifikate erstellen:

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 mit dem Namen le-clusterissuer muss bereits existieren, falls nicht, lassen Sie uns ihn mit HELM erstellen:

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

Um den kubeAPIServer zu betreiben, mĂŒssen OIDC konfiguriert und das Cluster aktualisiert werden:

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

Wir nutzen , es gibt auch ErwĂ€hnungen zum Aufbau von Service Mesh-Netzwerken ( um Cluster bereitzustellen, aber es funktioniert Ă€hnlich auch fĂŒr andere Cluster-Manager.

Konfiguration von Dex und dex-k8s-authenticator

Um Dex zu betreiben, benötigen wir ein Zertifikat und einen SchlĂŒssel vom Kubernetes-Master. Lassen Sie uns diese dort abrufen:

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

Wir klonen das Repository dex-k8s-authenticator:

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

Mit Hilfe von Values-Dateien können wir die Variablen fĂŒr unsere HELM-Charts flexibel anpassen.

Lassen Sie uns die Konfiguration fĂŒr Dex beschreiben:

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

Und fĂŒr 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

Wir installieren Dex und 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

ÜberprĂŒfen wir die FunktionalitĂ€t der Dienste (Dex sollte Code 400 zurĂŒckgeben, wĂ€hrend dex-k8s-authenticator Code 200 zurĂŒckgibt):

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

Wir erstellen eine ClusterRole fĂŒr die Gruppe, in unserem Fall mit read-only ZugĂ€ngen:

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

Erstellen wir die Konfiguration fĂŒr 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

Jetzt sind wir bereit fĂŒr den Test.

Tests

Gehen Sie zur Anmeldeseite (https://login.k8s.example.com) und melden Sie sich mit Ihrem GitHub-Konto an:

Authentifizierung in Kubernetes mit GitHub OAuth und Dex
Anmeldeseite

Authentifizierung in Kubernetes mit GitHub OAuth und Dex
Anmeldeseite umgeleitet zu GitHub

Authentifizierung in Kubernetes mit GitHub OAuth und Dex
 Befolgen Sie die generierte Anleitung, um Zugriff zu erhalten.

Nach dem Kopieren von der Webseite können wir kubectl nutzen, um die Ressourcen unseres Clusters zu verwalten:

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

kubectl delete po mypod
Fehler vom Server (Verboten): Pods "mypod" ist verboten: Benutzer "amet@example.com" kann Pods im Namespace "default" nicht löschen.

Und es funktioniert, alle GitHub-Nutzer in unserer Organisation können die Ressourcen sehen und auf die Pods zugreifen, haben jedoch keine Berechtigung, diese zu Àndern.

Quelle: habr.com

ZuverlĂ€ssiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen đŸ”„ ZuverlĂ€ssiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen | ProHoster