Autentisera i Kubernetes med GitHub OAuth och Dex

Jag presenterar för din uppmärksamhet en handledning för att generera åtkomst till ett Kubernetes-kluster med hjälp av Dex, dex-k8s-autenticator och GitHub.

Autentisera i Kubernetes med GitHub OAuth och Dex
Lokal meme från den ryskspråkiga Kubernetes chattar in Telegram

Inledning

Vi använder Kubernetes för att skapa dynamiska miljöer för utvecklings- och kvalitetssäkringsteamet. Så vi vill ge dem tillgång till klustret för både instrumentpanelen och kubectl. Till skillnad från OpenShift har vanilla Kubernetes inte inbyggd autentisering, så vi använder tredjepartsverktyg för detta.

I denna konfiguration använder vi:

  • dex-k8s-autenticator  — webbapplikation för att generera kubectl config
  • Dex — OpenID Connect-leverantör
  • GitHub – helt enkelt för att vi använder GitHub i vårt företag

Vi försökte använda Google OIDC, men tyvärr misslyckades att starta dem med grupper, så integrationen med GitHub passade oss ganska bra. Utan gruppmappning kommer det inte att vara möjligt att skapa RBAC-policyer baserade på grupper.

Så, hur fungerar vår Kubernetes-auktoriseringsprocess i en visuell representation:

Autentisera i Kubernetes med GitHub OAuth och Dex
Auktoriseringsprocess

Lite mer detalj och punkt för punkt:

  1. Användaren loggar in på dex-k8s-authenticator (login.k8s.example.com)
  2. dex-k8s-authenticator vidarebefordrar begäran till Dex (dex.k8s.example.com)
  3. Dex omdirigerar till GitHubs inloggningssida
  4. GitHub genererar nödvändig behörighetsinformation och returnerar den till Dex
  5. Dex skickar den mottagna informationen till dex-k8s-autenticator
  6. Användaren får en OIDC-token från GitHub
  7. dex-k8s-authenticator lägger till token till kubeconfig
  8. kubectl skickar token till KubeAPIServer
  9. KubeAPIServer returnerar åtkomst till kubectl baserat på den passerade token
  10. Användaren får åtkomst från kubectl

Förberedande åtgärder

Naturligtvis har vi redan ett Kubernetes-kluster installerat (k8s.example.com), och kommer även med HELM förinstallerat. Vi har även en organisation på GitHub (super-org).
Om du inte har HELM, installera det mycket enkel.

Först måste vi konfigurera GitHub.

Gå till sidan för organisationsinställningar, (https://github.com/organizations/super-org/settings/applications) och skapa en ny applikation (Authorized OAuth App):
Autentisera i Kubernetes med GitHub OAuth och Dex
Skapa en ny applikation på GitHub

Fyll i fälten med nödvändiga webbadresser, till exempel:

  • Hemsida URL: https://dex.k8s.example.com
  • Återuppringningsadress för auktorisering: https://dex.k8s.example.com/callback

Var försiktig med länkar, det är viktigt att inte tappa snedstreck.

Som svar på ett ifyllt formulär kommer GitHub att generera Client ID и Client secret, förvara dem på ett säkert ställe, de kommer att vara användbara för oss (till exempel använder vi Valv för att lagra hemligheter):

Client ID: 1ab2c3d4e5f6g7h8
Client secret: 98z76y54x32w1

Förbered DNS-poster för underdomäner login.k8s.example.com и dex.k8s.example.com, samt SSL-certifikat för inträde.

Låt oss skapa SSL-certifikat:

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 titel le-clusterissuer borde redan finnas, men om inte, skapa det med hjälp av 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

För att kubeAPIServer ska fungera måste du konfigurera OIDC och uppdatera klustret:

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 använder sparka för att distribuera kluster, men detta fungerar på liknande sätt för andra klusterchefer.

Dex-konfiguration och dex-k8s-autenticator

För att Dex ska fungera måste du ha ett certifikat och en nyckel från Kubernetes master, låt oss hämta det därifrån:

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

Låt oss klona dex-k8s-autenticator-förrådet:

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

Genom att använda värdefiler kan vi flexibelt konfigurera variabler för våra HELM diagram.

Låt oss beskriva konfigurationen 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

Och för dex-k8s-autenticator:

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

Installera Dex och dex-k8s-autenticator:

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

Låt oss kontrollera funktionerna hos tjänsterna (Dex ska returnera kod 400 och dex-k8s-authenticator ska returnera kod 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 skapar en ClusterRole för gruppen, i vårt fall med skrivskyddad åtkomst:

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

Låt oss skapa en 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

Nu är vi redo för test.

Tester

Gå till inloggningssidan (https://login.k8s.example.com) och logga in med ditt GitHub-konto:

Autentisera i Kubernetes med GitHub OAuth och Dex
Login sida

Autentisera i Kubernetes med GitHub OAuth och Dex
Inloggningssidan omdirigeras till GitHub

Autentisera i Kubernetes med GitHub OAuth och Dex
 Följ de genererade instruktionerna för att få åtkomst

Efter att ha kopierat in från webbsidan kan vi använda kubectl för att hantera våra klusterresurser:

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"

Och det fungerar, alla GitHub-användare i vår organisation kan se resurser och logga in på poddar, men de har inte rättigheter att ändra dem.

Källa: will.com

Lägg en kommentar