Entendendo o RBAC no Kubernetes

Nota perev. : Este artigo foi escrito por Javier Salmeron, engenheiro da conhecida comunidade Kubernetes em Bitnami, e publicado no blog do CNCF no início de agosto. O autor fala sobre os princípios básicos do mecanismo RBAC (controle de acesso baseado em função) que apareceu no Kubernetes há um ano e meio. O material será especialmente útil para aqueles que estão familiarizados com o dispositivo dos principais componentes dos K8s (consulte os links para outros artigos semelhantes no final).


Slide de uma apresentação feita por um funcionário do Google na ocasião do lançamento do Kubernetes 1.6

Muitos usuários experientes do Kubernetes podem se lembrar da versão 1.6 do Kubernetes, quando a autorização baseada em Controle de Acesso Baseado em Função (RBAC) se tornou beta. Portanto, apareceu um mecanismo de autenticação alternativo, que complementava o ABAC (controle de acesso baseado em atributos) já existente, mas difícil de gerenciar e entender. Todos receberam com entusiasmo o novo recurso, mas ao mesmo tempo inúmeros usuários ficaram decepcionados. StackOverflow e GitHub abundavam com relatórios de restrições RBAC, porque a maioria da documentação e exemplos não levavam em conta o RBAC (mas agora está tudo bem). O exemplo de referência foi Helm: apenas executar helm init + helm install não funcionou mais. De repente, precisávamos adicionar elementos "estranhos", como ServiceAccounts ou RoleBindings antes mesmo de implantarmos o gráfico com WordPress ou Redis (consulte as instruções para obter mais informações).

Deixando de lado essas primeiras tentativas malsucedidas, não se pode negar a enorme contribuição que o RBAC fez para transformar o Kubernetes em uma plataforma pronta para produção. Muitos de nós conseguiram jogar com o Kubernetes com privilégios totais de administrador e entendemos perfeitamente que em um ambiente real é necessário:

  • Ter muitos usuários com propriedades diferentes que fornecem o mecanismo de autenticação desejado.
  • Tenha controle total sobre quais operações cada usuário ou grupo de usuários pode executar.
  • Tenha controle total sobre quais operações cada processo no coração pode executar.
  • Limite a visibilidade de determinados recursos nos espaços para nome.

E, nesse sentido, o RBAC é um elemento-chave que fornece os recursos muito necessários. No artigo, abordaremos rapidamente o básico (consulte este vídeo para obter detalhes; siga o link do webinar Bitnami de 1 hora em inglês - aprox. Transl. ) E aprofundaremos um pouco os momentos mais confusos.

A chave para entender o RBAC no Kubernetes


Para realizar completamente a idéia do RBAC, você precisa entender que três elementos estão envolvidos nela:

  • Assuntos - um conjunto de usuários e processos que desejam ter acesso à API do Kubernetes;
  • Recursos - Uma coleção de objetos da API do Kubernetes disponíveis em um cluster. Seus exemplos (entre outros) são Pods , Implantações , Serviços , Nós , PersistentVolumes ;
  • Verbos (verbos) - um conjunto de operações que podem ser executadas em recursos. Existem vários verbos (obter, observar, criar, excluir etc.), mas todos são operações da categoria CRUD (Criar, Ler, Atualizar, Excluir).



Com esses três elementos em mente, a ideia principal do RBAC é:

"Queremos conectar os assuntos, recursos da API e operações." Em outras palavras, queremos indicar para um determinado usuário quais operações podem ser executadas em uma variedade de recursos .

Noções básicas sobre objetos RBAC na API


Ao combinar esses três tipos de entidades, os objetos RBAC disponíveis na API do Kubernetes ficam claros:

  • Roles conectam recursos e verbos. Eles podem ser reutilizados para diferentes assuntos. Vinculado a um espaço para nome (não podemos usar modelos que representam mais de um [espaço para nome], mas podemos implantar o mesmo objeto de função em diferentes espaços para nome). Se você deseja aplicar a função ao cluster inteiro, há um objeto ClusterRoles semelhante.
  • RoleBindings conectam as demais entidades. Ao especificar uma função que já vincula objetos da API a verbos, agora selecionamos os assuntos que podem usá-los. O equivalente para o nível do cluster (ou seja, sem ligação a espaços para nome) é ClusterRoleBindings .

No exemplo abaixo, damos ao usuário jsalmeron o direito de ler, obter uma lista e criar lares no espaço de nome de teste . Isso significa que o jsalmeron poderá executar estes comandos:

 kubectl get pods --namespace test kubectl describe pod --namespace test pod-name kubectl create --namespace test -f pod.yaml #      

... mas não é assim:

 kubectl get pods --namespace kube-system #    kubectl get pods --namespace test -w #    watch 



Exemplos de arquivos YAML:

 kind: Role apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: pod-read-create namespace: test rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "create"] 

 kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: salme-pods namespace: test subjects: - kind: User name: jsalmeron apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: pod-read-create apiGroup: rbac.authorization.k8s.io 

Outro ponto interessante é o seguinte: agora que o usuário pode criar pods, podemos limitar quanto? Isso exigirá outros objetos que não estejam diretamente relacionados à especificação RBAC e permitirá que você configure limites de recursos: ResourceQuota e LimitRanges . Definitivamente vale a pena explorar ao configurar um componente de cluster tão importante [como criar lareiras].

Assuntos: Usuários e ... ServiceAccounts?


