Autentizace v Kubernetes pomocí GitHub OAuth a Dex

Představuji vám návod na generování přístupů k Kubernetes clusteru pomocí Dex, dex-k8s-authenticator a GitHubu.

Autentizace v Kubernetes pomocí GitHub OAuth a Dex
Lokální mem z rusky mluvícího chatu Kubernetes v Telegram

Úvod

Používáme Kubernetes pro vytváření dynamických prostředí pro vývojový a QA tým. Tímto způsobem chceme poskytnout přístup k clusteru jak pro dashboard, tak pro kubectl. Na rozdíl od OpenShift, čistý Kubernetes nemá nativní autentizaci, proto používáme pro tuto funkcionalitu třetí strany.

V této konfiguraci používáme:

  • dex-k8s-authenticator  — webová aplikace pro generování konfiguračního souboru kubectl
  • Dex — poskytovatel OpenID Connect
  • GitHub — prostě proto, že v naší společnosti používáme GitHub

Pokoušeli jsme se použít Google OIDC, ale bohužel se nám to nepodařilo zprovoznit s skupinami, takže integrace s GitHubem nás docela uspokojila. Bez mapování skupin nelze vytvořit RBAC politiky založené na skupinách.

Tak jak vlastně funguje náš proces autorizace v Kubernetes v vizuálním zobrazení:

Autentizace v Kubernetes pomocí GitHub OAuth a Dex
Proces autorizace

Trochu podrobněji, krok za krokem:

  1. Uživatel se přihlašuje do dex-k8s-authenticator (login.k8s.example.com)
  2. dex-k8s-authenticator přesměrovává požadavek na Dex (dex.k8s.example.com)
  3. Dex přesměrovává na autorizační stránku GitHubu
  4. GitHub generuje potřebné autorizační informace a vrací je zpět do Dexu
  5. Dex předává získané informace do dex-k8s-authenticator
  6. Uživatel získává OIDC token od GitHubu
  7. dex-k8s-authenticator přidává token do kubeconfig
  8. kubectl předává token do KubeAPIServeru
  9. KubeAPIServer na základě předaného tokenu vrací přístupy do kubectl
  10. Uživatel získává přístupy od kubectl

Přípravné kroky

Samozřejmě máme již nainstalovaný Kubernetes cluster (k8s.example.com), a také je předinstalovaný HELM. Máme také organizaci na GitHubu (super-org).
Pokud nemáte HELM, jeho instalace je velmi jednoduchá.

Nejprve musíme nastavit GitHub.

Přejděte na stránku nastavení organizace, (https://github.com/organizations/super-org/settings/applications) a vytvořte novou aplikaci (Authorized OAuth App):
Autentizace v Kubernetes pomocí GitHub OAuth a Dex
Vytvoření nové aplikace na GitHubu

Vyplňte pole potřebnými URL, například:

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

Buďte opatrní s odkazy, je důležité neztratit lomítka.

V reakci na vyplněný formulář GitHub vygeneruje Client ID a Client secret, uložte si je na bezpečné místo, budou se nám hodit (například používáme Vault pro uchovávání tajemství):

Client ID: 1ab2c3d4e5f6g7h8
Client secret: 98z76y54x32w1

Připravte DNS záznamy pro subdomény login.k8s.example.com a dex.k8s.example.com, a také SSL certifikáty pro ingresses.

Vytvoříme SSL certifikáty:

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 s názvem le-clusterissuer už musí existovat, pokud ne — vytvoříme ho pomocí 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

Konfigurace KubeAPIServeru

Pro fungování kubeAPIServeru je třeba nakonfigurovat OIDC a aktualizovat cluster:

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

Používáme kops pro nasazení clusterů, ale funguje to podobně i pro jiné správce clusterů.

Konfigurace Dex a dex-k8s-authenticator

Pro fungování Dex je nutné mít certifikát a klíč z Kubernetes masteru, vezmeme ho odtamtud:

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

Klonujeme repozitář dex-k8s-authenticator:

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

Pomocí souborů values můžeme flexibilně konfigurovat proměnné pro naše HELM grafy.

Popíšeme konfiguraci pro 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

A pro 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

Nainstalujeme Dex a 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

Otestujeme funkčnost služeb (Dex by měl vrátit kód 400, a dex-k8s-authenticator — kód 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 konfigurace

Vytváříme ClusterRole pro skupinu, v našem případě se čtenářskými právy:

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

Vytvoříme konfiguraci pro 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

Teď jsme připraveni na testování.

Testy

Přejděte na přihlašovací stránku (https://login.k8s.example.com) a přihlaste se pomocí GitHub účtu:

Autentizace v Kubernetes pomocí GitHub OAuth a Dex
Přihlašovací stránka

Autentizace v Kubernetes pomocí GitHub OAuth a Dex
Přihlašovací stránka přesměrovaná na GitHub

Autentizace v Kubernetes pomocí GitHub OAuth a Dex
 Postupujte podle vygenerovaných pokynů pro získání oprávnění

Po zkopírování z webové stránky můžeme použít kubectl k řízení zdrojů našeho clusteru:

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"

A funguje to, všichni uživatelé GitHubu v naší organizaci mohou vidět zdroje a vstoupit do podů, ale nemají oprávnění je měnit.

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster