Como listar descobertas de segurança usando a API Security Command Center

As descobertas do Security Command Center modelam os possíveis riscos à segurança de recursos em um projeto ou uma organização. Uma descoberta sempre está relacionada a um recurso específico no Security Command Center.

Este guia mostra como usar as bibliotecas de cliente do Security Command Center para acessar as descobertas. Cada descoberta pertence a uma fonte. A maioria dos provedores e detectores produz descobertas na mesma fonte.

Os papéis do IAM para o Security Command Center podem ser concedidos no nível da organização, da pasta ou do projeto. A capacidade de ver, editar, criar ou atualizar descobertas, recursos e fontes de segurança depende do nível a que você tem acesso. Para saber mais sobre os papéis do Security Command Center, consulte Controle de acesso.

Antes de começar

Antes de configurar uma fonte, faça o seguinte:

Tamanho da página

Todas as APIs de lista do Security Command Center são paginadas. Cada resposta retorna uma página de resultados e um token para retornar a próxima página. O tamanho da página é configurável. O tamanho de página padrão é 10. É possível defini-la para um mínimo de 1 e um máximo de 1.000.

Retenção de descobertas

Uma descoberta permanece disponível para que você liste ou consulte por pelo menos 13 meses.

O Security Command Center armazena snapshots de cada descoberta. Um snapshot de uma descoberta é mantido por pelo menos 13 meses. Se todos os snapshots de uma descoberta forem excluídos, ela não poderá mais ser consultada ou recuperada.

Para saber mais sobre a retenção de dados do Security Command Center, consulte Retenção de dados.

Listar todas as descobertas

gcloud

Para listar todas as descobertas em um projeto, pasta ou organização, execute o seguinte comando:

gcloud scc findings list PARENT_ID

Substitua PARENT_ID por um dos seguintes valores:

  • Um ID de organização no seguinte formato: ORGANIZATION_ID (apenas o ID numérico)
  • Um ID de pasta no seguinte formato: folders/FOLDER_ID
  • Um ID de projeto no seguinte formato: projects/PROJECT_ID

Para mais exemplos, execute:

gcloud scc findings list --help

Para exemplos na documentação, consulte gcloud scc findings list.

Python

from google.cloud import securitycenter

# Create a client.
client = securitycenter.SecurityCenterClient()

# 'parent' must be in one of the following formats:
#   "organizations/{organization_id}"
#   "projects/{project_id}"
#   "folders/{folder_id}"
parent = f"organizations/{organization_id}"
# The "sources/-" suffix lists findings across all sources.  You
# also use a specific source_name instead.
all_sources = f"{parent}/sources/-"
finding_result_iterator = client.list_findings(request={"parent": all_sources})
for i, finding_result in enumerate(finding_result_iterator):
    print(
        "{}: name: {} resource: {}".format(
            i, finding_result.finding.name, finding_result.finding.resource_name
        )
    )

Java

static ImmutableList<ListFindingsResult> listAllFindings(OrganizationName organizationName) {
  try (SecurityCenterClient client = SecurityCenterClient.create()) {
    // Input parameters for SourceName must be in one of the following formats:
    //    * OrganizationName organizationName = OrganizationName.of("organization-id");
    //      organizationName.getOrganization();
    //    * ProjectName projectName = ProjectName.of("project-id");
    //      projectName.getProject();
    //    * FolderName folderName = FolderName.of("folder-id");
    //      folderName.getFolder();
    //
    // "-" Indicates listing across all sources.
    SourceName sourceName = SourceName.of(organizationName.getOrganization(), "-");

    ListFindingsRequest.Builder request =
        ListFindingsRequest.newBuilder().setParent(sourceName.toString());

    // Call the API.
    ListFindingsPagedResponse response = client.listFindings(request.build());

    // This creates one list for all findings.  If your organization has a large number of
    // findings this can cause out of memory issues.  You can process them in incrementally
    // by returning the Iterable returned response.iterateAll() directly.
    ImmutableList<ListFindingsResult> results = ImmutableList.copyOf(response.iterateAll());
    System.out.println("Findings:");
    System.out.println(results);
    return results;
  } catch (IOException e) {
    throw new RuntimeException("Couldn't create client.", e);
  }
}

