Práticas recomendadas para o RBAC do GKE


Nesta página, você verá práticas recomendadas para planejar suas políticas de controle de acesso baseado em papéis (RBAC, na sigla em inglês). Para saber como implementar o RBAC no Google Kubernetes Engine (GKE), consulte Configurar o controle de acesso baseado em papéis.

O RBAC é um recurso de segurança principal do Kubernetes, que permite criar permissões refinadas para gerenciar quais ações os usuários e cargas de trabalho podem executar nos recursos dos clusters. Como administrador de plataforma, você cria papéis do RBAC e vincula esses papéis a assuntos, que são usuários autenticados, como o serviço contas ou grupos.

Antes de começar

Verifique se você está familiarizado com os seguintes conceitos:

Para uma lista de verificação, consulte o Resumo da lista de verificação.

Como o RBAC funciona

O RBAC é compatível com os seguintes tipos de papéis e vinculações:

  • ClusterRole:: conjunto de permissões aplicáveis a qualquer namespace ou a todo o cluster.
  • Papel: um conjunto de permissões limitado a um único namespace.
  • ClusterRoleBinding: atribua um ClusterRole a um usuário ou a um grupo para todos os namespaces no cluster.
  • RoleBinding: atribua um Role ou ClusterRole a um usuário ou grupo em um namespace específico.

Defina as permissões como rules em um Role ou uma ClusterRole. Cada campo rules em um papel consiste em um grupo de APIs, os recursos da API nesse grupo e os verbos (ações) permitidos nesses recursos. Também é possível definir o verbo para instâncias nomeadas de recursos da API usando o campo resourceNames. Para ver um exemplo, consulte Restringir o acesso a instâncias de recursos específicas.

Depois de definir um papel, use RoleBinding ou ClusterRoleBinding para vinculá-lo a um sujeito. Escolha o tipo de vinculação com base na concessão de permissões em um único namespace ou em vários namespaces.

Design de papéis do RBAC

Use o princípio de privilégio mínimo

Ao atribuir permissões em um papel do RBAC, use o princípio de privilégio mínimo e conceda o mínimo de permissões necessárias para executar uma tarefa. O uso do princípio de privilégio mínimo reduz o potencial de escalonamento de privilégios se o cluster estiver comprometido e reduz a probabilidade de que o acesso excessivo resulte em um incidente de segurança.

Ao projetar seus papéis, considere cuidadosamente os riscos comuns de escalonamento de privilégios, como verbos escalate ou bind, acesso create para PersistentVolumes ou acesso create para solicitações de assinatura de certificado. Para ver uma lista de riscos, consulte RBAC do Kubernetes: riscos de escalonamento de privilégios.

Evitar funções e grupos padrão

O Kubernetes cria um conjunto de ClusterRoles e ClusterRoleBindings padrão que você pode usar para a descoberta de API e para ativar a funcionalidade do componente gerenciado. As permissões concedidas por esses papéis padrão podem ser extensas, dependendo do papel. O Kubernetes também tem um conjunto de usuários e grupos padrão, identificado pelo prefixo system:. Por padrão, o Kubernetes e o GKE vinculam automaticamente esses papéis aos grupos padrão e a vários assuntos. Para ver uma lista completa dos papéis e vinculações padrão que o Kubernetes cria, consulte Papéis e vinculações de papéis padrão.

A tabela a seguir descreve alguns papéis, usuários e grupos padrão. Recomendamos evitar a interação com esses papéis, usuários e grupos, a menos que você os tenha avaliado cuidadosamente, porque interagir com esses recursos pode ter consequências não intencionais na postura de segurança do cluster.

Nome Tipo Descrição
cluster-admin ClusterRole Concede uma permissão de assunto para fazer qualquer coisa em qualquer recurso no cluster.
system:anonymous Usuário

O Kubernetes atribui esse usuário às solicitações do servidor de API que não têm as informações de autenticação fornecidas.

Vincular um papel a esse usuário fornece a qualquer usuário não autenticado as permissões concedidas por esse papel.

system:unauthenticated Grupo

O Kubernetes atribui esse grupo a solicitações do servidor de API que não têm informações de autenticação fornecidas.

Vincular um papel a esse grupo fornece a qualquer usuário não autenticado as permissões concedidas por esse papel.

system:authenticated Grupo

O GKE atribui esse grupo a solicitações do servidor de API feitas por qualquer usuário conectado com uma Conta do Google, incluindo todas as contas do Gmail. Na prática, isso não é significativamente diferente de system:unauthenticated, porque qualquer pessoa pode criar uma Conta do Google.

Vincular um papel a este grupo concede a qualquer usuário uma Conta do Google, incluindo todas as contas do Gmail, as permissões concedidas por esse papel.

system:masters Grupo

O Kubernetes atribui o ClusterRole cluster-admin a este grupo por padrão para ativar a funcionalidade do sistema.

Se você adicionar os próprios assuntos a este grupo, eles terão acesso para fazer qualquer coisa em qualquer recurso no cluster.

Se possível, evite criar vinculações que envolvam usuários, papéis e grupos padrão. Isso pode ter consequências inesperadas para a postura de segurança do cluster. Por exemplo:

  • Vincular o ClusterRole cluster-admin padrão ao grupo system:unauthenticated dá a qualquer usuário não autenticado acesso a todos os recursos no cluster, incluindo Secrets. Essas vinculações altamente privilegiadas são visadas ativamente por ataques, como campanhas em massa de malware.
  • Vincular um papel personalizado ao grupo system:unauthenticated fornece aos usuários não autenticados as permissões concedidas por esse papel.

Quando possível, use as seguintes diretrizes:

  • Não adicione seus próprios assuntos ao grupo system:masters.
  • Não vincule o grupo system:unauthenticated a nenhum papel do RBAC.
  • Não vincule o grupo system:authenticated a nenhum papel do RBAC.
  • Não vincule ao usuário system:anonymous a nenhum papel do RBAC.
  • Não vincule o ClusterRole cluster-admin aos seus assuntos ou a qualquer usuário e grupo padrão. Se o aplicativo exigir muitas permissões, determine as permissões exatas necessárias e crie um papel específico para essa finalidade.
  • Avalie as permissões concedidas por outros papéis padrão antes de vincular assuntos.
  • Avalie os papéis vinculados aos grupos padrão antes de modificar os membros deles.

Impedir o uso de grupos padrão

É possível usar a gcloud CLI para desativar as vinculações não padrão do controle de acesso baseado em função (RBAC) em um cluster com referência aos grupos system:unauthenticated e system:authenticated ou ao usuário system:anonymous. Use uma ou ambas as flags a seguir ao criar um novo cluster do GKE ou atualizar um cluster já existente. O uso dessas flags não desativa as vinculações padrão do Kubernetes com referência a esses grupos. Essas flags exigem o GKE versão 1.30.1-gke.1283000 ou posterior.

Detectar e remover o uso de papéis e grupos padrão

Avalie os clusters para identificar se você vinculou o usuário system:anonymous ou os grupos system:unauthenticated ou system:authenticated usando ClusterRoleBindings e RoleBindings.

ClusterRoleBindings
  1. Liste os nomes de qualquer ClusterRoleBindings com o assunto system:anonymous, system:unauthenticated ou system:authenticated:

    kubectl get clusterrolebindings -o json \
      | jq -r '["Name"], ["-----"], (.items[] | select((.subjects | length) > 0) | select(any(.subjects[]; .name == "system:anonymous" or .name == "system:unauthenticated" or .name == "system:authenticated")) | [.metadata.namespace, .metadata.name]) | @tsv'
    

    A saída deve listar apenas os seguintes ClusterRoleBindings:

    Name
    ----
    "system:basic-user"
    "system:discovery"
    "system:public-info-viewer"
    

    Se a saída contiver outras vinculações não padrão, siga as etapas a seguir para cada vinculação adicional. Se a saída não contiver vinculações não padrão, pule as etapas a seguir.

  2. Liste as permissões do papel associado à vinculação:

    kubectl get clusterrolebinding CLUSTER_ROLE_BINDING_NAME -o json \
        | jq ' .roleRef.name +" " + .roleRef.kind' \
        | sed -e 's/"//g' \
        | xargs -l bash -c 'kubectl get $1 $0 -o yaml'
    

    Substitua CLUSTER_ROLE_BINDING_NAME pelo nome do ClusterRoleBinding não padrão.

    O resultado será assim:

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
    ...
    rules:
    - apiGroups:
      - ""
      resources:
      - secrets
      verbs:
      - get
      - watch
      - list
    

    Se você determinar que as permissões na saída são seguras para os usuários ou grupos padrão, nenhuma outra ação será necessária. Se você determinar que as permissões concedidas pela vinculação não são seguras, avance para a próxima etapa.

  3. Exclua uma vinculação não segura do seu cluster:

    kubectl delete clusterrolebinding CLUSTER_ROLE_BINDING_NAME
    

    Substitua CLUSTER_ROLE_BINDING_NAME pelo nome do ClusterRoleBinding a ser excluído.

RoleBindings
  1. Liste o namespace e o nome de qualquer RoleBinding com o assunto system:anonymous, system:unauthenticated ou system:authenticated:

    kubectl get rolebindings -A -o json \
      | jq -r '["Namespace", "Name"], ["---------", "-----"], (.items[] | select((.subjects | length) > 0) | select(any(.subjects[]; .name == "system:anonymous" or .name == "system:unauthenticated" or .name == "system:authenticated")) | [.metadata.namespace, .metadata.name]) | @tsv'
    

    Se o cluster estiver configurado corretamente, a saída vai ficar em branco. Se a saída contiver outras vinculações não padrão, siga as etapas a seguir para cada vinculação adicional. Se a saída estiver em branco, pule as etapas a seguir.

    Se você souber apenas o nome do RoleBinding, use o seguinte comando para encontrar vinculações de papéis correspondentes em todos os namespaces:

    kubectl get rolebindings -A -o json \
      | jq -r '["Namespace", "Name"], ["---------", "-----"], (.items[] | select((.subjects | length) > 0) | select(.metadata.name == "ROLE_BINDING_NAME") | [.metadata.namespace, .metadata.name]) | @tsv'
    

    Substitua ROLE_BINDING_NAME pelo nome do RoleBinding não padrão.

  2. Liste as permissões do papel associado à vinculação:

    kubectl get rolebinding ROLE_BINDING_NAME --namespace ROLE_BINDING_NAMESPACE -o json \
        | jq ' .roleRef.name +" " + .roleRef.kind' \
        | sed -e 's/"//g' \
        | xargs -l bash -c 'kubectl get $1 $0 -o yaml --namespace ROLE_BINDING_NAMESPACE'
    

    Substitua:

    • ROLE_BINDING_NAME: o nome do RoleBinding não padrão.
    • ROLE_BINDING_NAMESPACE: o namespace do RoleBinding não padrão.

    O resultado será assim:

    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
    ...
    rules:
    - apiGroups:
      - ""
      resources:
      - secrets
      verbs:
      - get
      - watch
      - list
    

    Se você determinar que as permissões na saída são seguras para os usuários ou grupos padrão, nenhuma outra ação será necessária. Se você determinar que as permissões concedidas pela vinculação não são seguras, avance para a próxima etapa.

  3. Exclua uma vinculação não segura do seu cluster:

    kubectl delete rolebinding ROLE_BINDING_NAME --namespace ROLE_BINDING_NAMESPACE
    

    Substitua:

    • ROLE_BINDING_NAME: o nome do RoleBinding a ser excluído.
    • ROLE_BINDING_NAMESPACE: o namespace do RoleBinding a ser excluído.

Permissões do escopo para o nível de namespace

Use vinculações e papéis da seguinte maneira, dependendo das necessidades da carga de trabalho ou do usuário:

  • Para conceder acesso a recursos em um namespace, use um Role com um RoleBinding.
  • Para conceder acesso a recursos em mais de um namespace, use um ClusterRole com um RoleBinding para cada namespace.
  • Para conceder acesso a recursos em todos os namespaces, use um ClusterRole com um ClusterRoleBinding.

