Avtentikacija v Kubernetes s pomočjo GitHub OAuth in Dex

Predstavljam vam priročnik za generiranje dostopov do Kubernetes klastera z uporabo Dex, dex-k8s-authenticator in GitHub.

Avtentikacija v Kubernetes s pomočjo GitHub OAuth in Dex
Lokalen meme iz rusko govorečega Kubernetes čata v Telegram

Uvod

Mi uporabljamo Kubernetes za ustvarjanje dinamičnih okolij za razvojne ekipe in QA. Tako želimo zagotoviti dostop do klasterja tako za nadzorno ploščo kot za kubectl. Za razliko od OpenShift, ima osnovni Kubernetes, brez dodatkov, nativno avtentikacijo, zato za to uporabljamo tuje rešitve.

V tej konfiguraciji uporabljamo:

  • dex-k8s-authenticator — spletna aplikacija za generiranje konfiguracije kubectl
  • Dex — ponudnik OpenID Connect
  • GitHub — preprosto zato, ker uporabljamo GitHub v naši družbi

Poskusili smo uporabiti Google OIDC, vendar nam ni uspelo nastaviti z skupinami, zato nas je integracija z GitHub v celoti zadovoljila. Brez povezovanja skupin ne moremo ustvariti RBAC politik, temelječih na skupinah.

Torej, kako deluje naš proces avtentikacije v Kubernetesu vizualno:

Avtentikacija v Kubernetes s pomočjo GitHub OAuth in Dex
Postopek avtentikacije

Malo podrobneje in po točkah:

  1. Uporabnik se prijavi v dex-k8s-authenticator (login.k8s.example.com)
  2. dex-k8s-authenticator preusmeri zahtevo v Dex (dex.k8s.example.com)
  3. Dex preusmeri na stran za prijavo v GitHub
  4. GitHub ustvari potrebno avtentikacijsko informacijo in jo vrne Dexu
  5. Dex posreduje pridobljeno informacijo nazaj v dex-k8s-authenticator
  6. Uporabnik pridobi OIDC žeton od GitHub
  7. dex-k8s-authenticator doda žeton v kubeconfig
  8. kubectl posreduje žeton v KubeAPIServer
  9. KubeAPIServer na podlagi posredovanega žetona vrne dostope v kubectl
  10. Uporabnik pridobi dostop do kubectl

Pripravljalne dejavnosti

Seveda imamo že nameščen Kubernetes klaster (k8s.example.com), prav tako pa je že nameščen HELM. Imamo tudi organizacijo v GitHub (super-org).
Če nimate HELM, ga lahko namestite zelo preprosto.

Najprej moramo nastaviti GitHub.

Pojdite na stran nastavitev organizacije, (https://github.com/organizations/super-org/settings/applications) in ustvarite novo aplikacijo (Authorized OAuth App):
Avtentikacija v Kubernetes s pomočjo GitHub OAuth in Dex
Ustvarjanje nove aplikacije v GitHub

Izpolnite polja z potrebnimi URL-ji, na primer:

  • URL domače strani: https://dex.k8s.example.com
  • URL za povrnitev avtentikacije: https://dex.k8s.example.com/callback

Bodite pozorni na povezave, pomembno je, da ne izgubite poševnic.

V odgovor na izpolnjen obrazec bo GitHub ustvaril Client ID in Client secret, shranite ju na varno mesto, koristila nam bosta (mi na primer uporabljamo Vault za shranjevanje skrivnosti):

Client ID: 1ab2c3d4e5f6g7h8
Client secret: 98z76y54x32w1

Pripravite DNS zapise za poddomene login.k8s.example.com in dex.k8s.example.com, in addition to SSL certificates for ingresses.

Let's create SSL certificates:

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 named le-clusterissuer must already exist, if not, we will create it using 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

KubeAPIServer Configuration

To operate kubeAPIServer, it is necessary to configure OIDC and update the 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

Imamo kops for deploying clusters, but this works similarly for other cluster managers.

Dex and dex-k8s-authenticator Configuration

To operate Dex, you need to have a certificate and key from the Kubernetes master, we will extract it from there:

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

We will clone the dex-k8s-authenticator repository:

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

With values files, we can flexibly configure variables for our HELM charts.

Let's describe the configuration 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

In addition 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

Let's install Dex and 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

Let's check the services' functionality (Dex should return code 400, while dex-k8s-authenticator should return code 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 configuration

We create a ClusterRole for the group, in our case with read-only accesses:

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

Ustvarimo konfiguracijo za 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

Sedaj smo pripravljeni na testiranje.

Testovi

Preklopimo na stran za prijavo (https://login.k8s.example.com) in se prijavimo z GitHub računom:

Avtentikacija v Kubernetes s pomočjo GitHub OAuth in Dex
Stran za avtorizacijo

Avtentikacija v Kubernetes s pomočjo GitHub OAuth in Dex
Stran za avtorizacijo preusmerjena na GitHub

Avtentikacija v Kubernetes s pomočjo GitHub OAuth in Dex
 Sledimo generiranim navodilom za pridobitev dostopov

Po kopiranju s spletne strani lahko uporabimo kubectl za upravljanje virov našega klastru:

kubectl get po
NAME                READY   STATUS    RESTARTS   AGE
mypod               1/1     Running   0          3d

kubectl delete po mypod
Napaka s strežnika (Prepovedano): pods "mypod" je prepovedano: uporabnik "amet@example.com" ne more brisati pods v prostoru "default"

In deluje, vsi uporabniki GitHub v naši organizaciji lahko vidijo vire in vstopajo v pode, vendar nimajo pravic za njihovo spreminjanje.

Izvor: habr.com

Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki 🔥 Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki | ProHoster