Usuários e HBAC no Kubernetes

Wed, Mar 3, 2021 5-minute read

Usuários e HBAC no Kubernetes

Para realizar qualquer ação em um cluster Kubernetes, você precisa acessar pela API e seguir por três etapas:

Autenticação: Autorização (ABAC ou RBAC): Controle de admissao.

Autenticação:

Existem três pontos principais a que devemos lembrar com a autenticação no Kubernetes:

De uma forma simples, a autenticação é feita com certificados, tokens ou autenticação básica (ou seja, nome de usuário e senha). Os usuários não são criados pela API, devem ser gerenciados por um sistema externo. As contas do sistema são usadas por processos para acessar a API (para saber mais, leia Configurar contas de serviço para pods).

Certificado x509

Para realizar a autenticação de um usuário vamos usar certificados assinados pela CA do kubernetes:

  1. Vamos criar a chave:
openssl genrsa -out capivara.key 2048

Resultado

Generating RSA private key, 2048 bit long modulus (2 primes)
..................................+++++
..+++++
e is 65537 (0x010001)
  1. Em seguida a requisição de assinatura de certificado
openssl req -new -subj "/CN=Kubernetes/CN=Capivara" -key capivara.key -out capivara.csr

3, Criar um certificado assinado pela CA do Kubernetes:

sudo openssl x509 -req -in capivara.csr -CAcreateserial -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -out capivara.crt

Contextos do Kubernetes

Uma vez que nossa chave foi criada, vamos associa-la a uma crendencial e um contexto do kubernetes, para seguir com os nossos testes vamos criar dois namespaces para poder ver a utilidade na pratica:

Crie os seguites namespaces development e production:

kubectl create ns development
kubectl create ns production

Seguindo vamos criar a credencial Capivara no nosso cluster:

kubectl config set-credentials capivara --client-certificate=/home/vagrant/capivara.crt --client-key=capivara.key

Resultado

User "capivara" set.

Com o usuário e namespaces criados vamos associá-los à um contexto, cada namespace vai ter o um context especifico:

kubectl config set-context DEV-Capivara --cluster=kubernetes --user=capivara --namespace=development

Resultado

Context "DEV-Capivara" created.

e prod:

kubectl config set-context PROD-Capivara --cluster=kubernetes --user=capivara --namespace=production

Resultado

Context "PROD-Capivara" created.

Liste os contextos disponiveis e certifique que os contextos recém-criados existem:

CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE  
          DEV-Capivara                  kubernetes   capivara           development
          PROD-Capivara                 kubernetes   capivara           production 
          kubernetes-admin@kubernetes   kubernetes   kubernetes-admin              

Até esse momento seguimos o seguinte fluxo:

Certificado -> Criação da Credencial -> Associar a Credential à um contexto

Agora com um contexto criado podemos testa-lo e nos certificar o seu funcionamento:

 kubectl --context=DEV-Capivara get pods

Resultado

Error from server (Forbidden): pods is forbidden: User "Capivara" cannot list resource "pods" in API group "" in the namespace "development"

Perceba que recebemos uma mensagem de erro, dizendo basicamente que o acesso foi negado, ele autenticou porém o acesso foi negado, então é nesse momento que vamos trabalhar com as RBAC.

Autorização (RBAC):

Atualizando o nosso fluxo:

  • Determinar ou criar namespace
  • Criar credenciais de certificado para o usuário
  • Defina as credenciais do usuário para o namespace usando um contexto
  • Crie uma função para o conjunto de tarefas esperado
  • Vincule o usuário à função
  • Verifique se o usuário tem acesso limitado.

Depois que uma solicitação é autenticada, ela precisa ser autorizada para poder prosseguir no sistema Kubernetes e executar a ação pretendida.

Todos os recursos são objetos da API modelados no Kubernetes, de pods a namespaces. Eles também pertencem a grupos de API, como CORE e apps. Esses recursos permitem operações como Create, Read, Update e Delete (CRUD), com as quais vamos trabalhado. Essas operações são chamadas de verbos nos arquivos YAML. Adicionando a esses componentes básicos, mais elementos da API, podemos gerenciar via RBAC.

Development Namespace