Conceda permissões no menor número possível de namespaces.

Não use caracteres curinga

O caractere * é um padrão de caracteres curinga que se aplica a tudo. Evite usar caracteres curinga nas regras. Especificar explicitamente grupos de API, recursos e verbos nas regras do RBAC Por exemplo, a especificação de * no campo verbs concederia get, list, watch, patch, update, deletecollection, e delete nos recursos. A tabela a seguir mostra exemplos de como evitar caracteres curinga nas regras:

Recomendado Não recomendado
- rules:
    apiGroups: ["apps","extensions"]
    resources: ["deployments"]
    verbs: ["get","list","watch"]

Concede verbos get, list e watch especificamente aos grupos de APIs apps e extensions.

- rules:
    apiGroups: ["*"]
    resources: ["deployments"]
    verbs: ["get","list","watch"]

Concede os verbos a deployments em qualquer grupo de APIs.

- rules:
    apiGroups: ["apps", "extensions"]
    resources: ["deployments"]
    verbs: ["get", "list", "watch"]

Concede apenas verbos get, list e watch às implantações nos grupos de APIs apps e extensions.

- rules:
    apiGroups: ["apps", "extensions"]
    resources: ["deployments"]
    verbs: ["*"]

Concede todos os verbos, incluindo patch ou delete.

Use regras separadas para conceder acesso com privilégio mínimo a recursos específicos

Ao planejar suas regras, tente as seguintes etapas gerais para um design de regra de privilégio mínimo mais eficiente em cada papel:

  1. Rascunho de regras separadas do RBAC para cada verbo em cada recurso que um assunto precisa acessar.
  2. Depois de fazer o rascunho das regras, analise-as para verificar se várias têm a mesma lista verbs. Combine essas regras em uma única regra.
  3. Mantenha todas as regras restantes separadas.

Essa abordagem resulta em um design de regra mais organizado, em que as regras que concedem os mesmos verbos a vários recursos são combinadas e as regras que concedem verbos diferentes a recursos são separadas.

Por exemplo, se sua carga de trabalho precisar de permissões para o recurso deployments, mas precisar de list e watch nos recursos daemonsets, use regras separadas ao criar um papel. Quando você vincula o papel do RBAC à carga de trabalho, ele não pode usar watch em deployments.

Outro exemplo: se sua carga de trabalho precisa de get e watch nos recursos pods e daemonsets, é possível combiná-las em uma única regra, porque a carga de trabalho precisa dos mesmos verbos nos dois recursos.

Na tabela a seguir, os dois projetos de regras funcionam, mas as regras de divisão restringem mais o acesso a recursos com base nas suas necessidades:

Recomendado Não recomendado
- rules:
    apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get"]
- rules:
    apiGroups: ["apps"]
    resources: ["daemonsets"]
    verbs: ["list", "watch"]

Concede acesso de get para implantações e acesso de watch e list para DaemonSets. Assuntos não podem listar implantações.

- rules:
    apiGroups: ["apps"]
    resources: ["deployments", "daemonsets"]
    verbs: ["get","list","watch"]

Concede os verbos a implantações e DaemonSets. Um sujeito que não pode exigir acesso list em objetos deployments ainda receberia esse acesso.

- rules:
    apiGroups: ["apps"]
    resources: ["daemonsets", "deployments"]
    verbs: ["list", "watch"]

Combina duas regras porque o assunto precisa dos mesmos verbos para os recursos daemonsets e deployments.

- rules:
    apiGroups: ["apps"]
    resources: ["daemonsets"]
    verbs: ["list", "watch"]
- rules:
    apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["list", "watch"]

Essas regras de divisão teriam o mesmo resultado que a regra combinada, mas criariam desordem desnecessária no manifesto do papel.

Restringir o acesso a instâncias de recursos específicas

