Listar resultados de segurança através da API Security Command Center

Os resultados do Security Command Center modelam os potenciais riscos de segurança dos recursos num projeto ou numa organização. Uma descoberta está sempre relacionada com um recurso específico no Security Command Center.

Este guia mostra como usar as bibliotecas cliente do Security Command Center para aceder a conclusões. Cada descoberta pertence a uma fonte. A maioria dos detetores ou fornecedores de resultados produz resultados na mesma origem.

As funções do IAM para o Security Command Center podem ser concedidas ao nível da organização, da pasta ou do projeto. A sua capacidade de ver, editar, criar ou atualizar resultados, recursos e origens de segurança depende do nível para o qual lhe é concedido acesso. Para saber mais sobre as funções do Security Command Center, consulte o artigo Controlo de acesso.

Antes de começar

Antes de configurar uma origem, tem de concluir o seguinte:

Tamanho da página

Todas as APIs de listas do Security Command Center são paginadas. Cada resposta devolve uma página de resultados e um token para devolver a página seguinte. O tamanho da página é configurável. O tamanho da página predefinido é 10. Pode defini-lo como um mínimo de 1 e um máximo de 1000.

Retenção de resultados

Consoante o seu nível do Security Command Center, as conclusões permanecem disponíveis para listar ou consultar durante períodos específicos. Para mais informações sobre a retenção de dados do Security Command Center, consulte o artigo Retenção de dados.

Apresente todas as conclusões

gcloud

Para apresentar uma lista de todas as descobertas num projeto, numa pasta ou numa organização, execute o seguinte comando:

gcloud scc findings list PARENT_TYPE/PARENT_ID \
  --location=LOCATION

Substitua o seguinte:

  • PARENT_TYPE: o nível da hierarquia de recursos para o qual listar as conclusões; use organizations, folders ou projects.
  • PARENT_ID: o ID numérico da organização, da pasta ou do projeto, ou o ID alfanumérico do projeto.
  • LOCATION: o Security Command Center localização na qual listar as conclusões; se a residência de dados estiver ativada, use eu, sa ou us; caso contrário, use o valor global.

Para ver mais exemplos, execute o seguinte comando:

gcloud scc findings list --help

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

Ir

import (
	"context"
	"fmt"
	"io"

	securitycenter "cloud.google.com/go/securitycenter/apiv2"
	"cloud.google.com/go/securitycenter/apiv2/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/-/locations/global"
		//		"projects/{projectId}/sources/-/locations/global"
		//		"folders/{folderId}/sources/-/locations/global"
		Parent: fmt.Sprintf("organizations/%s/sources/-/locations/global", 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
}

Java


import com.google.cloud.securitycenter.v2.ListFindingsRequest;
import com.google.cloud.securitycenter.v2.ListFindingsResponse.ListFindingsResult;
import com.google.cloud.securitycenter.v2.SecurityCenterClient;
import java.io.IOException;

public class ListAllFindings {

  public static void main(String[] args) throws IOException {
    // organizationId: The source to list all findings for.
    // You can also use project/ folder as the parent resource.
    String organizationId = "google-cloud-organization-id";

    // Specify the location to list the findings.
    String location = "global";

    // The source id to scope the findings.
    String sourceId = "source-id";

    listAllFindings(organizationId, sourceId, location);
  }

  // List all findings under a given parent resource.
  public static void listAllFindings(String organizationId, String sourceId, String location)
      throws IOException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests.
    try (SecurityCenterClient client = SecurityCenterClient.create()) {
      ListFindingsRequest request =
          ListFindingsRequest.newBuilder()
              // To list findings across all sources, use "-".
              .setParent(
                  String.format("organizations/%s/sources/%s/locations/%s", organizationId,
                      sourceId,
                      location))
              .build();

      for (ListFindingsResult result : client.listFindings(request).iterateAll()) {
        System.out.printf("Finding: %s", result.getFinding().getName());
      }
      System.out.println("\nListing complete.");
    }
  }
}

Node.js

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

// Creates a new client.
const client = new SecurityCenterClient();

// TODO(developer): Update the following for your own environment.
const organizationId = '1081635000895';
const location = 'global';

// Required. Name of the source the findings belong to. If no location is
// specified, the default is global. The following list shows some examples:
// - `organizations/[organization_id]/sources/[source_id]/locations/[location_id]`
// - `folders/[folder_id]/sources/[source_id]`
// - `folders/[folder_id]/sources/[source_id]/locations/[location_id]`
// - `projects/[project_id]/sources/[source_id]`
// - `projects/[project_id]/sources/[source_id]/locations/[location_id]`
// To groupBy across all sources provide a source_id of `-`.
const parent = `organizations/${organizationId}/sources/-/locations/${location}`;