Go

import (
	"context"
	"fmt"
	"io"

	securitycenter "cloud.google.com/go/securitycenter/apiv1"
	"cloud.google.com/go/securitycenter/apiv1/securitycenterpb"
	"google.golang.org/api/iterator"
)

// listFindings prints all findings in orgID to w. orgID is the numeric
// identifier of the organization.
func listFindings(w io.Writer, orgID string) error {
	// orgID := "12321311"
	// Instantiate a context and a security service client to make API calls.
	ctx := context.Background()
	client, err := securitycenter.NewClient(ctx)
	if err != nil {
		return fmt.Errorf("securitycenter.NewClient: %w", err)
	}
	defer client.Close() // Closing the client safely cleans up background resources.

	req := &securitycenterpb.ListFindingsRequest{
		// List findings across all sources.
		// Parent must be in one of the following formats:
		//		"organizations/{orgId}/sources/-"
		//		"projects/{projectId}/sources/-"
		//		"folders/{folderId}/sources/-"
		Parent: fmt.Sprintf("organizations/%s/sources/-", orgID),
	}
	it := client.ListFindings(ctx, req)
	for {
		result, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return fmt.Errorf("it.Next: %w", err)
		}
		finding := result.Finding
		fmt.Fprintf(w, "Finding Name: %s, ", finding.Name)
		fmt.Fprintf(w, "Resource Name %s, ", finding.ResourceName)
		fmt.Fprintf(w, "Category: %s\n", finding.Category)
	}
	return nil
}

Node.js

// Imports the Google Cloud client library.
const {SecurityCenterClient} = require('@google-cloud/security-center');

// Creates a new client.
const client = new SecurityCenterClient();
//  organizationId is the numeric ID of the organization.
/*
 * TODO(developer): Uncomment the following lines
 */
// const organizationId = "1234567777";

async function listAllFindings() {
  const [response] = await client.listFindings({
    // List findings across all sources.
    // parent: must be in one of the following formats:
    //    `organizations/${organization_id}/sources/-`
    //    `projects/${project_id}/sources/-`
    //    `folders/${folder_id}/sources/-`
    parent: `organizations/${organizationId}/sources/-`,
  });
  let count = 0;
  Array.from(response).forEach(result =>
    console.log(
      `${++count} ${result.finding.name} ${result.finding.resourceName}`
    )
  );
}
listAllFindings();

A saída para cada descoberta é semelhante à seguinte:

"finding": {
    "name": "organizations/ORGANIZATION_ID/sources/SOURCE_ID/findings/FINDING_ID",
    "parent": "organizations/ORGANIZATION_ID/sources/SOURCE_ID",
    "resourceName": "//cloudresourcemanager.googleapis.com/projects/PROJECT_NUMBER",
    "state": "ACTIVE",
    "category": "Malware: Cryptomining Bad Domain",
    "sourceProperties": {
      "sourceId": {
        "projectNumber": "PROJECT_NUMBER",
        "customerOrganizationNumber": "ORGANIZATION_ID"
      },
      "detectionCategory": {
        "technique": "cryptomining",
        "indicator": "domain",
        "ruleName": "bad_domain",
        "subRuleName": "cryptomining"
      },
      "detectionPriority": "LOW",
      "affectedResources": [{
        "gcpResourceName": "//cloudresourcemanager.googleapis.com/projects/PROJECT_NUMBER"
      }],
      "evidence": [{
        "sourceLogId": {
          "projectId": "PROJECT_ID",
          "resourceContainer": "projects/PROJECT_ID",
          "timestamp": {
            "seconds": "1636566099",
            "nanos": 5.41483849E8
          },
          "insertId": "INSERT_ID"
        }
      }],
      "properties": {
        "domains": ["DOMAIN"],
        "instanceDetails": "/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_ID",
        "network": {
          "project": "PROJECT_ID",
          "location": "ZONE"
        },
        "dnsContexts": [{
          "authAnswer": true,
          "sourceIp": "SOURCE_IP_ADDRESS",
          "queryName": "DOMAIN",
          "queryType": "A",
          "responseCode": "NXDOMAIN"
        }],
        "vpc": {
          "vpcName": "default"
        }
      },
      "findingId": "FINDING_ID",
      "contextUris": {
        "mitreUri": {
          "displayName": "MITRE Link",
          "url": "https://attack.mitre.org/techniques/T1496/"
        },
        "virustotalIndicatorQueryUri": [{
          "displayName": "VirusTotal Domain Link",
          "url": "https://www.virustotal.com/gui/domain/DOMAIN/detection"
        }],
        "cloudLoggingQueryUri": [{
          "displayName": "Cloud Logging Query Link",
          "url": "https://console.cloud.google.com/logs/query;query\u003dtimestamp%3D%222021-11-10T17:41:39.541483849Z%22%0AinsertId%3D%22INSERT_ID%22%0Aresource.labels.project_id%3D%22PROJECT_ID%22?project\u003dPROJECT_ID"
        }],
        "relatedFindingUri": {
        }
      }
    },
    "securityMarks": {
      "name": "organizations/ORGANIZATION_ID/sources/SOURCE_ID/findings/FINDING_ID/securityMarks"
    },
    "eventTime": "2021-11-10T17:41:41.594Z",
    "createTime": "2021-11-10T17:41:42.014Z",
    "severity": "LOW",
    "workflowState": "NEW",
    "canonicalName": "projects/PROJECT_NUMBER/sources/SOURCE_ID/findings/FINDING_ID",
    "mute": "UNDEFINED",
    "findingClass": "THREAT",
    "indicator": {
      "domains": ["DOMAIN"]
    }
  },
  "resource": {
    "name": "//cloudresourcemanager.googleapis.com/projects/PROJECT_NUMBER",
    "projectName": "//cloudresourcemanager.googleapis.com/projects/PROJECT_NUMBER",
    "projectDisplayName": "PROJECT_ID",
    "parentName": "//cloudresourcemanager.googleapis.com/organizations/ORGANIZATION_ID",
    "parentDisplayName": "PARENT_NAME",
    "type": "google.cloud.resourcemanager.Project",
    "displayName": "PROJECT_ID"
  }

Filtrar descobertas

Um projeto, uma pasta ou uma organização pode ter várias descobertas. O exemplo anterior não usa um filtro, portanto, todos os registros de descoberta são retornados. O Security Command Center permite usar filtros de descoberta para receber informações apenas sobre as descobertas que você quer.

Os filtros de localização são como cláusulas "onde" nas instruções SQL, exceto que em vez de colunas, eles se aplicam aos objetos retornados pela API.

O exemplo a seguir lista apenas as descobertas que têm uma categoria "MEDIUM_RISK_ONE". Provedores de descoberta diferentes (também conhecidos como fontes de segurança) usam diferentes conjuntos de categorias. Para determinar as categorias que podem ser usadas no filtro, consulte a documentação do provedor de descoberta.

gcloud

Use o seguinte comando para filtrar as descobertas:

gcloud scc findings list PARENT_ID --source=SOURCE_ID --filter="FILTER"

Substitua:

  • FILTER pelo filtro que você precisa usar. Por exemplo, o filtro a seguir retorna as descobertas somente da categoria MEDIUM_RISK_ONE:
    --filter="category=\"MEDIUM_RISK_ONE\""
  • PARENT_ID com um destes valores:
    • Um ID de organização no seguinte formato: ORGANIZATION_ID (apenas o ID numérico)
    • Um ID de projeto no seguinte formato: projects/PROJECT_ID
    • Um ID de pasta no seguinte formato: folders/FOLDER_ID
  • SOURCE_ID pelo ID da origem de segurança que fornece o tipo de descoberta.

Para mais exemplos, execute:

gcloud scc findings list --help

Para exemplos na documentação, consulte gcloud scc findings list.

Python

from google.cloud import securitycenter

# Create a new client.
client = securitycenter.SecurityCenterClient()