Como estamos criando regras de RBAC para namespaces especificos, vamos usar as roles, se fossemos criar regras no nível do cluster usariamos clusteroles:

cat > role-dev.yaml <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: development
  name: dev
rules:
- apiGroups: ["", "apps", "extensions"]
  resources: ["pods", "deployments", "replicasets"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
EOF

Crie a regra via kubectl:

kubectl create -f role-dev.yaml

Resultado

role.rbac.authorization.k8s.io/dev created

Agora vamos associar o usuário Capivara à role dev

cat > role-dev-binding.yaml <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: dev-binding
  namespace: development
subjects:
- kind: User
  name: Capivara
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: dev
  apiGroup: rbac.authorization.k8s.io
EOF

Crie a RoleBinding via kubectl:

kubectl create -f role-dev-binding.yaml

Resultado

rolebinding.rbac.authorization.k8s.io/dev-binding created

O RoleBinding segue o mesmo principio das Roles, se a regra fosse no nivel do cluste, usuáriamos ClusterRoleBinding mas o nosso exemplo usamos apenas o RoleBinding.

Hora da verdade! Agora podemos testar o contexto DEV-Capivara:

kubectl --context=DEV-Capivara create deployment nginx --image=nginx

Resultado

deployment.apps/nginx created

It's Alive!

Faça mais alguns testes:

kubectl --context=DEV-Capivara get po

Resultado

NAME                     READY   STATUS    RESTARTS   AGE  
nginx-6799fc88d8-8kk54   1/1     Running   0          118s 

Production Namespace

Agora podemos continuar e criar as Roles e RolesBinding para o namespace production:

Testando a falta de permissão:

kubectl --context=PROD-Capivara get po

Resultado

Error from server (Forbidden): pods is forbidden: User "Capivara" cannot list resource "pods" in API group "" in the namespace "production"

Roles:

cat > role-prod.yaml <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: production
  name: prod
rules:
- apiGroups: ["", "apps", "extensions"]
  resources: ["pods", "deployments"]
  verbs: ["get", "list", "watch"]
EOF

kubectl create -f role-prod.yaml

Resultado

role.rbac.authorization.k8s.io/prod created

RolesBinding

cat > role-prod-binding.yaml <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: prod-binding
  namespace: production
subjects:
- kind: User
  name: Capivara
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: prod
  apiGroup: rbac.authorization.k8s.io
EOF

kubectl create -f role-prod-binding.yaml

Resultado

rolebinding.rbac.authorization.k8s.io/prod-binding created 

Como não temos nenhum pod rodando nesse namespace o cluster vai responder que realmente não existe o recurso solicitado, isso valida a nossa permissão de leitura

kubectl --context=PROD-Capivara get po

Resultado

No resources found in production namespace.

Valide a permissão de apenas listar os pods no namespace production:

kubectl --context=PROD-Capivara run busybox --image=busybox

Resultado

Error from server (Forbidden): pods is forbidden: User "Capivara" cannot create resource "pods" in API group "" in the namespace "production"

OBS: todos os testes podem ser feitos via kubectl auth can-i

Controle de admissão.

A última etapa para permitir uma solicitação de API no Kubernetes é o admission control.

Os admission control são softwares que podem acessar o conteúdo dos objetos que estão sendo solicitados. Eles podem modificar o conteúdo ou validá-lo e potencialmente negar a solicitação.

Labs para fixar:

Crie um ClusterRole e ClusterRoleBinding para que o usuário secret@test.com possa acessar e gerenciar apenas secrets. Teste-o.

Crie um ClusterRole e ClusterRoleBinding para que o usuário deploy@test.com só possa implantar e gerenciar pods chamados compute. Teste-o.

Crie um ClusterRole e ClusterRoleBinding adicionais para deploy@test.com, adicionar permissão de leitura a segredos chamados compute-secret. Teste-o.

Referencias:

https://kubernetes.io/docs/reference/access-authn-authz/authorization/

https://kubernetes.io/docs/concepts/security/controlling-access/

https://kubernetes.io/docs/reference/access-authn-authz/rbac/

https://kubernetes.io/docs/reference/access-authn-authz/rbac/#rolebinding-and-clusterrolebinding

https://medium.com/faun/kubernetes-cka-hands-on-challenge-7-rbac-ac1cf1684dd5