// Build the list findings request.
const listFindingsRequest = {
  parent,
};

async function listAllFindings() {
  // Call the API.
  const iterable = client.listFindingsAsync(listFindingsRequest);
  let count = 0;

  for await (const response of iterable) {
    // Just print a few for demonstration.
    if (count > 5) break;
    console.log(
      `${++count} ${response.finding.name} ${response.finding.resourceName}`
    );
  }
}

await listAllFindings();

Python

def list_all_findings(organization_id, source_name, location_id) -> int:
    """
    lists all findings for a source
    Args:
       organization_id: organization_id is the numeric ID of the organization. e.g.:organization_id = "111122222444"
       source_name: is the resource path for a source that has been created
       location_id: GCP location id; example: 'global'
    Returns:
        int: returns the count of all findings for a source
    """
    from google.cloud import securitycenter_v2

    # Create a client.
    client = securitycenter_v2.SecurityCenterClient()
    parent = f"organizations/{organization_id}"
    all_sources = f"{parent}/sources/{source_name}/locations/{location_id}"

    # Create the request dictionary
    request = {"parent": all_sources}

    # Print the request for debugging
    print("Request: ", request)

    finding_result_iterator = client.list_findings(request={"parent": all_sources})
    for count, finding_result in enumerate(finding_result_iterator):
        print(
            "{}: name: {} resource: {}".format(
                count, finding_result.finding.name, finding_result.finding.resource_name
            )
        )
    return finding_result_iterator

O resultado de cada descoberta é semelhante ao 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"
  }
}

Filtre as conclusões

Um projeto, uma pasta ou uma organização podem ter muitas descobertas. O exemplo anterior não usa um filtro, pelo que são devolvidos todos os registos de resultados.

Para ajudar a aceder a informações apenas sobre os campos pretendidos, pode usar os filtros de pesquisa. Estes filtros são semelhantes às cláusulas "where" nas declarações SQL, mas, em vez de colunas, aplicam-se aos objetos devolvidos pela API.

O exemplo seguinte apresenta apenas as conclusões que têm uma categoria "MEDIUM_RISK_ONE". Diferentes fornecedores de conclusões (também conhecidos como fontes de segurança) usam diferentes conjuntos de categorias. Para determinar as categorias que pode usar no filtro, consulte a documentação do fornecedor de resultados.

gcloud

Use o seguinte comando para filtrar as descobertas:

gcloud scc findings list PARENT_TYPE/PARENT_ID \
  --location=LOCATION \
  --source=SOURCE_ID \
  --filter="FILTER"

Substitua o seguinte:

  • PARENT_TYPE: o nível da hierarquia de recursos para o qual listar as conclusões; use organizations, folders ou projects.
  • PARENT_ID: o ID numérico da organização, da pasta ou do projeto, ou o ID alfanumérico do projeto.
  • LOCATION: a localização do Security Command Center na qual listar as descobertas com um filtro; se a residência de dados estiver ativada, use eu, sa ou us; caso contrário, use o valor global.
  • SOURCE_ID: o ID da origem de segurança que fornece o tipo de descoberta.
  • FILTER: o filtro que tem de usar. Por exemplo, o filtro seguinte devolve resultados da categoria MEDIUM_RISK_ONE apenas:
    --filter="category=\"MEDIUM_RISK_ONE\""

Para ver mais exemplos, execute o seguinte comando:

gcloud scc findings list --help

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

Ir

import (
	"context"
	"fmt"
	"io"

	securitycenter "cloud.google.com/go/securitycenter/apiv2"
	"cloud.google.com/go/securitycenter/apiv2/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
}

Java


import com.google.cloud.securitycenter.v2.ListFindingsRequest;
import com.google.cloud.securitycenter.v2.ListFindingsResponse.ListFindingsResult;
import com.google.cloud.securitycenter.v2.SecurityCenterClient;
import java.io.IOException;

public class ListFindingsWithFilter {

  public static void main(String[] args) throws IOException {
    // TODO: Replace the variables within {}
    // organizationId: Google Cloud Organization id.
    // You can also use project/ folder as the parent resource.
    String organizationId = "google-cloud-organization-id";

    // Specify the location to list the findings.
    String location = "global";

    // The source id to scope the findings.
    String sourceId = "source-id";

    listFilteredFindings(organizationId, sourceId, location);
  }