Uma das dificuldades que muitos usuários do Kubernetes enfrentam no contexto de assuntos é a distinção entre usuários regulares e ServiceAccounts . Em teoria, tudo é simples:

  • Users - usuários globais, projetados para pessoas ou processos que vivem fora do cluster;
  • ServiceAccounts - limitado pelo namespace e destinado a processos dentro do cluster em execução em pods.

A semelhança de ambos os tipos reside na necessidade de se autenticar com a API para executar determinadas operações em muitos recursos, e suas áreas de assunto parecem muito específicas. Eles também podem pertencer a grupos, portanto, o RoleBinding permite vincular mais de um assunto (embora apenas um grupo seja permitido para ServiceAccounts - system:serviceaccounts ). No entanto, a principal diferença é a causa da dor de cabeça: os usuários não têm objetos correspondentes a eles na API do Kubernetes. Acontece que essa operação existe:

 kubectl create serviceaccount test-service-account # OK 

... mas este se foi:

 kubectl create user jsalmeron # ! 

Essa situação tem uma consequência séria: se o cluster não armazenar informações sobre usuários, o administrador precisará gerenciar contas fora do cluster. Existem diferentes maneiras de resolver o problema: certificados TLS, tokens, OAuth2 etc.

Além disso, você precisará criar contextos kubectl que possamos acessar o cluster por meio dessas novas contas. Para criar arquivos com eles, você pode usar os comandos kubectl config (que não requerem acesso à API do Kubernetes, para que possam ser executados por qualquer usuário). O vídeo acima tem um exemplo de criação de um usuário com certificados TLS.

RBAC em implantações: exemplo


Vimos um exemplo no qual o usuário especificado recebe direitos para operações no cluster. Mas e as implantações que exigem acesso à API do Kubernetes? Considere um cenário específico para entender melhor.

Tomemos, por exemplo, o popular aplicativo de infraestrutura - RabbitMQ. Usaremos o Gráfico de Helm Bitmami para RabbitMQ (do repositório oficial de helm / charts), que usa o contêiner bitnami / rabbitmq . Um plug-in para o Kubernetes está embutido no contêiner, responsável por detectar outros membros do cluster RabbitMQ. Por esse motivo, o processo dentro do contêiner requer acesso à API do Kubernetes e precisamos configurar a ServiceAccount com os privilégios corretos do RBAC.

Quando se trata de ServiceAccounts , siga estas boas práticas:

- Configure ServiceAccounts para cada implantação com um conjunto mínimo de privilégios .

Para aplicativos que exigem acesso à API do Kubernetes, você pode ser tentado a criar algum tipo de " ServiceAccount privilegiada" que pode fazer quase tudo no cluster. Embora isso pareça uma solução mais simples, pode levar a uma vulnerabilidade de segurança que pode permitir operações indesejadas. (O vídeo mostra um exemplo de um Tiller [componente Helm] e as consequências de ter ServiceAccounts com grandes privilégios.)

Além disso, diferentes implantações terão necessidades diferentes em termos de acesso à API, portanto, é razoável que cada implantação tenha ServiceAccounts diferentes.

Tendo isso em mente, vamos ver qual configuração do RBAC está correta para o caso do Deployment com o RabbitMQ.

Na documentação do plug - in e seu código-fonte, você pode ver que ele está solicitando uma lista de pontos de extremidade da API do Kubernetes. É assim que os membros restantes do cluster RabbitMQ são detectados. Portanto, o gráfico Bitnami RabbitMQ cria:

  • ServiceAccount para lares com RabbitMQ:

     {{- if .Values.rbacEnabled }} apiVersion: v1 kind: ServiceAccount metadata: name: {{ template "rabbitmq.fullname" . }} labels: app: {{ template "rabbitmq.name" . }} chart: {{ template "rabbitmq.chart" . }} release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}" {{- end }} 
  • Função (assumimos que todo o cluster RabbitMQ esteja implementado em um único espaço de nome), permitindo que o verbo obtenha o recurso Endpoint :

     {{- if .Values.rbacEnabled }} kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: name: {{ template "rabbitmq.fullname" . }}-endpoint-reader labels: app: {{ template "rabbitmq.name" . }} chart: {{ template "rabbitmq.chart" . }} release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}" rules: - apiGroups: [""] resources: ["endpoints"] verbs: ["get"] {{- end }} 
  • RoleBinding conectando um ServiceAccount a uma função:

     {{- if .Values.rbacEnabled }} kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: {{ template "rabbitmq.fullname" . }}-endpoint-reader labels: app: {{ template "rabbitmq.name" . }} chart: {{ template "rabbitmq.chart" . }} release: "{{ .Release.Name }}" heritage: "{{ .Release.Service }}" subjects: - kind: ServiceAccount name: {{ template "rabbitmq.fullname" . }} roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: {{ template "rabbitmq.fullname" . }}-endpoint-reader {{- end }} 



O diagrama mostra que permitimos que os processos em execução nos pods RabbitMQ realizassem operações get nos objetos Endpoint . Este é o conjunto mínimo de operações necessárias para que tudo funcione. Ao mesmo tempo, sabemos que o gráfico implantado é seguro e não executará ações indesejadas dentro do cluster Kubernetes.

Considerações finais


Para trabalhar com o Kubernetes na produção, as políticas do RBAC não são opcionais. Eles não podem ser considerados como um conjunto de objetos de API que somente os administradores devem conhecer. Os desenvolvedores realmente precisam deles para implantar aplicativos seguros e aproveitar ao máximo o potencial oferecido pela API Kubernetes para aplicativos nativos da nuvem. Mais informações sobre o RBAC podem ser encontradas nesses links:


PS do tradutor


Leia também em nosso blog:

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


All Articles