Authenticatie in Kubernetes met GitHub OAuth en Dex

Ik presenteer u een tutorial voor het genereren van toegang tot het Kubernetes-cluster met behulp van Dex, dex-k8s-authenticator en GitHub.

Authenticatie in Kubernetes met GitHub OAuth en Dex
Een lokale meme uit een Russischtalige Kubernetes-chat in Telegram

Inleiding

We gebruiken Kubernetes voor het creƫren van dynamische omgevingen voor het ontwikkelingsteam en QA. Op deze manier willen we hen toegang geven tot het cluster, zowel voor het dashboard als voor kubectl. In tegenstelling tot OpenShift heeft puur Kubernetes geen native authenticatie, daarom gebruiken we externe hulpmiddelen.

In deze configuratie gebruiken we:

  • dex-k8s-authenticatorā€Š — een webapplicatie voor het genereren van de kubectl-configuratie
  • Dex — een OpenID Connect-provider
  • GitHub — gewoon omdat we GitHub in ons bedrijf gebruiken

We hebben geprobeerd Google OIDC te gebruiken, maar helaas hebben we het niet voor elkaar gekregen om ze met groepen aan de praat te krijgen, dus de integratie met GitHub voldeed ons helemaal. Zonder groepsmapping kunnen we geen RBAC-beleid creƫren dat op groepen is gebaseerd.

Dus, hoe werkt ons autorisatieproces in Kubernetes visueel:

Authenticatie in Kubernetes met GitHub OAuth en Dex
Het autorisatieproces

Een beetje meer in detail en puntsgewijs:

  1. De gebruiker logt in op dex-k8s-authenticator (login.k8s.example.com)
  2. dex-k8s-authenticator leidt het verzoek door naar Dex (dex.k8s.example.com)
  3. Dex leidt door naar de inlogpagina van GitHub
  4. GitHub genereert de benodigde autorisatie-informatie en geeft deze terug aan Dex
  5. Dex geeft de verkregen informatie door aan dex-k8s-authenticator
  6. De gebruiker ontvangt een OIDC-token van GitHub
  7. dex-k8s-authenticator voegt het token toe aan kubeconfig
  8. kubectl geeft het token door aan KubeAPIServer
  9. KubeAPIServer retourneert op basis van het doorgegeven token de toegangen aan kubectl
  10. De gebruiker ontvangt toegangen van kubectl

Voorbereidende acties

Natuurlijk hebben we al een Kubernetes-cluster geĆÆnstalleerd (k8s.example.com), en ook HELM is al geĆÆnstalleerd. We hebben ook een organisatie op GitHub (super-org).
Als je geen HELM hebt, installeer je het heel eenvoudig.

Eerst moeten we GitHub configureren.

Ga naar de instellingenpagina van de organisatie, (https://github.com/organizations/super-org/settings/applications) en maak een nieuwe applicatie aan (Authorized OAuth App):
Authenticatie in Kubernetes met GitHub OAuth en Dex
Een nieuwe applicatie in GitHub aanmaken

Vul de velden in met de benodigde URL's, bijvoorbeeld:

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

Wees voorzichtig met de links, het is belangrijk om de schuine strepen niet kwijt te raken.

In antwoord op het ingevulde formulier genereert GitHub Cliƫnt ID en Client secret, bewaar deze op een veilige plaats, we hebben ze nodig (wij gebruiken bijvoorbeeld Vault voor de opslag van geheimen):

Client-ID: 1ab2c3d4e5f6g7h8
Client secret: 98z76y54x32w1

Bereid DNS-records voor de subdomeinen login.k8s.example.com en dex.k8s.example.com, evenals SSL-certificaten voor ingressen.

We zullen SSL-certificaten aanmaken:

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 met de naam le-clusterissuer moet al bestaan; als dat niet zo is, zullen we het maken met 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

Configuratie KubeAPIServer

Voor het functioneren van kubeAPIServer moet OIDC geconfigureerd worden en moet de cluster geüpdatet worden:

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

Wij gebruiken kops voor het uitrollen van clusters, maar dit werkt op dezelfde manier voor andere clusterbeheerders.

Configuratie Dex en dex-k8s-authenticator

Om Dex te gebruiken, moet je een certificaat en sleutel van de Kubernetes-master hebben, die halen we daar vandaan:

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

We klonen de repository dex-k8s-authenticator:

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

Met behulp van values-bestanden kunnen we variabelen flexibel instellen voor onze HELM-charts.

Laten we de configuratie voor Dex beschrijven:

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

En voor 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

Laten we Dex en dex-k8s-authenticator installeren:

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

Laten we de werking van de services controleren (Dex moet statuscode 400 teruggeven en dex-k8s-authenticator moet statuscode 200 teruggeven):

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

We maken een ClusterRole aan voor de groep, in ons geval met read-only toegang:

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

Laten we de configuratie voor ClusterRoleBinding aanmaken:

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

Nu zijn we klaar om te testen.

Tests

Laten we naar de inlogpagina gaan (https://login.k8s.example.com) en ons aanmelden met een GitHub-account:

Authenticatie in Kubernetes met GitHub OAuth en Dex
Inlogpagina

Authenticatie in Kubernetes met GitHub OAuth en Dex
Inlogpagina omgeleid naar GitHub

Authenticatie in Kubernetes met GitHub OAuth en Dex
Ā Volg de gegenereerde instructies om toegang te krijgen

Na het kopiƫren en plakken vanaf de webpagina kunnen we kubectl gebruiken om de resources van onze cluster te beheren:

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"

En het werkt, alle GitHub-gebruikers in onze organisatie kunnen resources zien en in pods inloggen, maar ze hebben geen rechten om deze te wijzigen.

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers šŸ”„ Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster