Gravar um modelo de restrição personalizado

Esta página mostra como gravar um modelo de restrição personalizado e usá-lo para estender o Policy Controller se você não encontrar um modelo de restrição pré-gravado que se adapte às suas necessidades.

Esta página é destinada a administradores e operadores de TI que querem garantir que todos os recursos em execução na plataforma de nuvem cumpram os requisitos de compliance organizacional, fornecendo e mantendo automação para auditar ou aplicar, e usar modelos de configuração declarativa. Para saber mais sobre papéis comuns e tarefas de exemplo referenciados no conteúdo do Google Cloud, consulte Tarefas e funções de usuário comuns do GKE Enterprise.

As políticas do controlador de políticas são descritas usando a biblioteca de restrições de OPA e são programadas em Rego (links em inglês). Uma política pode avaliar qualquer campo de um objeto Kubernetes.

Escrever políticas usando o Rego é uma habilidade especializada. Por esse motivo, uma biblioteca de modelos de restrição comuns é instalada por padrão. Você provavelmente pode invocar esses modelos de restrição ao criar restrições. Se você tiver necessidades especializadas, poderá criar seus próprios modelos de restrição.

Os modelos de restrição permitem separar a lógica de uma política dos requisitos específicos para reutilização e delegação. É possível criar restrições usando modelos de restrição desenvolvidos por terceiros, como projetos de código aberto, fornecedores de software ou especialistas em regulamentação.

Antes de começar

Modelo de restrição de exemplo

Veja a seguir um modelo de restrição de exemplo que nega todos os recursos cujo nome corresponde a um valor fornecido pelo criador da restrição. O restante desta página discute o conteúdo do modelo, destacando conceitos importantes.

Se você estiver usando o Config Sync com um repositório hierárquico, recomendamos criar suas restrições no diretório cluster/.

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8sdenyname
spec:
  crd:
    spec:
      names:
        kind: K8sDenyName
      validation:
        # Schema for the `parameters` field
        openAPIV3Schema:
          properties:
            invalidName:
              type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sdenynames
        violation[{"msg": msg}] {
          input.review.object.metadata.name == input.parameters.invalidName
          msg := sprintf("The name %v is not allowed", [input.parameters.invalidName])
        }

Restrição de exemplo

Veja a seguir uma restrição de exemplo que pode ser implementada para negar todos os recursos chamados policy-violation:

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sDenyName
metadata:
  name: no-policy-violation
spec:
  parameters:
    invalidName: "policy-violation"

Partes de um modelo de restrição

Os modelos de restrição têm duas partes importantes:

  • O esquema da restrição que você quer que os usuários criem. O esquema de um modelo de restrição é armazenado no campo crd.

  • O código-fonte Rego que é executado quando a restrição é avaliada. O código fonte Rego para um modelo é armazenado no campo targets.

Esquema (campo crd)

O campo CRD é um modelo para criar a Definição de Recurso Personalizado do Kubernetes que define o recurso de restrição para o servidor da API Kubernetes. Você só precisa preencher os seguintes campos:

Campo Descrição
spec.crd.spec.names.kind O tipo da restrição. Quando em minúsculas, o valor desse campo precisa ser igual a metadata.name.
spec.crd.spec.validation.openAPIV3Schema

O esquema do campo spec.parameters do recurso de restrição (o Controlador de Políticas define automaticamente o restante do esquema da restrição). Ele segue as mesmas convenções de um recurso regular de CRD.

Prefixo do modelo de restrição com nome K8s é uma convenção que permite evitar conflitos com outros tipos de modelos de restrição, como modelos do Forseti que segmentam recursos do Google Cloud.

Código-fonte original (campo targets)

As seções a seguir fornecem mais informações sobre o código-fonte do Rego.

Local

O código-fonte do Rego é armazenado no campo spec.targets, em que targets é uma matriz de objetos no seguinte formato:

{"target": "admission.k8s.gatekeeper.sh","rego": REGO_SOURCE_CODE, "libs": LIST_OF_REGO_LIBRARIES}
  • target: informa ao Controlador de Políticas qual sistema estamos conferindo (neste caso, Kubernetes); apenas uma entrada em targets é permitida.
  • rego é o código-fonte da restrição.
  • libs: uma lista opcional de bibliotecas do código do Rego que é disponibilizada para o modelo de restrição. Ele foi desenvolvido para facilitar o uso de bibliotecas compartilhadas e está fora do escopo deste documento.

Código-fonte

Veja a seguir o código-fonte do Rego para a restrição anterior:

package k8sdenynames

violation[{"msg": msg}] {
   input.review.object.metadata.name == input.parameters.invalidName
   msg := sprintf("The name %v is not allowed", [input.parameters.invalidName])
}

