Usuários e HBAC no Kubernetes
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:
- 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)
- 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
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