Vi presento un tutorial per generare accessi a un cluster Kubernetes utilizzando Dex, dex-k8s-authenticator e GitHub.

Un meme locale dal chat russo di Kubernetes in
Introduzione
Utilizziamo Kubernetes per creare ambienti dinamici per il nostro team di sviluppo e QA. Vogliamo quindi fornire loro accesso al cluster sia per la dashboard che per kubectl. A differenza di OpenShift, Kubernetes vanilla non ha un'autenticazione nativa, quindi utilizziamo strumenti di terze parti per questo.
In questa configurazione utilizziamo:
- — un'app web per generare la configurazione di kubectl
- — un provider OpenID Connect
- GitHub — semplicemente perché utilizziamo GitHub nella nostra azienda
Abbiamo provato a usare Google OIDC, ma purtroppo non a impostare gruppi, quindi l'integrazione con GitHub ci ha soddisfatti. Senza il mapping dei gruppi non si possono creare politiche RBAC basate sui gruppi.
Quindi, come funziona il nostro processo di autorizzazione in Kubernetes in un formato visivo:

Il processo di autenticazione
Un po' più nel dettaglio e per punti:
- L'utente accede a dex-k8s-authenticator (
login.k8s.example.com) - ) dex-k8s-authenticator reindirizza la richiesta a Dex (
dex.k8s.example.com) - ) Dex reindirizza alla pagina di autorizzazione di GitHub
- GitHub genera le informazioni necessarie per l'autorizzazione e le restituisce a Dex
- Dex passa le informazioni ricevute a dex-k8s-authenticator
- L'utente riceve un token OIDC da GitHub
- dex-k8s-authenticator aggiunge il token a kubeconfig
- kubectl passa il token a KubeAPIServer
- KubeAPIServer, basandosi sul token fornito, restituisce i permessi a kubectl
- L'utente riceve i permessi da kubectl
Preparazioni
Naturalmente abbiamo già un cluster Kubernetes (k8s.example.com) e HELM preinstallato. Abbiamo anche un'organizzazione su GitHub (super-org).
Se non hai HELM, l'installazione è .
Prima di tutto dobbiamo configurare GitHub.
Andiamo alla pagina delle impostazioni dell'organizzazione, (https://github.com/organizations/super-org/settings/applications) e creiamo una nuova applicazione (App OAuth autorizzata):

Creazione di una nuova applicazione su GitHub
Compiliamo i campi con gli URL necessari, ad esempio:
- Homepage URL:
https://dex.k8s.example.com - Authorization callback URL:
https://dex.k8s.example.com/callback
Fai attenzione ai link, è importante non perdere gli slash.
In risposta al modulo compilato, GitHub genererà ID del Client e Client secret, conservali in un luogo sicuro, ci serviranno (noi ad esempio utilizziamo per conservare i segreti):
Client ID: 1ab2c3d4e5f6g7h8
Client secret: 98z76y54x32w1 Prepara i record DNS per i sottodomini login.k8s.example.com e dex.k8s.example.com, così come i certificati SSL per gli ingressi.
Creiamo i certificati SSL:
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 Il ClusterIssuer con il nome le-clusterissuer dovrebbe già esistere, se non c'è — creiamolo usando 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: {}
EOFConfigurazione KubeAPIServer
Per far funzionare kubeAPIServer è necessario configurare OIDC e aggiornare il 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 --yesUtilizziamo per il deployment dei cluster, ma questo funziona analogamente anche per .
Configurazione di Dex e dex-k8s-authenticator
Per far funzionare Dex è necessario avere un certificato e una chiave dal master di Kubernetes, li estrarremo da lì:
sudo cat /srv/kubernetes/ca.{crt,key}
-----BEGIN CERTIFICATE-----
AAAAAAAAAAABBBBBBBBBBCCCCCC
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
DDDDDDDDDDDEEEEEEEEEEFFFFFF
-----END RSA PRIVATE KEY-----Cloniamo il repository dex-k8s-authenticator:
git clone git@github.com:mintel/dex-k8s-authenticator.git
cd dex-k8s-authenticator/Utilizzando i file values possiamo configurare in modo flessibile le variabili per i nostri .
Descriviamo la configurazione per 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
E per 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
EOFInstalldiamo Dex e 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-authenticatorControlliamo il funzionamento dei servizi (Dex dovrebbe restituire codice 400, mentre dex-k8s-authenticator dovrebbe restituire codice 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 200Configurazione RBAC
Creiamo un ClusterRole per il gruppo, nel nostro caso con accessi in sola lettura:
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"]
EOFCreiamo la configurazione per 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"
EOFOra siamo pronti per il test.
Test
Andiamo alla pagina di login (https://login.k8s.example.com) e autorizziamoci utilizzando il nostro account GitHub:

Pagina di autorizzazione

Pagina di autorizzazione reindirizzata a GitHub

Seguiamo le istruzioni generate per ottenere i permessi
Dopo aver copiato e incollato dal sito web, possiamo utilizzare kubectl per gestire le risorse del nostro cluster:
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" E funziona, tutti gli utenti GitHub nella nostra organizzazione possono vedere le risorse e accedere ai pod, ma non hanno diritti per modificarle.
Fonte: habr.com