Observe o seguinte:

  • package k8sdenynames é requerido pelo OPA (ambiente de execução do Rego). O valor é ignorado.
  • A regra Rego que o Policy Controller chama para verificar se há alguma violação é chamada violation. Se essa regra tiver correspondências, ocorreu uma violação da restrição.
  • A regra violation tem a assinatura violation[{"msg": "violation message for the user"}], onde o valor de "msg" é a mensagem de violação retornada ao usuário.
  • Os parâmetros fornecidos à restrição são disponibilizados sob a palavra-chave input.parameters.
  • O request-under-test é armazenado sob a palavra-chave input.review.

A palavra-chave input.review tem os campos a seguir.

Campo Descrição
uid O ID exclusivo dessa solicitação. Não fica disponíveis durante a auditoria.
kind

As informações de Tipo de object-under-test. Ele tem o seguinte formato:

  • kind o tipo de recurso
  • group o grupo de recursos
  • version: a versão do recurso
name O nome do recurso. É possível que ela esteja vazia se o usuário depende do servidor de API para gerar o nome em uma solicitação CREATE.
namespace O namespace do recurso (não fornecido para recursos com escopo no cluster).
operation A operação solicitada (por exemplo, CREATE ou UPDATE). Não ficam disponíveis durante a auditoria.
userInfo

As informações do usuário solicitante. Não é possível fazer isso durante a auditoria. Ele tem o seguinte formato:

  • username: o usuário que está fazendo a solicitação
  • uid: o UID do usuário
  • groups: uma lista de grupos do qual o usuário é membro
  • extra: qualquer informação extra fornecida pelo Kubernetes.
object O objeto que o usuário está tentando modificar ou criar
oldObject O estado original do objeto. Está disponível somente nas operações UPDATE.
dryRun Se esta solicitação foi invocada com kubectl --dry-run Ela não estará disponível durante a auditoria.

Escrever modelos de restrição referencial

Modelos de restrição referencial são modelos que permitem ao usuário restringir um objeto em relação a outros objetos. Um exemplo disso pode ser "não permita que um pod seja criado antes que se saiba que existe uma entrada correspondente". Outro exemplo pode ser "não permitir que dois serviços tenham o mesmo nome de host".

O Policy Controller permite que você escreva restrições referenciais observando o servidor de API para conseguir um conjunto de recursos fornecidos pelo usuário. Quando um recurso é modificado, o Policy Controller o armazena em cache localmente, para que possa ser facilmente referenciado pelo código-fonte Rego. O Policy Controller disponibiliza esse cache com a palavra-chave data.inventory.

Os recursos com escopo definido em cluster são armazenados em cache no seguinte local:

data.inventory.cluster["GROUP_VERSION"]["KIND"]["NAME"]

Por exemplo, um nó chamado my-favorite-node pode ser encontrado em

data.inventory.cluster["v1"]["Node"]["my-favorite-node"]

Recursos com namespace são armazenados em cache aqui:

data.inventory.namespace["NAMESPACE"]["GROUP_VERSION"]["KIND"]["NAME"]

Por exemplo, um ConfigMap chamado production-variables no namespace shipping-prod pode ser encontrado em

data.inventory.namespace["shipping-prod"]["v1"]["ConfigMap"]["production-variables"]

O conteúdo completo do objeto é armazenado nesse local de cache e pode ser referenciado no seu Rego da maneira que você achar melhor.

Mais informações sobre Rego

As informações anteriores fornecem os recursos exclusivos do Policy Controller que facilitam a gravação de restrições nos recursos do Kubernetes no Rego. Um tutorial completo sobre como programar no Rego está fora do escopo deste guia. No entanto, a documentação do agente de política aberta tem informações sobre a sintaxe e os recursos da própria linguagem Rego.

Instalar seu modelo de restrição

Depois de criar o modelo de restrição, use kubectl apply para aplicá-lo. O Policy Controller cuidará do processamento. Verifique o campo status do seu modelo de restrição para garantir que não haja erros ao instancia-lo. Na ingestão bem-sucedida, o campo status precisa mostrar created: true e o observedGeneration anotado no campo status precisa ser igual ao campo metadata.generation.

Depois que o modelo é ingerido, você pode aplicar restrições, conforme descrito em Como criar restrições.

Remover um modelo de restrição

Para remover um modelo de restrição, siga estas etapas:

  1. Verifique se nenhuma restrição que você quer preservar está usando o modelo de restrição:

    kubectl get TEMPLATE_NAME
    

    No caso de um conflito de nomenclatura entre o nome do modelo de restrição e um objeto diferente no cluster, use o seguinte comando:

    kubectl get TEMPLATE_NAME.constraints.gatekeeper.sh
    
  2. Remova o modelo de restrição:

    kubectl delete constrainttemplate CONSTRAINT_TEMPLATE_NAME
    

Quando você remove um modelo de restrição, não é mais possível criar restrições que o referenciem.

A seguir