O RBAC permite usar o campo resourceNames nas suas regras para restringir o acesso a uma instância específica nomeada de um recurso. Por exemplo, se você estiver criando um papel de RBAC que precise update do ConfigMap seccomp-high e nada mais, use resourceNames para especificar apenas esse ConfigMap. Use resourceNames sempre que possível.

Recomendado Não recomendado
- rules:
    apiGroups: [""]
    resources: ["configmaps"]
    resourceNames: ["seccomp-high"]
    verbs: ["update"]

Restringe o assunto a atualizar apenas o ConfigMap seccomp-high. O assunto não pode atualizar nenhum outro ConfigMaps no namespace.

- rules:
    apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["update"]

O assunto pode atualizar o ConfigMap seccomp-high e qualquer outro ConfigMap no namespace.

- rules:
    apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["list"]
- rules:
    apiGroups: [""]
    resources: ["configmaps"]
    resourceNames: ["seccomp-high"]
    verbs: ["update"]

Concede acesso de list a todos os ConfigMaps no namespace, incluindo seccomp-high. Restringe o acesso update apenas ao ConfigMap seccomp-high. As regras são divididas porque não é possível conceder a list recursos nomeados.

- rules:
    apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["update", "list"]

Concede acesso de update para todos os ConfigMaps, além de acesso list.

Não permitir que as contas de serviço modifiquem recursos do RBAC

Não vincule recursos Role ou ClusterRole que tenham as permissões bind, escalate, create, update ou patch à rbac.authorization.k8s.io Grupo de APIs para contas de serviço em qualquer namespace. escalate e bind, em particular, podem permitir que um invasor ignore os mecanismos de prevenção de encaminhamento integrados ao RBAC.

Contas de Serviço Kubernetes

Crie uma conta de serviço do Kubernetes para cada carga de trabalho

Crie uma conta de serviço do Kubernetes separada para cada carga de trabalho. Vincule um privilégio mínimo Role ou ClusterRole a essa conta de serviço.

Não usar a conta de serviço padrão

O Kubernetes cria uma conta de serviço chamada default em todos os namespaces. A conta de serviço default é atribuída automaticamente aos pods que não especificam explicitamente uma conta de serviço no manifesto. Evite vincular um Role ou ClusterRole à conta de serviço default. O Kubernetes pode atribuir a conta de serviço default a um pod que não precisa do acesso concedido nesses papéis.

Não montar tokens de conta de serviço automaticamente

O campo automountServiceAccountToken na especificação do pod informa ao Kubernetes para injetar um token de credencial de uma conta de serviço do Kubernetes no pod. O pod pode usar esse token para fazer solicitações autenticadas para o servidor da API Kubernetes. O valor padrão deste campo é true.

Em todas as versões do GKE, defina automountServiceAccountToken=false na especificação do pod se os pods não precisarem se comunicar com o servidor da API.

Use tokens temporários em vez de tokens baseados em secrets

Por padrão, o processo do kubelet no nó recupera um token da conta de serviço de curta duração com rotação automática para cada pod. O kubelet monta esse token no pod como um volume projetado, a menos que você defina o campo automountServiceAccountToken como false na especificação do pod. Todas as chamadas para a API Kubernetes a partir do pod usam esse token para autenticar no servidor da API.

Se você estiver recuperando manualmente os tokens da conta de serviço, evite usar secrets do Kubernetes para armazenar o token. Os tokens de conta de serviço baseados em secret são credenciais legadas que não expiram e não são alternadas automaticamente. Se você precisar de credenciais para contas de serviço, use a API TokenRequest para receber tokens de curta duração que são alternados automaticamente.

Analisar continuamente as permissões do RBAC

Revise os papéis do RBAC e o acesse regularmente para identificar possíveis caminhos de escalonamento e regras redundantes. Por exemplo, considere uma situação em que você não exclui uma RoleBinding que vincula um Role com privilégios especiais a um usuário excluído. Se um invasor criar uma conta de usuário nesse namespace com o mesmo nome do usuário excluído, ele será vinculado a esse Role e herdará o mesmo acesso. As avaliações periódicas minimizam esse risco.

Lista de verificação resumida

A seguir