# 'source_name' is the resource path for a source that has been
# created previously (you can use list_sources to find a specific one).
# Its format is:
# source_name = f"{parent}/sources/{source_id}"
# 'parent' must be in one of the following formats:
#   "organizations/{organization_id}"
#   "projects/{project_id}"
#   "folders/{folder_id}"
# You an also use a wild-card "-" for all sources:
#   source_name = "organizations/111122222444/sources/-"
finding_result_iterator = client.list_findings(
    request={"parent": source_name, "filter": 'category="MEDIUM_RISK_ONE"'}
)
# Iterate an print all finding names and the resource they are
# in reference to.
for i, finding_result in enumerate(finding_result_iterator):
    print(
        "{}: name: {} resource: {}".format(
            i, finding_result.finding.name, finding_result.finding.resource_name
        )
    )

Java

static ImmutableList<ListFindingsResult> listFilteredFindings(SourceName sourceName) {
  try (SecurityCenterClient client = SecurityCenterClient.create()) {
    // parentId: must be one of the following:
    //    "organization-id"
    //    "project-id"
    //    "folder-id"
    // SourceName sourceName = SourceName.of(parentId, sourceId);

    // Create filter to category of MEDIUM_RISK_ONE
    String filter = "category=\"MEDIUM_RISK_ONE\"";

    ListFindingsRequest.Builder request =
        ListFindingsRequest.newBuilder().setParent(sourceName.toString()).setFilter(filter);

    // Call the API.
    ListFindingsPagedResponse response = client.listFindings(request.build());

    // This creates one list for all findings.  If your organization has a large number of
    // findings this can cause out of memory issues.  You can process them in incrementally
    // by returning the Iterable returned response.iterateAll() directly.
    ImmutableList<ListFindingsResult> results = ImmutableList.copyOf(response.iterateAll());
    System.out.println("Findings:");
    System.out.println(results);
    return results;
  } catch (IOException e) {
    throw new RuntimeException("Couldn't create client.", e);
  }
}

Go

import (
	"context"
	"fmt"
	"io"

	securitycenter "cloud.google.com/go/securitycenter/apiv1"
	"cloud.google.com/go/securitycenter/apiv1/securitycenterpb"
	"google.golang.org/api/iterator"
)

// listFilteredFindings prints findings with category 'MEDIUM_RISK_ONE' for a
// specific source to w. sourceName is the full resource name of the source
// to search for findings under.
func listFilteredFindings(w io.Writer, sourceName string) error {
	// Specific source:
	// 		sourceName := "{parent}/sources/{sourceId}"
	// All sources:
	// 		sourceName := "{parent}/sources/-"
	// where,
	// Parent must be in one of the following formats:
	//		"organizations/{orgId}"
	//		"projects/{projectId}"
	//		"folders/{folderId}"
	// Instantiate a context and a security service client to make API calls.
	ctx := context.Background()
	client, err := securitycenter.NewClient(ctx)
	if err != nil {
		return fmt.Errorf("securitycenter.NewClient: %w", err)
	}
	defer client.Close() // Closing the client safely cleans up background resources.

	req := &securitycenterpb.ListFindingsRequest{
		Parent: sourceName,
		Filter: `category="MEDIUM_RISK_ONE"`,
	}
	it := client.ListFindings(ctx, req)
	for {
		result, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return fmt.Errorf("it.Next: %w", err)
		}
		finding := result.Finding
		fmt.Fprintf(w, "Finding Name: %s, ", finding.Name)
		fmt.Fprintf(w, "Resource Name %s, ", finding.ResourceName)
		fmt.Fprintf(w, "Category: %s\n", finding.Category)
	}
	return nil
}

Node.js

// Imports the Google Cloud client library.
const {SecurityCenterClient} = require('@google-cloud/security-center');

// Creates a new client.
const client = new SecurityCenterClient();
//  sourceName is the full resource path of the source to search for
//  findings.
/*
 * TODO(developer): Uncomment the following lines
 */