  // List filtered findings under a source.
  public static void listFilteredFindings(String organizationId, String sourceId, String location)
      throws IOException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests.
    try (SecurityCenterClient client = SecurityCenterClient.create()) {

      // Use any one of the following formats:
      //  * organizations/{organization_id}/sources/{source_id}/locations/{location}
      //  * folders/{folder_id}/sources/{source_id}/locations/{location}
      //  * projects/{project_id}/sources/{source_id}/locations/{location}
      String parent = String.format("organizations/%s/sources/%s/locations/%s", organizationId,
          sourceId,
          location);

      // Listing all findings of category "MEDIUM_RISK_ONE".
      String filter = "category=\"MEDIUM_RISK_ONE\"";

      ListFindingsRequest request =
          ListFindingsRequest.newBuilder()
              .setParent(parent)
              .setFilter(filter)
              .build();

      for (ListFindingsResult result : client.listFindings(request).iterateAll()) {
        System.out.printf("Finding: %s", result.getFinding().getName());
      }
      System.out.println("\nListing complete.");
    }
  }
}

Node.js

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

// Creates a new client.
const client = new SecurityCenterClient();

// TODO(developer): Update the following for your own environment.
const organizationId = '1081635000895';
const location = 'global';

// Required. Name of the source to groupBy. If no location is specified,
// finding is assumed to be in global.
//  The following list shows some examples:
// - `organizations/[organization_id]/sources/[source_id]`
// - `organizations/[organization_id]/sources/[source_id]/locations/[location_id]`
// - `folders/[folder_id]/sources/[source_id]`
// - `folders/[folder_id]/sources/[source_id]/locations/[location_id]`
// - `projects/[project_id]/sources/[source_id]`
// - `projects/[project_id]/sources/[source_id]/locations/[location_id]`
// To groupBy across all sources provide a source_id of `-`.
const parent = `organizations/${organizationId}/sources/-/locations/${location}`;

// Listing all findings of category "MEDIUM_RISK_ONE".
const filter = 'category="MEDIUM_RISK_ONE"';

// Build the list findings with filter request.
const listFilteredFindingsRequest = {
  parent,
  filter,
};

async function listFilteredFindings() {
  // Call the API.
  const iterable = client.listFindingsAsync(listFilteredFindingsRequest);
  let count = 0;
  console.log('Findings:');
  for await (const response of iterable) {
    // Just print a few for demonstration.
    if (count > 5) break;
    console.log(
      `${++count} ${response.finding.name} ${response.finding.resourceName}`
    );
  }
}
await listFilteredFindings();

Python

def list_filtered_findings(organization_id, source_name, location_id) -> int:
    """
    lists filtered findings for a source
    Args:
        organization_id: organization_id is the numeric ID of the organization. e.g.:organization_id = "111122222444"
        source_name: is the resource path for a source that has been created
        location_id: GCP location id; example: 'global'
    Returns:
         int: returns the filtered findings for a source
    """
    count = 0
    from google.cloud import securitycenter_v2

    # Create a new client.
    client = securitycenter_v2.SecurityCenterClient()
    parent = f"organizations/{organization_id}"
    all_sources = f"{parent}/sources/{source_name}/locations/{location_id}"
    finding_result_iterator = client.list_findings(
        request={"parent": all_sources, "filter": 'severity="LOW"'}
    )
    # Iterate an print all finding names and the resource they are
    # in reference to.
    for count, finding_result in enumerate(finding_result_iterator):
        print(
            "{}: name: {} resource: {}".format(
                count, finding_result.finding.name, finding_result.finding.resource_name
            )
        )
    return count

O Security Command Center também suporta objetos e matrizes JSON completos como potenciais tipos de propriedades. Pode filtrar por:

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

Operadores suportados

As declarações de consulta para as conclusões do Security Command Center suportam os operadores que a maioria das Google Cloud APIs suporta.

A lista seguinte mostra a utilização 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 seguinte mostra todos os operadores e funções que são suportados em declarações de consulta para resultados:

  • Para strings:
    • = para igualdade total
    • : para correspondência parcial de strings
  • Para números (exceto int64):
    • <, >, <= e >= para desigualdades
    • =, != pela igualdade
  • Para números (int 64):
    • =, != pela igualdade
  • Para valores booleanos:
    • = pela 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 resultados com um campo de matriz que contém, pelo menos, um elemento que corresponde ao filtro especificado
    • containsOnly(), uma função para consultar resultados 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 num intervalo CIDR especificado

Filtragem em endereços IP

Determinadas propriedades de resultados incluem endereços IP. Pode filtrar as conclusões com base em endereços IP específicos ou num intervalo de endereços IP.

Os endereços IP aparecem como strings numa variedade de resultados e propriedades dos resultados, incluindo o seguinte:

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

Para filtrar por um endereço IP específico, pode usar o operador de igualdade, conforme mostrado no exemplo seguinte:

access.caller_ip="192.0.2.0"

Para filtrar resultados com base num intervalo de endereços IP, use a função inIpRange. Com a função inIpRange, filtra as descobertas para apenas as descobertas que contêm um endereço IP num intervalo CIDR especificado. Ao usar a operação NOT com inIpRange, pode filtrar as descobertas para apenas as descobertas que contêm um endereço IP fora do intervalo CIDR especificado.

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

inIpRange(IP_FINDING_FIELD, "CIDR_RANGE")

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

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

No exemplo seguinte, a função inIpRange avalia cada elemento destination_ip da matriz contida no campo de localização connections para um endereço IP que esteja no intervalo CIDR definido por 192.0.2.0/24:

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

O exemplo seguinte mostra um comando da CLI gcloud que usa a função inIpRange para filtrar resultados que têm um endereço IP no campo connections.source_ip que está dentro de um intervalo, mas não noutro. O campo connections é um campo do tipo matriz, pelo que é usada a função contains:

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --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 apresentados mais adiante nesta página partem do princípio de que o seguinte objeto JSON é 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 resultados

Suponhamos que o exemplo JSON anterior é um atributo de descoberta denominado my_property. O exemplo seguinte inclui consultas para resultados que têm o objeto como uma propriedade. Também pode usar estes filtros com outros filtros usando AND e OR na sua consulta.

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --filter="my_property.outer_object.middle_object.deeply_nested_object.x = 123"

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --filter="my_property.outer_object.middle_object.y = \"some-string-value\""

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --filter="my_property.outer_object.middle_object.y : \"string-value\""

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --filter="my_property.outer_object.z = \"some-other-string-value\""

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --filter="my_property.outer_object.z : \"other-string-value\""

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --filter="my_property.outer_object.u : \"list-element-1\""

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --filter="my_property.outer_object.u : \"list-element-2\""

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --filter="my_property.outer_object.u : \"list-element-3\""

Subfiltros para campos do tipo matriz

Quando chama ListFindings, pode usar uma correspondência de substring :, que faz uma única verificação de uma correspondência de string parcial em todo o conteúdo da matriz. Em alternativa, pode executar um subfiltro diretamente em elementos da matriz e respetivos subcampos através de uma das seguintes funções:

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

  • A função containsOnly() para devolver resultados apenas se todos os elementos da matriz corresponderem ao subfiltro.

Ambas as funções suportam capacidades de consulta de subfiltros, como as seguintes:

  • Correspondência exata de elementos: corresponder a elementos da matriz que contêm a string exata, "example".
  • Operações de números específicos: corresponder a elementos da matriz que sejam superiores ou iguais a 100.
  • Filtragem complexa em estruturas de matrizes: fazer corresponder elementos de matriz que contenham 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 o seguinte:

  • ARRAY_ATTRIBUTE_NAME: um campo ou um subcampo do tipo matriz (uma lista).
  • SUBFILTER: uma expressão que define os valores a procurar na matriz. O formato do subfiltro difere consoante ARRAY_ATTRIBUTE_NAME seja uma matriz de objetos ou uma matriz de elementos de tipo primitivo. Se o elemento ARRAY_ATTRIBUTE_NAME for uma matriz de objetos com matrizes aninhadas, pode usar um subfiltro com âmbito para especificar que quer que todas as condições sejam satisfeitas no mesmo elemento ARRAY_ATTRIBUTE_NAME.

A API Security Command Center devolve resultados em que o elemento ARRAY_ATTRIBUTE_NAME contém, pelo menos, um elemento que satisfaz a condição SUBFILTER.

Formato da função containsOnly()

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

containsOnly(ARRAY_ATTRIBUTE_NAME, SUBFILTER)

Substitua o seguinte:

  • ARRAY_ATTRIBUTE_NAME: um campo ou um subcampo do tipo matriz (uma lista). Quando executa consultas através da API Security Command Center, pode usar a função containsOnly() para qualquer atributo de matriz disponível.
  • SUBFILTER: uma expressão que define os valores a procurar na matriz. O formato do subfiltro difere consoante ARRAY_ATTRIBUTE_NAME seja uma matriz de objetos ou uma matriz de elementos de tipo primitivo. Se o ARRAY_ATTRIBUTE_NAME for uma matriz de objetos com matrizes aninhadas, pode usar um subfiltro com âmbito para especificar que quer que todas as condições sejam satisfeitas no mesmo elemento ARRAY_ATTRIBUTE_NAME.

A API Security Command Center devolve resultados em que todos os elementos ARRAY_ATTRIBUTE_NAME correspondem ao SUBFILTER.

Subfiltre uma matriz de objetos

Segue-se um excerto do exemplo de JSON anterior. Aqui, o campo list_middle_object é uma matriz de objetos:

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

O exemplo seguinte consulta registos onde, pelo menos, um dos elementos no campo list_middle_object tem um subcampo v com um valor superior ou igual a 321:

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --filter="contains(my_property.outer_object.list_middle_object, v  >= 321)"

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

Subfiltro para uma matriz que contém elementos do tipo primitivo

Os tipos primitivos são strings, números e booleanos. Para usar a função contains() num conjunto que contenha tipos primitivos, usa a palavra-chave especial elem.

Segue-se um excerto do exemplo de JSON anterior. Aqui, o campo u é uma matriz de elementos do tipo primitivo:

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

O exemplo seguinte consulta as descobertas em que, pelo menos, um dos elementos no campo u é "list-element-1":

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --filter="contains(my_property.outer_object.u, elem = \"list-element-1\")"

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

Subfiltro baseado em âmbito

Segue-se um excerto do exemplo de JSON anterior. Aqui, o campo list_middle_object é uma matriz de objetos e os objetos nesta matriz contêm uma matriz aninhada.

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

O exemplo seguinte consulta conclusões em que ambas as condições seguintes são satisfeitas no mesmo elemento list_middle_object:

  • O subcampo v tem um valor igual ou superior a 321.
  • O subcampo w não contém um elemento com uma propriedade a igual a 3.
gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --filter="contains(my_property.outer_object.list_middle_object, v  >= 321 AND -contains(w, a = 3))"

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

Exemplo de ordenação de conclusões

Pode ordenar as descobertas por subcampos rigorosos que são tipos primitivos: strings, números e booleanos. Suponhamos que o exemplo JSON anterior é um atributo de descoberta denominado my_property. O exemplo seguinte inclui consultas para ordenar os campos de registo de deteção. A palavra-chave DESC especifica que o campo que se segue tem de ser ordenado por ordem descendente. A ordem predefinida é ascendente.

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --order-by="my_property.outer_object.middle_object.deeply_nested_object.x DESC"

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --order-by="my_property.outer_object.middle_object.deeply_nested_object.x"

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --order-by="my_property.outer_object.middle_object.y DESC"

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --order-by="my_property.outer_object.middle_object.y"

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --order-by="my_property.outer_object.z DESC"

gcloud scc findings list PARENT_TYPE/PARENT_ID \
    --location=LOCATION \
    --source=SOURCE_ID \
    --order-by="my_property.outer_object.z"

Exemplos de filtros

As secções seguintes mostram exemplos práticos de como encontrar filtros.

Filtre as descobertas que ocorreram após um determinado momento

Estes filtros de exemplo correspondem a descobertas que ocorreram mais recentemente após quarta-feira, 5 de junho de 2019 às 22:12:05 GMT. Com o filtro event_time, pode expressar o tempo através dos seguintes formatos e tipos:

  • Tempo de época 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\""
    

Filtre campos do tipo matriz

O exemplo seguinte mostra a utilização de uma correspondência parcial de strings num campo do tipo matriz num filtro:

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

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

Nas secções seguintes, os filtros de exemplo mostram algumas opções de utilização da filtragem de tipo de matriz avançada através da função contains().

Filtre pelo campo vulnerability.cve.references

O exemplo seguinte devolve resultados 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.

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

Substitua o seguinte:

Filtre pelo campo indicator.domains

O exemplo seguinte devolve resultados em que, pelo menos, um domínio indicador tem mycompanyprefix e .ca.

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

Filtre pelo campo indicator.ip_addresses

O exemplo seguinte devolve resultados 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 está a pesquisar.

Filtre por responsáveis do sistema externo

O exemplo seguinte devolve resultados 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 o seguinte:

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

Filtre pelo campo resource.folders.resource_folder

O exemplo seguinte devolve resultados em que, pelo menos, um elemento na matriz resource.folders.resource_folder não é igual a FOLDER_NAME.

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

Filtre pelo campo resource.folders.resource_folder_display_name

O exemplo seguinte devolve resultados 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 utilizador da pasta associada às descobertas que está a procurar.

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

O exemplo seguinte devolve resultados apenas quando o valor do 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 email das contas de serviço.

Para saber como usar as funções contains() e containsOnly() num filtro de localização, consulte o artigo Subfiltros para campos do tipo matriz.

O que se segue?

Saiba mais sobre como configurar notificações de localização.