Autentificering i Kubernetes med GitHub OAuth og Dex

Jeg præsenterer en tutorial til generering af adgang til Kubernetes-klyngen med Dex, dex-k8s-authenticator og GitHub.

Autentificering i Kubernetes med GitHub OAuth og Dex
Et lokalt meme fra den russisk talende Kubernetes chat i Telegram

Introduktion

Vi bruger Kubernetes til at oprette dynamiske miljøer for udviklingsteamet og QA. På den måde ønsker vi at give dem adgang til klyngen både til dashboardet og til kubectl. I modsætning til OpenShift har vanilje Kubernetes ikke indbygget autentificering, så vi anvender tredjeparts værktøjer til dette.

I denne konfiguration bruger vi:

  • dex-k8s-authenticator  — en webapplikation til generering af kubectl konfiguration
  • Dex — OpenID Connect udbyder
  • GitHub — bare fordi vi bruger GitHub i vores virksomhed

Vi forsøgte at bruge Google OIDC, men desværre kunne vi ikke få det til at fungere med grupper, så integrationen med GitHub er helt acceptabel for os. Uden gruppemapping er det ikke muligt at oprette RBAC-politikker baseret på grupper.

Så hvordan fungerer vores godkendelsesproces i Kubernetes visuelt:

Autentificering i Kubernetes med GitHub OAuth og Dex
Godkendelsesprocessen

Lidt nærmere og punkt for punkt:

  1. Brugeren logger ind på dex-k8s-authenticator (login.k8s.example.com)
  2. dex-k8s-authenticator omdirigerer anmodningen til Dex (dex.k8s.example.com)
  3. Dex omdirigerer til GitHub login-siden
  4. GitHub genererer den nødvendige autoriseringsinformation og returnerer den til Dex
  5. Dex sender den modtagne information til dex-k8s-authenticator
  6. Brugeren får et OIDC-token fra GitHub
  7. dex-k8s-authenticator tilføjer token til kubeconfig
  8. kubectl sender token til KubeAPIServer
  9. KubeAPIServer returnerer adgang til kubectl baseret på det sendte token
  10. Brugeren får adgang fra kubectl

Forberedende handlinger

Selvfølgelig har vi allerede en Kubernetes-klynge (k8s.example.com), samt forhåndsinstalleret HELM. Vi har også en organisation på GitHub (super-org).
Hvis du ikke har HELM, kan det installeres meget nemt.

Først skal vi konfigurere GitHub.

Gå til organisationsindstillingerne, (https://github.com/organizations/super-org/settings/applications) og opret en ny applikation (Autoriseret OAuth App):
Autentificering i Kubernetes med GitHub OAuth og Dex
Oprettelse af ny applikation på GitHub

Udfyld felterne med de nødvendige URL'er, for eksempel:

  • Hjemmeside URL: https://dex.k8s.example.com
  • Autoriserings callback URL: https://dex.k8s.example.com/callback

Vær opmærksom på links, det er vigtigt ikke at miste skråstregene.

Som svar på den udfyldte formular vil GitHub generere Denne ID bruges til at identificere og Client secret, gem dem på et sikkert sted, da vi får brug for dem (vi bruger f.eks. Vault til opbevaring af hemmeligheder):

Client ID: 1ab2c3d4e5f6g7h8
Client secret: 98z76y54x32w1

Forbered DNS-poster for underdomæner login.k8s.example.com og dex.k8s.example.com, samt SSL-certifikater til indgange.

Lad os oprette SSL-certifikater:

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 med navnet le-clusterissuer bør allerede eksistere, hvis ikke — lad os oprette det med 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

Konfiguration af KubeAPIServer

For at få kubeAPIServer til at fungere skal OIDC konfigureres og klyngen opdateres:

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

Vi bruger kops til udrulning af klynger, men dette fungerer også tilsvarende for andre klyngeadministratorer.

Konfiguration af Dex og dex-k8s-authenticator

For at Dex kan fungere, skal vi have et certifikat og en nøgle fra Kubernetes-masteren, lad os hente det derfra:

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

Lad os klone repoet dex-k8s-authenticator:

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

Med værdifilerne kan vi fleksibelt konfigurere variabler til vores HELM-diagrammer.

Lad os beskrive konfigurationen for 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

Og for 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

Lad os installere Dex og 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

Lad os kontrollere tjenesterne (Dex skal returnere statuskode 400, mens dex-k8s-authenticator skal returnere statuskode 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-konfiguration

Vi opretter en ClusterRole for gruppen, i dette tilfælde med read-only adgang:

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

Lad os oprette en konfiguration til 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

Vi er nu klar til at teste.

Tests

Gå til login-siden (https://login.k8s.example.com) og log ind med en GitHub-konto:

Autentificering i Kubernetes med GitHub OAuth og Dex
Login-side

Autentificering i Kubernetes med GitHub OAuth og Dex
Login-side omdirigeret til GitHub

Autentificering i Kubernetes med GitHub OAuth og Dex
 Følg den genererede instruktion for at få adgang

Efter at have kopieret og indsat fra web-siden kan vi bruge kubectl til at administrere ressourcerne i vores klynge:

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"

Og det virker, alle GitHub-brugere i vores organisation kan se ressourcerne og logge ind i pods, men de har ikke rettigheder til at ændre dem.

Kilde: habr.com

Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere 🔥 Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster