Kubernetes-Authentifizierung mit GitHub OAuth und Dex

Ich präsentiere Ihnen ein Tutorial zum Generieren des Zugriffs auf einen Kubernetes-Cluster mithilfe von Dex, dex-k8s-authenticator und GitHub.

Kubernetes-Authentifizierung mit GitHub OAuth und Dex
Lokales Meme aus dem russischsprachigen Kubernetes-Chat Telegram

Einführung

Wir verwenden Kubernetes, um dynamische Umgebungen für das Entwicklungsteam und die Qualitätssicherung zu erstellen. Deshalb möchten wir ihnen Zugriff auf den Cluster sowohl für das Dashboard als auch für kubectl gewähren. Im Gegensatz zum gleichen OpenShift verfügt Vanilla Kubernetes nicht über eine native Authentifizierung, daher verwenden wir hierfür Tools von Drittanbietern.

In dieser Konfiguration verwenden wir:

  • dex-k8s-authenticator  - Webanwendung zum Generieren der kubectl-Konfiguration
  • Dex - OpenID Connect-Anbieter
  • GitHub – einfach weil wir GitHub in unserem Unternehmen nutzen

Wir haben versucht, Google OIDC zu verwenden, aber leider haben wir gescheitert um sie mit Gruppen zu starten, daher hat uns die Integration mit GitHub sehr gut gefallen. Ohne Gruppenzuordnung ist es nicht möglich, gruppenbasierte RBAC-Richtlinien zu erstellen.

Wie funktioniert also unser Kubernetes-Autorisierungsprozess in einer visuellen Darstellung:

Kubernetes-Authentifizierung mit GitHub OAuth und Dex
Autorisierungsprozess

Etwas detaillierter und Punkt für Punkt:

  1. Benutzer meldet sich bei dex-k8s-authenticator an (login.k8s.example.com)
  2. dex-k8s-authenticator leitet die Anfrage an Dex weiter (dex.k8s.example.com)
  3. Dex leitet zur GitHub-Anmeldeseite weiter
  4. GitHub generiert die erforderlichen Autorisierungsinformationen und gibt sie an Dex zurück
  5. Dex übergibt die empfangenen Informationen an dex-k8s-authenticator
  6. Der Benutzer erhält ein OIDC-Token von GitHub
  7. dex-k8s-authenticator fügt kubeconfig ein Token hinzu
  8. kubectl übergibt das Token an KubeAPIServer
  9. KubeAPIServer gibt basierend auf dem übergebenen Token Zugriff auf kubectl zurück
  10. Benutzerzugriffe über kubectl

Vorbereitende Maßnahmen

Natürlich haben wir bereits einen Kubernetes-Cluster installiert (k8s.example.com), sowie HELM vorinstalliert. Wir haben auch eine Organisation auf GitHub (super-org).
Wenn Sie HELM nicht haben, installieren Sie es sehr einfach.

Zuerst müssen wir GitHub einrichten.

Gehen Sie zur Seite mit den Organisationseinstellungen (https://github.com/organizations/super-org/settings/applications) und erstellen Sie eine neue Anwendung (Autorisierte OAuth-App):
Kubernetes-Authentifizierung mit GitHub OAuth und Dex
Erstellen Sie eine neue App auf GitHub

Füllen Sie die Felder mit den erforderlichen URLs aus, zum Beispiel:

  • Homepage-URL: https://dex.k8s.example.com
  • Autorisierungs-Rückruf-URL: https://dex.k8s.example.com/callback

Seien Sie vorsichtig mit Links, es ist wichtig, dass Schrägstriche nicht verloren gehen.

Als Antwort auf das ausgefüllte Formular generiert GitHub Client ID и Client secret, bewahren Sie sie an einem sicheren Ort auf, sie werden uns nützlich sein (z. B. verwenden wir Gewölbe zum Bewahren von Geheimnissen):

Client ID: 1ab2c3d4e5f6g7h8
Client secret: 98z76y54x32w1

Bereiten Sie DNS-Einträge für Subdomains vor login.k8s.example.com и dex.k8s.example.comsowie SSL-Zertifikate für eingehende Daten.

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 Titel le-clusterissuer sollte bereits vorhanden sein, falls nicht, erstellen Sie es mit 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: [email protected]
    privateKeySecretRef:
      name: le-clusterissuer
    http01: {}
EOF

KubeAPIServer-Konfiguration

Damit kubeAPIServer funktioniert, müssen Sie OIDC konfigurieren und den Cluster aktualisieren:

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 gebrauchen Kops um Cluster zu erweitern, aber es funktioniert genauso andere Clustermanager.

Dex-Konfiguration und dex-k8s-authenticator

Damit Dex funktioniert, benötigen Sie ein Zertifikat und einen Schlüssel vom Kubernetes-Master. Wir werden ihn von dort abrufen:

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

Klonen Sie das dex-k8s-authenticator-Repository:

git clone [email protected]:mintel/dex-k8s-authenticator.git
cd dex-k8s-authenticator/

Mit Hilfe von Wertedateien können wir flexibel Variablen für unsere einrichten HELM-Charts.

Beschreiben wir die Konfiguration für 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

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

Installieren Sie 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 Funktionsfähigkeit der Dienste (Dex sollte den Code 400 zurückgeben und dex-k8s-authenticator sollte den Code 200 zurückgeben):

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

Erstellen Sie eine ClusterRole für die Gruppe, in unserem Fall mit schreibgeschütztem Zugriff:

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 eine 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 zum Testen.

Tests

Gehen Sie zur Anmeldeseitehttps://login.k8s.example.com) und melden Sie sich mit einem GitHub-Konto an:

Kubernetes-Authentifizierung mit GitHub OAuth und Dex
Autorisierungsseite

Kubernetes-Authentifizierung mit GitHub OAuth und Dex
Autorisierungsseite auf GitHub umgeleitet

Kubernetes-Authentifizierung mit GitHub OAuth und Dex
 Befolgen Sie die generierten Anweisungen, um Zugriff zu erhalten

Nach dem Kopieren und Einfügen von der Webseite können wir kubectl verwenden, um unsere Clusterressourcen zu verwalten:

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 "[email protected]" cannot delete pods in the namespace "default"

Und es funktioniert: Alle GitHub-Benutzer in unserer Organisation können Ressourcen sehen und sich bei Pods anmelden, haben aber keine Berechtigung, diese zu ändern.

Source: habr.com

Kommentar hinzufügen