Programar um módulo personalizado para o Security Health Analytics

Nesta página, explicamos como codificar uma definição de módulo personalizado usando a Common Expression Language (CEL) e o YAML.

Use a Google Cloud CLI para fazer upload das definições dos seus módulos personalizados para o Security Health Analytics.

No arquivo YAML, uma definição de módulo personalizado consiste em um conjunto estruturado de propriedades que você usa para definir os seguintes elementos de um módulo personalizado do Security Health Analytics:

  • Os recursos a serem verificados.
  • A lógica de detecção a ser usada.
  • As informações a serem fornecidas às equipes de segurança para que elas possam entender, filtrar e resolver rapidamente o problema detectado.

As propriedades obrigatórias e opcionais que compõem uma definição YAML são abordadas em Etapas de programação.

Evitar a criação de detectores redundantes

Para controlar a localização de volume, evite criar e executar módulos que contenham funcionalidade redundante.

Por exemplo, se você criar um módulo personalizado que verifica chaves de criptografia que não são rotacionadas após 30 dias, considere desativar o detector integrado do Security Health Analytics KMS_KEY_NOT_ROTATED, porque a verificação que usa um valor de 90 dias, seria supérfluo.

Para saber mais sobre como desativar detectores, consulte Ativar e desativar detectores.

Etapas de programação

Você codifica a definição de um módulo personalizado para o Security Health Analytics como uma série de propriedades YAML, algumas contendo expressões CEL.

Para codificar um módulo de definição personalizado, siga estas etapas:

  1. Crie um arquivo de texto com a extensão de nome de arquivo yaml.

  2. No arquivo de texto, crie uma propriedade resource_selector e especifique de um a cinco tipos de recursos a serem verificados pelo módulo personalizado. Um tipo de recurso não pode ser especificado mais de uma vez em uma definição de módulo personalizado. Exemplo:

    resource_selector:
     resource_types:
     ‐ cloudkms.googleapis.com/CryptoKey

    Os tipos de recurso especificados precisam ser compatíveis com o Security Command Center. Para acessar uma lista de tipos de recursos compatíveis, consulte Tipos de recursos compatíveis.

  3. Crie uma propriedade predicate e especifique uma ou mais expressões CEL que verificam as propriedades dos tipos de recursos a serem verificados. Todas as propriedades referenciadas nas expressões CEL precisam existir na definição da API Google Cloud de cada tipo de recurso especificado em resource_selector. Para acionar uma descoberta, a expressão precisa ser resolvida como TRUE. Por exemplo, na expressão a seguir, apenas valores rotationPeriod maiores que 2592000s acionam uma descoberta.

    predicate:
     expression: resource.rotationPeriod > duration("2592000s")

    Se você precisar de ajuda para escrever expressões CEL, consulte os seguintes recursos:

  4. Crie uma propriedade description que explique a vulnerabilidade ou configuração incorreta detectada pelo módulo personalizado. Essa explicação aparece em cada instância de descoberta para ajudar os investigadores a entender o problema detectado. O texto precisa estar entre aspas. Exemplo:

    description: "The rotation period of
     the identified cryptokey resource exceeds 30 days, the
     maximum rotation period that our security guidelines allow."
  5. Crie uma propriedade recommendation que explique como corrigir o problema detectado. A CLI gcloud requer um caractere de escape antes de determinados caracteres, como aspas. O exemplo a seguir mostra o uso da barra invertida como um escape para cada conjunto de aspas:

    recommendation: "To fix this issue go to
      https://console.cloud.google.com/security/kms. Click the key-ring that
      contains the key. Click the key. Click \"Edit rotation period\". Then
      set the rotation period to at most 30 days."
    

    Se você criar ou atualizar um módulo personalizado usando o console do Google Cloud, os caracteres de escape não serão obrigatórios.

  6. Crie uma propriedade severity e especifique a gravidade padrão para as descobertas criadas por este módulo. Os valores mais usados para a propriedade severity são LOW, MEDIUM, HIGH e CRITICAL. Por exemplo:

    severity: MEDIUM
  7. Se quiser, crie uma propriedade custom_output e especifique outras informações para retornar com cada descoberta. Especifique as informações que serão retornadas como um ou mais pares de nome-valor. É possível retornar o valor de uma propriedade do recurso verificado ou uma string literal. As propriedades precisam ser especificadas como resource.PROPERTY_NAME. As strings literais precisam estar entre aspas. O exemplo a seguir mostra uma definição de custom_output que retorna um valor de propriedade, o valor de rotationPeriod no recurso CryptoKey verificado e uma string de texto, "Excessive rotation period for CryptoKey":

     custom_output:
       properties:
         - name: duration
           value_expression:
             expression: resource.rotationPeriod
         - name: note
           value_expression:
             expression: "Excessive rotation period for CryptoKey"
    
  8. Salve o arquivo em um local que a CLI gcloud possa acessar.

  9. Faça upload da definição no Security Health Analytics com o seguinte comando:

     gcloud scc custom-modules sha create \
         --organization=organizations/ORGANIZATION_ID \
         --display-name="MODULE_DISPLAY_NAME" \
         --enablement-state="ENABLED" \
         --custom-config-from-file=DEFINITION_FILE_NAME.yaml
    

    Substitua os seguintes valores:

    • ORGANIZATION_ID pelo ID da organização pai do módulo personalizado ou substituir a sinalização --organization por --folders ou --project e especificar o ID da pasta ou projeto pai.
    • MODULE_DISPLAY_NAME com um nome a ser exibido como a categoria de descoberta quando o módulo personalizado retorna descobertas. O nome precisa ter entre 1 e 128 caracteres, começar com letra minúscula e conter apenas caracteres alfanuméricos ou sublinhados.
    • DEFINITION_FILE_NAME pelo caminho e nome do arquivo YAML que contém a definição do módulo personalizado.

    Para mais informações sobre como trabalhar com os módulos personalizados do Security Health Analytics, consulte Como usar módulos personalizados para o Security Health Analytics.

Verificar as latências em busca de novos módulos personalizados

A criação de um módulo personalizado não aciona uma nova verificação.

O Security Health Analytics não começa a usar um novo módulo personalizado até uma das seguintes opções:

  • A primeira verificação em lote após a criação do módulo personalizado. Dependendo de quando você cria um módulo personalizado na programação de leitura em lote, pode ser necessário esperar até 24 horas para que o Security Health Analytics comece a usar o módulo personalizado.
  • Uma mudança em um recurso de destino aciona uma verificação em tempo real.

Exemplo de definição de módulo personalizado

O exemplo a seguir mostra uma definição de módulo personalizado concluída que aciona uma descoberta se o valor da propriedade rotationPeriod de um recurso cloudkms.googleapis.com/CryptoKey for maior que 2.592.000 segundos (30 dias). O exemplo retorna dois valores opcionais na seção custom_output: o valor de resource.rotationPeriod e uma observação como uma string de texto.

No exemplo, observe os seguintes elementos:

  • O tipo de recurso a ser verificado está listado na seção resource_selector em resource_types.
  • A verificação que o módulo executa nos recursos, a lógica de detecção, é definida na seção predicate precedida por expression.
  • Duas propriedades de origem personalizadas, duration e violation, são definidas na seção custom_output.
  • A explicação do problema que foi detectado é especificada na propriedade description.
  • As orientações para corrigir o problema detectado são especificadas na propriedade recommendation. Como as aspas aparecem na orientação, é necessário um caractere de escape de barra invertida antes de cada aspa.
severity: HIGH
description: "Regular key rotation helps provide protection against
compromised keys, and limits the number of encrypted messages available
to cryptanalysis for a specific key version."
recommendation: "To fix this issue go to
https://console.cloud.google.com/security/kms. Click the key-ring that
contains the key. Click the key. Click \"Edit rotation period\". Then
set the rotation period to at most 30 days."
resource_selector:
  resource_types:
  - cloudkms.googleapis.com/CryptoKey
predicate:
  expression: resource.rotationPeriod > duration("2592000s")
custom_output:
  properties:
    - name: duration
      value_expression:
        expression: resource.rotationPeriod
    - name: violation
      value_expression:
        expression:
          "Excessive rotation period for CryptoKey"

Como referenciar propriedades de recursos e políticas em módulos personalizados

Seja qual for o método usado para criar um módulo personalizado, seja usando o console do Google Cloud ou escrevendo a definição, você precisa pesquisar as propriedades que pode avaliar na módulo personalizado. Você também precisa saber como referenciar essas propriedades em uma definição de módulo personalizada.

Encontrar as propriedades de um recurso ou política

As propriedades de um recurso do Google Cloud são definidas na definição da API do recurso. Para encontrar essa definição, clique no nome do recurso em Tipos de recursos compatíveis.

As propriedades de uma política estão disponíveis na documentação de referência da API IAM. Para propriedades de uma política, consulte Política.

Fazer referência a uma propriedade de recurso em uma definição de módulo personalizada

Quando você cria um módulo personalizado, todas as referências diretas à propriedade de um recurso verificado precisam começar com resource, seguido por qualquer propriedade pai e, por fim, pela propriedade de destino. As propriedades são separadas por um ponto, usando uma notação de ponto no estilo JSON.

Veja a seguir exemplos de propriedades de recurso e como elas podem ser recuperadas:

  • resourceName: armazena o nome completo de um recurso no Inventário de recursos do Cloud, por exemplo, //cloudresourcemanager.googleapis.com/projects/296605646631.
  • resource.rotationPeriod: em que rotationPeriod é uma propriedade de resource.
  • resource.metadata.name: em que name é uma subpropriedade de metadata, que é uma subpropriedade de resource.

Propriedades de referência das políticas do IAM

É possível criar expressões de CEL que avaliam a política do IAM de um recurso fazendo referência às propriedades da política do IAM do recurso. As únicas propriedades disponíveis são vinculações e papéis dentro de vinculações.

Ao fazer referência às propriedades de política do IAM, policy é a propriedade de nível superior.

Veja a seguir exemplos de propriedades de política do IAM e como elas podem ser recuperadas:

  • policy.bindings, em que bindings é uma propriedade de policy.
  • policy.version, em que version é uma propriedade de policy.

Para mais exemplos, consulte Exemplos de expressões CEL.

Para mais informações sobre as propriedades de uma política, consulte Política.

Como escrever expressões CEL

Ao criar um módulo personalizado, você usa expressões CEL para avaliar as propriedades do recurso verificado. Também é possível usar expressões CEL para definir pares personalizados name-value que retornam mais informações com suas descobertas.

Se você estiver criando um módulo personalizado no console do Google Cloud ou escrevendo sua definição de módulo personalizado em um arquivo YAML, as expressões CEL definidas serão as mesmas.

Expressões CEL para lógica de detecção

Codifique a lógica de detecção de um módulo personalizado usando expressões CEL com operadores CEL padrão para avaliar as propriedades dos recursos verificados.

Suas expressões podem ser verificações simples de um único valor ou expressões compostas mais complexas que verificam vários valores ou condições. De qualquer forma, a expressão precisa ser resolvida com um true booleano para acionar uma descoberta.

Se você estiver criando um módulo personalizado no console do Google Cloud, escreva essas expressões no Editor de expressões na página Configurar módulo.

Se você estiver codificando um módulo personalizado em um arquivo YAML, adicione essas expressões na propriedade predicate.

Independentemente de você estar usando o console do Google Cloud ou um arquivo YAML, as expressões CEL que avaliam propriedades de recursos precisam estar em conformidade com as seguintes regras:

  • As propriedades especificadas em uma expressão CEL precisam ser propriedades do recurso verificado, conforme definido na definição da API do tipo de recurso.
  • Se um módulo personalizado avaliar vários tipos de recursos, as propriedades especificadas nas expressões CEL precisarão ser comuns a cada tipo de recurso avaliado pelo módulo personalizado.

    Por exemplo, se você definir um módulo personalizado chamado invalid_cryptokey que verifica dois tipos de recursos: cloudkms.googleapis.com/CryptoKey e cloudkms.googleapis.com/CryptoKeyVersion, é possível escrever a seguinte expressão, porque os tipos de recursos CryptoKey e CryptoKeyVersion incluem a propriedade name:

    predicate:
    resource.name.matches("projects/project1/locations/us-central1/keyRings/keyring1/cryptoKeys/.*")

    No entanto, não é possível especificar a expressão a seguir no módulo personalizado invalid_cryptokey porque as propriedades importTime e rotationPeriod que a expressão avalia não são compartilhadas pelos dois tipos de recursos:

    predicate:
    resource.importTime >= timestamp("2022-10-02T15:01:23Z") || resource.rotationPeriod > duration("2592000s")
  • Todas as enumerações em uma expressão CEL precisam ser representadas como strings. Por exemplo, uma expressão válida para o tipo de recurso cloudkms.googleapis.com/CryptoKeyVersion:

    resource.state = "PENDING_GENERATION"
  • O resultado das expressões CEL definidas na propriedade predicate precisa ser um booleano. Uma descoberta será acionada somente se o resultado for true.

Para mais informações sobre CEL, consulte estes documentos:

Exemplo de expressões CEL

A tabela a seguir lista algumas expressões CEL que podem ser usadas para avaliar as propriedades dos recursos. É possível usar isso no console do Google Cloud e nas definições do módulo personalizado YAML.