// const sourceName = `${parent}/sources/${sourceId}`;
// where,
// parent: must be in one of the following formats:
//    `organizations/${organization_id}`
//    `projects/${project_id}`
//    `folders/${folder_id}`
async function listFilteredFindings() {
  const [response] = await client.listFindings({
    // List findings across all sources.
    parent: sourceName,
    filter: 'category="MEDIUM_RISK_ONE"',
  });
  let count = 0;
  Array.from(response).forEach(result =>
    console.log(
      `${++count} ${result.finding.name} ${result.finding.resourceName}`
    )
  );
}
listFilteredFindings();

O Security Command Center também é compatível com matrizes e objetos JSON completos como tipos de propriedade em potencial. É possível filtrar por:

  • Elementos de matriz
  • Objetos JSON completos com correspondência parcial de string no objeto
  • Subcampos de objetos JSON

Operadores compatíveis

As instruções de consulta para descobertas do Security Command Center são compatíveis com os operadores compatíveis com a maioria das APIs do Google Cloud.

A lista a seguir mostra o uso de vários operadores:

  • state="ACTIVE" AND NOT mute="MUTED"
  • create_time>"2023-08-15T19:05:32.428Z"
  • resource.parent_name:"prod"
  • severity="CRITICAL" OR severity="HIGH"

A lista a seguir mostra todos os operadores e funções compatíveis com as instruções de consulta para descobertas:

  • Para strings:
    • = para igualdade total
    • : para correspondência parcial de string
  • Para números:
    • <, >, <=, >= para desigualdades
    • =, != fpara igualdade
  • Para booleanos:
    • = para igualdade
  • Para relações lógicas:
    • AND
    • OR
    • NOT ou -
  • Para expressões de agrupamento:
    • (, ) (parênteses)
  • Para matrizes:
    • contains(), uma função para consultar descobertas com um campo de matriz que contém pelo menos um elemento que corresponde ao filtro especificado.
    • containsOnly(), uma função para consultar as descobertas com um campo de matriz que contém apenas elementos que correspondem ao filtro especificado.
  • Para endereços IP:
    • inIpRange(), uma função para consultar endereços IP dentro de um intervalo CIDR especificado.

Como filtrar endereços IP

Algumas propriedades de localização incluem endereços IP. É possível filtrar descobertas com base em endereços IP específicos ou em um intervalo de endereços IP.

Os endereços IP aparecem como strings em uma variedade de descobertas e propriedades, incluindo o seguinte:

  • access.caller_ip
  • connections.destinationIp
  • connections.sourceIp
  • indicator.ip_addresses

Para filtrar um endereço IP específico, use o operador de igualdade, como mostrado no exemplo a seguir:

access.caller_ip="192.0.2.0"

Para filtrar descobertas com base em um intervalo de endereços IP, use a função inIpRange. Usando a função inIpRange, você filtra as descobertas apenas para as descobertas que contêm um endereço IP dentro de um intervalo CIDR especificado. Usando a operação NOT com inIpRange, é possível filtrar as descobertas somente para as descobertas que contêm um endereço IP fora do intervalo CIDR especificado.

O exemplo a seguir mostra a sintaxe da função inIpRange:

inIpRange(IP_FINDING_FIELD, "CIDR_RANGE")

Se o endereço IP estiver em um elemento de matriz em um campo de descoberta que contenha uma matriz, use a seguinte sintaxe com a função contains e inIpRange:

contains(ATTRIBUTE_WITH_ARRAY, inIpRange(IP_FINDING_FIELD, "CIDR_RANGE"))

No exemplo a seguir, a função inIpRange avalia cada elemento destination_ip da matriz contido no campo de descoberta connections para um endereço IP que está no intervalo CIDR definido por 192.0.2.0/24:

contains(connections, inIpRange(destination_ip, "192.0.2.0/24"))

O exemplo a seguir mostra um comando da CLI da gcloud que usa a função inIpRange para filtrar descobertas que têm um endereço IP no campo connections.source_ip que está dentro de um intervalo, mas não em outro do Google Analytics. O campo connections é um campo do tipo matriz, portanto, a função contains é usada:

  gcloud scc findings list example-organization.com \
    --source=123456789012345678 \
    --filter="contains(connections, inIpRange(source_ip, "2001:db8::/32")) \
      AND NOT contains(connections, inIpRange(source_ip, "192.0.2.0/24"))

