Autentifikācija Kubernetes ar GitHub OAuth un Dex

I am pleased to present a tutorial for generating access to the Kubernetes cluster using Dex, dex-k8s-authenticator, and GitHub.

Autentifikācija Kubernetes ar GitHub OAuth un Dex
Local meme from the Russian-speaking Kubernetes chat in Telegram

Ievads

We use Kubernetes to create dynamic environments for the development and QA teams. Thus, we want to provide them access to the cluster for both the dashboard and kubectl. Unlike OpenShift, vanilla Kubernetes does not have native authentication, so we use third-party tools for this.

In this configuration, we use:

  • dex-k8s-authenticator  — a web application for generating the kubectl config
  • Dex — an OpenID Connect provider
  • GitHub — simply because we use GitHub in our company

We tried to use Google OIDC, but unfortunately we could not set them up with groups, so the integration with GitHub suited us just fine. Without group mapping, it won't be possible to create RBAC policies based on groups.

So, how does our authorization process in Kubernetes work in a visual representation:

Autentifikācija Kubernetes ar GitHub OAuth un Dex
Authorization Process

A bit more detail and by points:

  1. The user logs into dex-k8s-authenticator (login.k8s.example.com)
  2. dex-k8s-authenticator redirects the request to Dex (dex.k8s.example.com)
  3. Dex redirects to the authorization page on GitHub
  4. GitHub generates the required authorization information and returns it to Dex
  5. Dex passes the received information to dex-k8s-authenticator
  6. The user receives an OIDC token from GitHub
  7. dex-k8s-authenticator adds the token to kubeconfig
  8. kubectl sends the token to KubeAPIServer
  9. KubeAPIServer returns access to kubectl based on the provided token
  10. The user receives access from kubectl

Preparatory Actions

Of course, we already have a Kubernetes cluster set up (k8s.example.com), as well as pre-installed HELM. We also have an organization on GitHub (super-org).
If you do not have HELM, it installs very simply.

First, we need to configure GitHub.

Go to the organization settings page, (https://github.com/organizations/super-org/settings/applications) and create a new application (Authorized OAuth App):
Autentifikācija Kubernetes ar GitHub OAuth un Dex
Creating a new application on GitHub

Fill in the fields with the necessary URLs, for example:

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

Be careful with the links, it is important not to lose the slashes.

In response to the completed form, GitHub will generate Klienta ID un Client secret, save it in a secure place, as we will need it (for example, we use Vault to store secrets):

Client ID: 1ab2c3d4e5f6g7h8
Client secret: 98z76y54x32w1

Prepare DNS records for subdomains login.k8s.example.com un dex.k8s.example.com, kā arī SSL sertifikātiem iebraukšanai.

Izveidosim SSL sertifikātus:

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 ar nosaukumu le-clusterissuer jau ir jābūt eksistējošam, ja tāda nav — izveidosim to ar 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 konfigurācija

Lai strādātu kubeAPIServer, ir nepieciešams konfigurēt OIDC un atjaunot klasteri:

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

Mēs izmantojam kops klasteru izvēršanai, taču tas strādā līdzīgi arī citos klasteru pārvaldniekos citiem klasteru pārvaldniekiem.

Dex un dex-k8s-authenticator konfigurācija

Lai Dex darbotos, ir nepieciešams sertifikāts un atslēga no Kubernetes meistara, izņemsim to no turienes:

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

Noslēgsim dex-k8s-authenticator repozitoriju:

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

Izmantojot values failus, mēs varam elastīgi konfigurēt mainīgus mūsu HELM diagrammām.

Aprakstīsim Dex konfigurāciju:

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

Un arī dex-k8s-authenticator:

cat < values-auth.yml
global:
  deployEnv: prod
dexK8sAuthenticator:
  clusters:
  - name: k8s.example.com
    short_description: "k8s klasteris"
    description: "Kubernetes klasteris"
    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

Uzstādīsim Dex un 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

Pārbaudīsim pakalpojumu darba spēju (Dex jāatgriež kods 400, bet dex-k8s-authenticator — kods 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 konfigurācija

Izveidojam ClusterRole grupai, mūsu gadījumā ar read-only piekļuves tiesībām:

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

Izveidosim konfigurāciju 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

Tagad mēs esam gatavi testēšanai.

Testi

Pārejiet uz pieteikšanās lapu (https://login.k8s.example.com) un autorizējieties, izmantojot GitHub kontu:

Autentifikācija Kubernetes ar GitHub OAuth un Dex
Autorizācijas lapa

Autentifikācija Kubernetes ar GitHub OAuth un Dex
Autorizācijas lapa, kas novirzīta uz GitHub

Autentifikācija Kubernetes ar GitHub OAuth un Dex
 Sekojiet ģenerētajām instrukcijām, lai iegūtu piekļuves tiesības

Pēc kopēšanas no tīmekļa lapas mēs varam izmantot kubectl, lai pārvaldītu mūsu klastera resursus:

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"

Un tas darbojas, visi GitHub lietotāji mūsu organizācijā var apskatīt resursus un piekļūt podiem, taču viņiem nav tiesību tos mainīt.

Avots: habr.com

Iegādājieties uzticamu tīmekļa hostingu ar DDoS aizsardzību, VPS VDS serveriem 🔥 Iegādājieties uzticamu tīmekļa hostingu ar DDoS aizsardzību, VPS VDS serveriem | ProHoster