Autenticação no Kubernetes com GitHub OAuth e Dex

Apresento a você o tutorial para gerar acesso ao cluster Kubernetes usando Dex, dex-k8s-authenticator e GitHub.

imagem

Meme local do chat em língua russa Kubernetes no Telegram

1. Introdução


Usamos o Kubernetes para criar ambientes dinâmicos para a equipe de desenvolvimento e o controle de qualidade. Portanto, queremos dar a eles acesso ao cluster para os painéis e o kubectl. Ao contrário do OpenShift, o Kubernetes de baunilha não possui autenticação nativa; portanto, usamos ferramentas de terceiros para isso.

Nesta configuração, usamos:

  • dex-k8s-authenticator - aplicativo da web para gerar a configuração do kubectl
  • Dex - Fornecedor do OpenID Connect
  • GitHub - simplesmente porque usamos o GitHub em nossa empresa

Tentamos usar o Google OIDC, mas, infelizmente, não conseguimos encontrá-los em grupos; portanto, a integração com o GitHub foi muito bem conosco. Sem o mapeamento de grupo, você não pode criar políticas RBAC baseadas em grupo.

Então, como nosso processo de autorização no Kubernetes funciona em uma representação visual:

imagem
Processo de autorização

Um pouco mais de detalhes e pontos:

  1. O usuário efetua login no dex-k8s-authenticator ( login.k8s.example.com )
  2. O dex-k8s-authenticator redireciona a solicitação para o Dex ( dex.k8s.example.com )
  3. Dex redireciona para a página de login do GitHub
  4. O GitHub gera as informações de autorização necessárias e as retorna ao Dex
  5. Dex passa as informações recebidas para dex-k8s-authenticator
  6. Usuário obtém token OIDC do GitHub
  7. dex-k8s-authenticator adiciona um token ao kubeconfig
  8. O kubectl passa o token para o KubeAPIServer
  9. O KubeAPIServer baseado no token transferido retorna acessos no kubectl
  10. O usuário obtém acesso do kubectl

Atividades preparatórias


Obviamente, já temos um cluster k8s.example.com ( k8s.example.com ) instalado, além do HELM. Também temos uma organização no GitHub (super-org).
Se você não possui o HELM, é muito fácil de instalar.

Primeiro, precisamos configurar o GitHub.

Vá para a página de configurações da organização ( https://github.com/organizations/super-org/settings/applications ) e crie um novo aplicativo (aplicativo autorizado do OAuth):
imagem
Criando um novo aplicativo no GitHub

Preencha os campos com os URLs necessários, por exemplo:

  • URL da página inicial: https://dex.k8s.example.com
  • URL de retorno de chamada de autorização: https://dex.k8s.example.com/callback

Cuidado com os links, pois é importante não perder barras.

Em resposta ao formulário preenchido, o GitHub irá gerar o Client ID do Client ID e o Client secret , salvando-os em um local seguro, eles serão úteis para nós (por exemplo, usamos o Vault para armazenar segredos):

 Client ID: 1ab2c3d4e5f6g7h8 Client secret: 98z76y54x32w1 

Prepare registros DNS para os subdomínios login.k8s.example.com e dex.k8s.example.com , bem como certificados SSL para entradas.

Crie certificados 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 

Um ClusterIssuer com o nome le-clusterissuer já deve existir, caso contrário, crie-o 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: {} EOF 

Configuração do KubeAPIServer


Para que o kubeAPIServer funcione, você deve configurar o OIDC e atualizar o 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 

Usamos o kops para implantar clusters, mas funciona da mesma forma para outros gerenciadores de cluster .

Configuração de dex e dex-k8s-authenticator


Para que Dex funcione, você deve ter um certificado e uma chave do mestre do Kubernetes, retirando-o de lá:

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

Clone o repositório dex-k8s-authenticator:

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

Usando arquivos de valores, podemos definir variáveis ​​de forma flexível para nossos gráficos HELM .

Vamos descrever a configuração do 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 

E para o dex-k8s-authenticator:
 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 

Instale 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-authenticator 

Vamos verificar a capacidade de manutenção dos serviços (o Dex deve retornar o código 400 e o dex-k8s-authenticator - o código 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 

Configuração RBAC


Criamos o ClusterRole para o grupo, no nosso caso com acessos somente leitura:

 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 

Crie uma configuração para 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 

Agora estamos prontos para o teste.

Testes


Vamos para a página de login ( https://login.k8s.example.com ) e efetuamos login usando a conta do GitHub:

imagem
Página de login

imagem
Página de login redirecionada para o GitHub

imagem
Siga as instruções geradas para acesso

Após copiar e colar da página da web, podemos usar o kubectl para gerenciar os recursos do nosso 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 funciona: todos os usuários do GitHub em nossa organização podem ver recursos e inserir pods, mas eles não têm o direito de alterá-los.

Source: https://habr.com/ru/post/pt436238/


All Articles