Aplique políticas de segurança personalizadas ao nível do pod com o Gatekeeper

Esta página mostra como usar o controlador de admissão do Gatekeeper para aplicar controlos de segurança ao nível do pod aos seus clusters do Google Kubernetes Engine (GKE). Nesta página, vai saber como usar o Gatekeeper para aplicar restrições que lhe permitem aplicar políticas de segurança para ajudar a cumprir os requisitos de segurança da sua organização.

Esta página destina-se a especialistas em segurança que querem aplicar controlos de segurança aos respetivos clusters do GKE. Para saber mais sobre as funções comuns e as tarefas de exemplo que referimos no conteúdo, consulte o artigo Funções e tarefas comuns do utilizador do GKE. Google Cloud

Antes de ler esta página, certifique-se de que conhece os seguintes conceitos:

Vista geral do Gatekeeper

O Gatekeeper é um controlador de admissão que valida pedidos para criar e atualizar pods em clusters do Kubernetes, usando o Open Policy Agent (OPA).

A utilização do Gatekeeper permite que os administradores definam políticas com uma restrição, que é um conjunto de condições que permitem ou negam comportamentos de implementação no Kubernetes. Em seguida, pode aplicar estas políticas num cluster através de um ConstraintTemplate. Este documento fornece exemplos para restringir as capacidades de segurança das cargas de trabalho para garantir a aplicação, o teste e a auditoria das políticas de segurança através do Gatekeeper.

O Gatekeeper também pode:

  • Implemente políticas: aplique a política de forma gradual e restrita para limitar o risco de interromper as cargas de trabalho.
  • Alterações à política de execução de teste: forneça mecanismos para testar o impacto e o alcance da política antes da aplicação.
  • Audite as políticas existentes: garanta a aplicação de controlos de segurança a cargas de trabalho novas e existentes (controlos de auditoria).

Conceitos principais do Gatekeeper

O Gatekeeper introduz dois conceitos para oferecer aos administradores um meio poderoso e flexível de controlar o respetivo cluster: restrições e modelos de restrições, que são conceitos herdados da estrutura de restrições do Open Policy Agent.

As restrições são a representação da sua política de segurança. Definem os requisitos e o âmbito da aplicação. Os modelos de restrições são declarações reutilizáveis (escritas em Rego) que aplicam lógica para avaliar campos específicos em objetos Kubernetes, com base nos requisitos definidos nas restrições.

Por exemplo, pode ter uma restrição que declare perfis seccomp permitidos que podem ser aplicados a pods num espaço de nomes específico e um modelo de restrição comparável que forneça a lógica para extrair estes valores e processar a aplicação.

O seguinte modelo de restrição, do repositório Gatekeeper, verifica a existência de securityContext.privileged numa especificação de Pod:

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8spspprivilegedcontainer
spec:
  crd:
    spec:
      names:
        kind: K8sPSPPrivilegedContainer
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8spspprivileged

        violation[{"msg": msg, "details": {}}] {
            c := input_containers[_]
            c.securityContext.privileged
            msg := sprintf("Privileged container is not allowed: %v, securityContext: %v", [c.name, c.securityContext])
        }
        input_containers[c] {
            c := input.review.object.spec.containers[_]
        }
        input_containers[c] {
            c := input.review.object.spec.initContainers[_]
        }

Para expandir o exemplo do modelo de restrição anterior, a seguinte restrição define o âmbito (kinds) para a aplicação específica deste modelo de restrição num modo dryrun:

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sPSPPrivilegedContainer
metadata:
  name: psp-privileged-container
spec:
  enforcementAction: dryrun
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]

Com o Gatekeeper, pode criar as suas próprias restrições e modelos de restrições para satisfazer as suas necessidades específicas. Também pode usar um conjunto padrão de restrições e modelos de restrições no repositório do Gatekeeper que foram definidos para permitir uma adoção rápida e a aplicação da segurança. Cada restrição também é acompanhada de exemplos de configurações de agrupamentos.

Google Cloud oferece uma versão gerida e oficialmente suportada do Gatekeeper de código aberto denominada Policy Controller. A Google não suporta oficialmente o projeto Gatekeeper de código aberto.

Antes de começar

Antes de começar, certifique-se de que realizou as seguintes tarefas:

  • Ative a API Google Kubernetes Engine.
  • Ative a API Google Kubernetes Engine
  • Se quiser usar a CLI gcloud para esta tarefa, instale-a e, em seguida, inicialize-a. Se instalou anteriormente a CLI gcloud, execute gcloud components update para obter a versão mais recente.

Ative o Gatekeeper num cluster com o Policy Controller

O Policy Controller é um motor de políticas criado com base no projeto de código aberto Gatekeeper. A Google recomenda a utilização do Policy Controller porque inclui funcionalidades adicionais para ajudar a aplicar políticas à escala, incluindo políticas como código, suporte multi-cluster, integração com o Cloud Logging e a capacidade de ver o estado das políticas na Google Cloud consola. O Policy Controller está disponível com o GKE, mas pode instalar o Gatekeeper no seu cluster.

Para ativar o Policy Controller num cluster, siga o guia de instalação do Policy Controller.

Ative restrições e modelos de restrições

O Gatekeeper e os respetivos modelos de restrições podem ser instalados e ativados sem afetar negativamente as cargas de trabalho existentes ou novas. Por este motivo, recomendamos que todos os modelos de restrição de segurança de pods aplicáveis sejam aplicados ao cluster.

Além disso, podem ser implementadas restrições do Gatekeeper para aplicar controlos a objetos específicos, como espaços de nomes e pods.

Observe o exemplo abaixo que limita o âmbito aos Pods localizados no espaço de nomes de produção definindo-os na declaração de correspondência de restrições:

...
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
    namespaces:
      - "production"

Para mais informações sobre as opções disponíveis para objetos Constraint e ConstraintTemplate, consulte o artigo Como usar o Gatekeeper.

Teste políticas

A introdução de novas políticas em clusters existentes pode ter um comportamento adverso, por exemplo, restringindo cargas de trabalho existentes. Uma das vantagens de usar o Gatekeeper para a segurança de pods é a capacidade de testar a eficácia e o impacto que uma política terá sem fazer alterações reais, usando um modo de teste. Isto permite testar a configuração da política em clusters em execução sem aplicação. As violações de políticas são registadas e identificadas sem interferência.

Os passos seguintes demonstram como um programador, um operador ou um administrador pode aplicar modelos de restrições e restrições para determinar a respetiva eficácia ou potencial impacto:

  1. Aplique a configuração do Gatekeeper para replicar dados para fins de auditoria e funcionalidade de teste:

    kubectl create -f- <<EOF
    apiVersion: config.gatekeeper.sh/v1alpha1
    kind: Config
    metadata:
      name: config
      namespace: "gatekeeper-system"
    spec:
      sync:
        syncOnly:
          - group: ""
            version: "v1"
            kind: "Namespace"
          - group: ""
            version: "v1"
            kind: "Pod"
    EOF
    
  2. Sem restrições aplicadas, execute uma carga de trabalho com privilégios elevados:

    kubectl create -f- <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        securityContext:
          privileged: true
    EOF
    
  3. Carregue o modelo de restrição k8spspprivilegedcontainer anterior:

    kubectl create -f- <<EOF
    apiVersion: templates.gatekeeper.sh/v1beta1
    kind: ConstraintTemplate
    metadata:
      name: k8spspprivilegedcontainer
    spec:
      crd:
        spec:
          names:
            kind: K8sPSPPrivilegedContainer
      targets:
        - target: admission.k8s.gatekeeper.sh
          rego: |
            package k8spspprivileged
    
            violation[{"msg": msg, "details": {}}] {
                c := input_containers[_]
                c.securityContext.privileged
                msg := sprintf("Privileged container is not allowed: %v, securityContext: %v", [c.name, c.securityContext])
            }
            input_containers[c] {
                c := input.review.object.spec.containers[_]
            }
            input_containers[c] {
                c := input.review.object.spec.initContainers[_]
            }
    EOF
    
  4. Crie uma nova restrição para estender este modelo de restrição. Desta vez, defina o enforcementAction para dryrun:

    kubectl create -f- <<EOF
    apiVersion: constraints.gatekeeper.sh/v1beta1
    kind: K8sPSPPrivilegedContainer
    metadata:
      name: psp-privileged-container
    spec:
      enforcementAction: dryrun
      match:
        kinds:
          - apiGroups: [""]
            kinds: ["Pod"]
    EOF
    
  5. Com o Gatekeeper a sincronizar os dados dos objetos em execução e a verificar passivamente a existência de violações, confirme se foram encontradas violações verificando o status da restrição:

    kubectl get k8spspprivilegedcontainer.constraints.gatekeeper.sh/psp-privileged-container -o yaml
    
    apiVersion: constraints.gatekeeper.sh/v1beta1
    kind: K8sPSPPrivilegedContainer
    metadata:
    ...
     name: psp-privileged-container
    ...
    spec:
     enforcementAction: dryrun
     match:
       kinds:
       - apiGroups:
         - ""
         kinds:
         - Pod
    status:
     auditTimestamp: "2019-12-15T22:19:54Z"
     byPod:
     - enforced: true
       id: gatekeeper-controller-manager-0
     violations:
     - enforcementAction: dryrun
       kind: Pod
       message: 'Privileged container is not allowed: nginx, securityContext: {"privileged":
         true}'
       name: nginx
       namespace: default
    
  6. Para confirmar que a política não interfere com as implementações, execute outro pod privilegiado:

    kubectl create -f- <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
      name: privpod
      labels:
        app: privpod
    spec:
      containers:
      - name: nginx
        image: nginx
        securityContext:
          privileged: true
    EOF
    

    Este novo pod vai ser implementado com êxito.

  7. Para limpar os recursos criados nesta secção, execute os seguintes comandos:

    kubectl delete k8spspprivilegedcontainer.constraints.gatekeeper.sh/psp-privileged-container
    kubectl delete constrainttemplate k8spspprivilegedcontainer
    kubectl delete pod/nginx
    kubectl delete pod/privpod
    