Resource type Explicação Expressão CEL
Qualquer recurso com uma política do IAM Verificação de política do IAM para identificar membros de fora do domínio !policy.bindings.all(binding, binding.members.all(m ,!m.endsWith('@gmail.com')))
cloudkms.googleapis.com/CryptoKey Verificação do período de rotação de chaves do Cloud KMS has(resource.rotationPeriod) && resource.rotationPeriod > duration('60h')
Vários tipos de recursos com uma única política Verifique se o nome do recurso começa com dev ou devAccess com base no tipo de recurso (resource.type == 'compute.googleapis.com/Disk' && resource.name.startsWith('projects/PROJECT_ID/regions/ REGION/disks/devAccess')) || (resource.type == 'compute.googleapis.com/Instance ' && resource.name.startsWith('projects/PROJECT_ID/zones/REGION/instances/dev-'))
compute.googleapis.com/Network Regra de peering da nuvem privada virtual para corresponder a pares de redes resource.selfLink.matches('https://www.googleapis.com/compute/v1/projects/PROJECT_ID/global/networks/default') || resource.peerings.exists(p, p.network.matches('https://www.googleapis.com/compute/v1/projects/PROJECT_ID/global/networks/shared$'))
cloudfunctions.googleapis.com/CloudFunction Permitir apenas tráfego de entrada interno para a função do Cloud Run has(resource.ingressSettings) && resource.ingressSettings.matches('ALLOW_INTERNAL_ONLY')
compute.googleapis.com/Instance O nome do recurso corresponde ao padrão resource.name.matches('^gcp-vm-(linux|windows)-v\\d+$')
serviceusage.googleapis.com/Service Permitir que apenas APIs relacionadas ao armazenamento sejam ativadas resource.state == 'ENABLED' && !( resource.name.matches('storage-api.googleapis.com') || resource.name.matches('bigquery-json.googleapis.com') || resource.name.matches('bigquery.googleapis.com') || resource.name.matches('sql-component.googleapis.com') || resource.name.matches('spanner.googleapis.com'))
sqladmin.googleapis.com/Instance Apenas IPs públicos com autorização são permitidos (resource.instanceType == 'CLOUD_SQL_INSTANCE' && resource.backendType == 'SECOND_GEN' && resource.settings.ipConfiguration.ipv4Enabled ) && !(resource.ipAddresses.all(ip, ip.type != 'PRIMARY' || ip.ipAddress.matches('IP_ADDRESS'))))
dataproc.googleapis.com/Cluster Verifique se os IDs de projeto em um cluster do Dataproc contêm o teste ou desenvolvimento de substrings has(resource.projectId) && resource.projectId.contains('testing') || resource.projectId.contains('development')

Expressões CEL para propriedades de descoberta personalizadas

Opcionalmente, para retornar mais informações com cada descoberta que pode ser usada na busca de consultas, você pode definir até dez propriedades personalizadas para retornar com as descobertas que são geradas por seus módulos personalizados.

As propriedades personalizadas aparecem nas propriedades de origem da descoberta no JSON e na guia Propriedades de origem dos detalhes da descoberta no console do Google Cloud.

Você define propriedades personalizadas como pares name-value.

Se estiver criando um módulo personalizado no console do Google Cloud, você vai definir os pares de name-value na seção Propriedades de descoberta personalizadas na página Definir detalhes da descoberta.

Se você estiver codificando um módulo personalizado em um arquivo YAML, liste os pares de name-value como properties na propriedade custom_output.

Independentemente de você estar usando o console do Google Cloud ou um arquivo YAML, as seguintes regras se aplicam:

  • Especifique name como uma string de texto sem aspas.
  • Especifique value como uma destas:

    • Para retornar o valor de uma propriedade, especifique-a no seguinte formato:

      RESOURCE_TYPE.PROPERTY.PROPERTY_TO_RETURN

    No exemplo:

    • RESOURCE_TYPE pode ser resource ou policy.
    • PROPERTY uma ou mais propriedades pai da propriedade que contém o valor a ser retornado.
    • PROPERTY_TO_RETURN é a propriedade que contém o valor a ser retornado.

    • Para retornar uma string de texto, coloque a string entre aspas.

O exemplo a seguir mostra dois pares name-value definidos corretamente em custom_output em um arquivo YAML:

custom_output:
  properties:
    - name: duration
      value_expression:
        expression: resource.name
    - name: property_with_text
      value_expression:
        expression: "Note content"

A seguir

Para testar, enviar, ver e atualizar módulos personalizados, consulte as seguintes páginas: