Authenticeer in Kubernetes met GitHub OAuth en Dex

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

Authenticeer in Kubernetes met GitHub OAuth en Dex
Lokale meme van de Russischtalige Kubernetes-chat Telegram

Introductie

We gebruiken Kubernetes om dynamische omgevingen te creëren voor het ontwikkelings- en QA-team. We willen ze dus toegang geven tot het cluster voor zowel het dashboard als kubectl. In tegenstelling tot OpenShift beschikt vanilla Kubernetes niet over native authenticatie, daarom gebruiken we hiervoor tools van derden.

In deze configuratie gebruiken we:

  • dex-k8s-authenticator  — webapplicatie voor het genereren van kubectl-config
  • Dex — OpenID Connect-provider
  • GitHub - simpelweg omdat we GitHub in ons bedrijf gebruiken

We hebben geprobeerd Google OIDC te gebruiken, maar helaas mislukt om ze met groepen te starten, dus de integratie met GitHub beviel ons prima. Zonder groepstoewijzing is het niet mogelijk om RBAC-beleid te maken op basis van groepen.

Hoe werkt ons Kubernetes-autorisatieproces in een visuele weergave:

Authenticeer in Kubernetes met GitHub OAuth en Dex
Autorisatieproces

Iets gedetailleerder en punt voor punt:

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

Voorbereidende acties

Natuurlijk hebben we al een Kubernetes-cluster geïnstalleerd (k8s.example.com), en wordt ook geleverd met HELM vooraf geïnstalleerd. We hebben ook een organisatie op GitHub (super-org).
Als u geen HELM heeft, installeer deze dan eenvoudige.

Eerst moeten we GitHub instellen.

Ga naar de pagina met organisatie-instellingen (https://github.com/organizations/super-org/settings/applications) en maak een nieuwe applicatie (Authorized OAuth App):
Authenticeer in Kubernetes met GitHub OAuth en Dex
Een nieuwe applicatie maken op GitHub

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

  • Startpagina URL: https://dex.k8s.example.com
  • Autorisatie callback-URL: https://dex.k8s.example.com/callback

Wees voorzichtig met links, het is belangrijk dat er geen schuine strepen verloren gaan.

Als reactie op een ingevuld formulier genereert GitHub Client ID и Client secret, bewaar ze op een veilige plaats, ze zullen ons van pas komen (wij gebruiken bijvoorbeeld Gewelf voor het opslaan van geheimen):

Client ID: 1ab2c3d4e5f6g7h8
Client secret: 98z76y54x32w1

DNS-records voorbereiden voor subdomeinen login.k8s.example.com и dex.k8s.example.com, evenals SSL-certificaten voor inkomend verkeer.

Laten we SSL-certificaten maken:

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 titel le-clusterissuer zou al moeten bestaan, maar als dat niet het geval is, maak het dan aan 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: [email protected]
    privateKeySecretRef:
      name: le-clusterissuer
    http01: {}
EOF

KubeAPIServer-configuratie

Om kubeAPIServer te laten werken, moet u OIDC configureren en het cluster bijwerken:

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

We gebruiken trap voor het implementeren van clusters, maar dit werkt op dezelfde manier voor andere clustermanagers.

Dex-configuratie en dex-k8s-authenticator

Om Dex te laten werken, heb je een certificaat en een sleutel van de Kubernetes-master nodig, laten we het vanaf daar doen:

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

Laten we de dex-k8s-authenticator-repository klonen:

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

Met behulp van waardenbestanden kunnen we flexibel variabelen configureren voor onze HELM-grafieken.

Laten we de configuratie voor Dex beschrijven:

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

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

Installeer Dex en 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

Laten we de functionaliteit van de services controleren (Dex zou code 400 moeten retourneren, en dex-k8s-authenticator zou code 200 moeten retourneren):

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 voor de groep, in ons geval met alleen-lezen 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 een configuratie maken voor 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

Nu zijn we klaar om te testen.

Testen

Ga naar de inlogpagina (https://login.k8s.example.com) en log in met uw GitHub-account:

Authenticeer in Kubernetes met GitHub OAuth en Dex
Login pagina

Authenticeer in Kubernetes met GitHub OAuth en Dex
Inlogpagina doorgestuurd naar GitHub

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

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

Bron: www.habr.com

Voeg een reactie