Aplique políticas

Agora que pode confirmar a validade e o impacto de uma política sem afetar as cargas de trabalho existentes ou novas, pode implementar uma política com aplicação total.

Com base nos exemplos usados para validar a política acima, os passos seguintes demonstram como um programador, um operador ou um administrador pode aplicar modelos e restrições de restrições para aplicar uma política:

  1. Carregue o modelo de restrição k8spspprivilegedcontainer mencionado anteriormente:

    kubectl create -f- <<EOF
    apiVersion: templates.gatekeeper.sh/v1beta1
    kind: ConstraintTemplate
    metadata:
      name: k8spspprivilegedcontainer
    spec:
      crd:
        spec:
          names:
            kind: K8sPSPPrivilegedContainer
      targets:
        - target: admission.k8s.gatekeeper.sh
          rego: |
            package k8spspprivileged
    
            violation[{"msg": msg, "details": {}}] {
                c := input_containers[_]
                c.securityContext.privileged
                msg := sprintf("Privileged container is not allowed: %v, securityContext: %v", [c.name, c.securityContext])
            }
            input_containers[c] {
                c := input.review.object.spec.containers[_]
            }
            input_containers[c] {
                c := input.review.object.spec.initContainers[_]
            }
    EOF
    
  2. Crie uma nova restrição para estender este modelo de restrição. Desta vez, não defina a chave do enforcementAction. Por predefinição, a chave enforcementAction está definida como deny:

    kubectl create -f- <<EOF
    apiVersion: constraints.gatekeeper.sh/v1beta1
    kind: K8sPSPPrivilegedContainer
    metadata:
      name: psp-privileged-container
    spec:
      match:
        kinds:
          - apiGroups: [""]
            kinds: ["Pod"]
    EOF
    
  3. Tentar implementar um contentor que declare autorizações privilegiadas:

    kubectl create -f- <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        securityContext:
          privileged: true
    EOF
    

    Deve receber a seguinte mensagem de erro:

    Error from server ([denied by psp-privileged-container] Privileged container is not allowed:
    nginx, securityContext: {"privileged": true}): error when creating "STDIN": admission webhook "validation.gatekeeper.sh" denied the request: [denied by psp-privileged-container]
    Privileged container is not allowed: nginx, securityContext: {"privileged": true}
    
  4. Para limpar, execute os seguintes comandos:

    kubectl delete k8spspprivilegedcontainer.constraints.gatekeeper.sh/psp-privileged-container
    kubectl delete constrainttemplate k8spspprivilegedcontainer
    

Alternativas ao Gatekeeper

O Gatekeeper permite-lhe declarar e aplicar políticas de segurança personalizadas ao nível do pod. Também pode usar o PodSecuritycontrolador de admissão integrado do Kubernetes para aplicar políticas de segurança predefinidas ao nível do pod. Estas políticas predefinidas estão alinhadas com os níveis definidos pelas Normas de segurança de pods.

O que se segue?

O Gatekeeper oferece um meio incrivelmente eficaz de aplicar e validar a segurança em clusters do GKE através de políticas declarativas. No entanto, a utilização do Gatekeeper vai além da segurança e pode ser usada noutros aspetos da administração e das operações.