Exemplo de objeto JSON

Os exemplos posteriores nesta página presumem que o seguinte objeto JSON seja um atributo de descoberta:

{
  "outer_object": {
    "middle_object": {
      "deeply_nested_object": {
        "x": 123
      },
      "y": "some-string-value"
    },
    "list_middle_object": [
      {
        "v": 321,
        "w": [
          {
            "a": 3,
            "b": 4
          }
        ]
      }
    ],
    "z": "some-other-string-value",
    "u": [
      "list-element-1",
      "list-element-2",
      "list-element-3"
    ]
  }
}

Exemplo de filtragem de descobertas

Suponha que o exemplo JSON anterior seja um atributo de descoberta chamado my_property. O exemplo a seguir inclui consultas para descobertas que têm o objeto como uma propriedade. Você também pode usar esses filtros com outros filtros usando AND e OR na consulta.

# ORGANIZATION_ID=organization-id
# SOURCE_ID="source-id"

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --filter="my_property.outer_object.middle_object.deeply_nested_object.x = 123"

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --filter="my_property.outer_object.middle_object.y = \"some-string-value\""

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --filter="my_property.outer_object.middle_object.y : \"string-value\""

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --filter="my_property.outer_object.z = \"some-other-string-value\""

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --filter="my_property.outer_object.z : \"other-string-value\""

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --filter="my_property.outer_object.u : \"list-element-1\""

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --filter="my_property.outer_object.u : \"list-element-2\""

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --filter="my_property.outer_object.u : \"list-element-3\""

Como filtrar campos do tipo matriz

Ao chamar ListFindings, você pode usar uma correspondência de substring :, que fará uma única verificação de uma correspondência parcial de string em todo o conteúdo da matriz. Como alternativa, é possível executar um subfiltro diretamente nos elementos da matriz e nos subcampos usando uma das seguintes funções:

  • A função contains() para retornar descobertas quando qualquer elemento da matriz contém o valor especificado.

  • A função containsOnly() para retornar descobertas somente se todos os elementos da matriz corresponderem ao subfiltro.

As duas funções aceitam recursos de consulta de subfiltro, como este:

  • Correspondência exata de elementos: faz a correspondência de elementos da matriz que contenham a string exata, "example".
  • Operações de números específicos: elementos de matriz de correspondência maiores ou iguais a 100.
  • Filtragem complexa contra estruturas de matriz: corresponde a elementos da matriz que contêm a propriedade x com um valor correspondente y.

Formato da função contains()

A função contains() tem o seguinte formato:

contains(ARRAY_ATTRIBUTE_NAME, SUBFILTER)

Substitua:

  • ARRAY_ATTRIBUTE_NAME: um campo ou subcampo do tipo matriz (uma lista).
  • SUBFILTER: uma expressão que define os valores a serem procurados na matriz. O formato do subfiltro varia dependendo se ARRAY_ATTRIBUTE_NAME é uma matriz de objetos ou uma matriz de elementos primitivos. Se ARRAY_ATTRIBUTE_NAME for uma matriz de objetos que têm matrizes aninhadas, será possível usar um subfiltro com escopo para especificar que você quer que todas as condições sejam satisfeitas dentro da mesma ARRAY_ATTRIBUTE_NAME.

A API Security Command Center retorna descobertas em que ARRAY_ATTRIBUTE_NAME contenha pelo menos um elemento que satisfaça ao SUBFILTER.

Formato da função containsOnly()

A função containsOnly() tem o seguinte formato:

containsOnly(ARRAY_ATTRIBUTE_NAME, SUBFILTER)

Substitua:

  • ARRAY_ATTRIBUTE_NAME: um campo ou subcampo do tipo matriz (uma lista). Quando você executa consultas usando a API Security Command Center, é possível usar a função containsOnly() para qualquer atributo de matriz disponível.

  • SUBFILTER: uma expressão que define os valores a serem procurados na matriz. O formato do subfiltro varia dependendo se ARRAY_ATTRIBUTE_NAME é uma matriz de objetos ou uma matriz de elementos primitivos. Se ARRAY_ATTRIBUTE_NAME for uma matriz de objetos que têm matrizes aninhadas, será possível usar um subfiltro com escopo para especificar que você quer que todas as condições sejam satisfeitas dentro do mesmo elemento ARRAY_ATTRIBUTE_NAME.

A API Security Command Center retorna descobertas em que todos os elementos ARRAY_ATTRIBUTE_NAME correspondem a SUBFILTER.

Subfiltro para uma matriz de objetos

Veja a seguir um trecho do exemplo JSON anterior. Aqui, o campo list_middle_object é uma matriz de objetos:

    "list_middle_object": [
      {
        "v": 321,
        "w": [
          {
            "a": 3,
            "b": 4
          }
        ]
      }
    ]

No exemplo a seguir, consultas para descobertas em que pelo menos um dos elementos no campo list_middle_object tem um subcampo v com um valor maior ou igual a 321:

# ORGANIZATION_ID=organization-id
# SOURCE_ID="source-id"

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --filter="contains(my_property.outer_object.list_middle_object, v  >= 321)"

Para exemplos práticos que usam as funções contains() e containsOnly(), consulte Descobertas que contêm valores de matriz específicos.

Subfiltro para uma matriz que contém elementos primitivos

Os tipos primitivos são strings, números e booleanos. Para usar a função contains() com uma matriz que contém tipos primitivos, use a palavra-chave especial, elem.

Veja a seguir um trecho do exemplo JSON anterior. Aqui, o campo u é uma matriz de elementos primitivos:

"u": ["list-element-1", "list-element-2", "list-element-3"]

No exemplo a seguir, as descobertas são descobertas em que pelo menos um dos elementos no campo u é "list-element-1":

# ORGANIZATION_ID=organization-id
# SOURCE_ID="source-id"

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --filter="contains(my_property.outer_object.u, elem = \"list-element-1\")"

Para exemplos práticos que usam a função contains(), consulte Descobertas que contêm valores de matriz específicos.

Subfiltro com escopo

Veja a seguir um trecho do exemplo JSON anterior. Aqui, o campo list_middle_object é uma matriz de objetos, e os objetos nessa matriz contêm uma matriz aninhada.

    "list_middle_object": [
      {
        "v": 321,
        "w": [
          {
            "a": 3,
            "b": 4
          }
        ]
      }
    ]

No exemplo a seguir, consultas de descobertas em que ambas as condições a seguir são satisfeitas no mesmo elemento list_middle_object:

  • O subcampo v tem um valor maior ou igual a 321.
  • O subcampo w não contém um elemento com uma propriedade a igual a 3.
# ORGANIZATION_ID=organization-id
# SOURCE_ID="source-id"

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --filter="contains(my_property.outer_object.list_middle_object, v  >= 321 AND -contains(w, a = 3))"

Para exemplos práticos que usam a função contains(), consulte Descobertas que contêm valores de matriz específicos.

Exemplo de classificação de descobertas

É possível classificar as descobertas por subcampos rígidos que são tipos primitivos: strings, números e booleanos. Suponha que o exemplo JSON anterior seja um atributo de descoberta chamado my_property. O exemplo a seguir inclui consultas para classificar os campos de descoberta. A palavra-chave DESC especifica que o campo a ser seguido precisa ser classificado em ordem decrescente. A ordem padrão é crescente.

# ORGANIZATION_ID=organization-id
# SOURCE_ID="source-id"

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --order-by="my_property.outer_object.middle_object.deeply_nested_object.x DESC"

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --order-by="my_property.outer_object.middle_object.deeply_nested_object.x"

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --order-by="my_property.outer_object.middle_object.y DESC"

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --order-by="my_property.outer_object.middle_object.y"

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --order-by="my_property.outer_object.z DESC"

gcloud scc findings list $ORGANIZATION_ID --source=$SOURCE_ID \
  --order-by="my_property.outer_object.z"

Exemplos de filtros

As seções a seguir mostram exemplos práticos de como encontrar filtros.

Filtrar descobertas que ocorreram após um momento

Esses filtros de exemplo correspondem às descobertas mais recentes após quarta-feira, 5 de junho de 2019, às 22:12:05 GMT. Com o filtro event_time, é possível expressar tempo usando os seguintes formatos e tipos:

  • Tempo Unix (em milissegundos) como um literal inteiro

    "event_time > 1559772725000"
    
  • RFC 3339 como um literal de string

    "event_time > \"2019-06-05T22:34:40+00:00\""
    

Filtrar campos de tipo de matriz

O exemplo a seguir mostra o uso de uma correspondência parcial de string em um campo de tipo de matriz em um filtro:

"indicator.domains : \"website.com\""

A API Security Command Center retorna qualquer descoberta com uma string parcial website.com na matriz. Por exemplo, ele corresponde a uma descoberta com indicator.domains = [\"onewebsite.com\"] porque "website.com" é uma substring em um elemento na matriz.

Nas seções a seguir, os filtros de exemplo mostram algumas opções para uso da filtragem avançada de tipo de matriz que usa a função contains().

Filtrar no campo vulnerability.cve.references

O exemplo a seguir retorna descobertas em que pelo menos um elemento na matriz vulnerability.cve.references tem uma propriedade source igual a SOURCE_OF_REFERENCE e uma propriedade uri que tem FILTERED_URI de dados.

"contains(vulnerability.cve.references, source = \"SOURCE_OF_REFERENCE\" AND uri : \"FILTERED_URI\")"

Substitua:

Filtrar no campo indicator.domains

O exemplo a seguir retorna descobertas em que pelo menos um domínio indicador tem mycompanyprefix e .ca.

"contains(indicator.domains, elem : \"mycompanyprefix\" AND elem : \".ca\")"

Filtrar no campo indicator.ip_addresses

O exemplo a seguir retorna descobertas em que pelo menos um elemento na matriz indicator.ip_addresses é igual a IP_ADDRESS.

"contains(indicator.ip_addresses, elem = \"IP_ADDRESS\")"

Substitua IP_ADDRESS por um endereço IP associado às descobertas que você está procurando.

Filtrar por usuários externos do sistema

O exemplo a seguir retorna descobertas em que pelo menos um elemento na matriz external_systems.EXTERNAL_SYSTEM_NAME.assignees é igual a ASSIGNEE.

"contains(external_systems.EXTERNAL_SYSTEM_NAME.assignees, elem = \"ASSIGNEE\")"

Substitua:

  • EXTERNAL_SYSTEM_NAME: o nome de um sistema SIEM/SOAR de terceiros, por exemplo, demisto;
  • ASSIGNEE: um responsável no sistema externo.

Filtrar no campo resource.folders.resource_folder

O exemplo a seguir retorna descobertas em que pelo menos um elemento na matriz resource.folders.resource_folder é diferente de FOLDER_NAME.

"contains(resource.folders.resource_folder, -(elem = \"FOLDER_NAME\"))"

Filtrar no campo resource.folders.resource_folder_display_name

O exemplo a seguir retorna descobertas em que pelo menos um elemento na matriz resource.folders.resource_folder_display_name é igual a DISPLAY_NAME.

"contains(resource.folders.resource_folder_display_name, elem = \"DISPLAY_NAME\")"

Substitua DISPLAY_NAME pelo nome definido pelo usuário para a pasta associada às descobertas que você está procurando.

O filtro inclui somente contas de serviço específicas

O exemplo a seguir retorna descobertas somente quando o valor de membro de cada entrada iam_bindings é igual a uma das contas de serviço fornecidas.

containsOnly(iam_bindings, (member = SERVICE_ACCOUNT1 OR member = SERVICE_ACCOUNT2 OR member = "SERVICE_ACCOUNT3 "))

Substitua SERVICE_ACCOUNT1, SERVICE_ACCOUNT2 e SERVICE_ACCOUNT3 pelos endereços de e-mail das contas de serviço.

Para saber como usar as funções contains() e containsOnly() em um filtro de descoberta, consulte Como filtrar campos do tipo matriz.

A seguir

Saiba mais em Como configurar notificações de localização.