Genera una lista de resultados de seguridad con la API de Security Command Center

Los hallazgos de Security Command Center modelan los riesgos de seguridad potenciales de los activos en un proyecto u organización. Un resultado siempre se relaciona con un recurso específico en Security Command Center.

En esta guía, se muestra cómo usar las bibliotecas cliente de Security Command Center para acceder a los hallazgos. Cada resultado pertenece a una fuente. La mayoría de los detectores o los proveedores de resultados producirán resultados dentro de la misma fuente.

Los roles de IAM para Security Command Center se pueden otorgar a nivel de la organización, a nivel de carpeta o proyecto. Tu capacidad para ver, editar, crear o actualizar resultados, recursos, y las fuentes de seguridad dependen del nivel al que se te otorgue acceso. Para aprender para obtener más información sobre los roles de Security Command Center, consulta Control de acceso.

Antes de comenzar

Antes de configurar una fuente, debes completar lo siguiente:

Tamaño de la página

Se paginan todas las API de listas del Security Command Center. Cada respuesta muestra una página de resultados y un token para mostrar la página siguiente. El tamaño de la página se puede configurar. El tamaño de página predeterminado es 10. Puedes establecerlo en un mínimo de 1 y un máximo de 1,000.

Retención de resultados

Un hallazgo permanece disponible para que lo enumeres o busques durante al menos 13 meses.

Security Command Center almacena instantáneas de cada resultado. R instantánea de un hallazgo se conserva durante al menos 13 meses. Si todas las instantáneas de un hallazgo, este ya no se podrá enumerar ni recuperar.

Para obtener más información sobre la retención de datos de Security Command Center, consulta Retención de datos.

Enumerar todos los hallazgos

gcloud

Para enumerar todos los resultados de un proyecto, una carpeta o una organización, ejecuta el siguiente comando: :

gcloud scc findings list PARENT_ID

Reemplaza PARENT_ID por uno de los siguientes valores:

  • Un ID de la organización en el siguiente formato: ORGANIZATION_ID (solo el ID numérico)
  • Un ID de carpeta en el siguiente formato: folders/FOLDER_ID
  • Un ID del proyecto en el siguiente formato: projects/PROJECT_ID

Para ver más ejemplos, ejecuta el siguiente comando:

gcloud scc findings list --help

Para ver ejemplos en la documentación, consulta la lista de hallazgos de scc de gcloud.

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();

El resultado de cada hallazgo es similar al siguiente:

"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 resultados

Un proyecto, una carpeta o una organización pueden tener muchos hallazgos. El ejemplo anterior no usa un filtro, por lo que se muestran todos los registros de resultados. Security Command Center te permite usar filtros de búsqueda para obtener información solo sobre los los resultados que deseas.

Los filtros de resultado son como las cláusulas “where” en las instrucciones de SQL, excepto en lugar de columnas, se aplican a los objetos que muestra la API.

En el siguiente ejemplo, solo se enumeran los resultados que tienen una categoría “MEDIUM_RISK_ONE”. Los distintos proveedores de resultados (también conocidos como fuentes de seguridad) usan diferentes conjuntos de categorías. Para determinar las categorías que puedes usar en tu filtro, consulta la documentación del proveedor de búsqueda.

gcloud

Usa el siguiente comando para filtrar los resultados:

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

Reemplaza lo siguiente:

  • FILTER por el filtro que necesitas usar Por ejemplo: el siguiente filtro devuelve resultados en la categoría de Solo MEDIUM_RISK_ONE:
    --filter="category=\"MEDIUM_RISK_ONE\""
  • PARENT_ID con uno de los siguientes valores:
    • Un ID de la organización en el siguiente formato: ORGANIZATION_ID (solo el ID numérico)
    • Un ID del proyecto en el siguiente formato: projects/PROJECT_ID
    • Un ID de carpeta en el siguiente formato: folders/FOLDER_ID
  • SOURCE_ID por el ID de la fuente de seguridad que proporciona el tipo de hallazgo.

Para ver más ejemplos, ejecuta el siguiente comando:

gcloud scc findings list --help

Para ver ejemplos en la documentación, consulta la lista de hallazgos de scc de gcloud.

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();

Security Command Center también admite arreglos y objetos JSON completos como posibles tipos de propiedades. Puedes aplicar los siguientes filtros:

  • Elementos del array
  • Objetos JSON completos con coincidencia parcial de strings dentro del objeto
  • Subcampos de objetos JSON

Operadores admitidos

Las instrucciones de consulta para los resultados de Security Command Center admiten la operadores que admite la mayoría de las APIs de Google Cloud.

En la siguiente lista, se muestra el uso de varios operadores:

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

La siguiente lista muestra todos los operadores y funciones que son se admiten en las instrucciones de la consulta para los resultados:

  • Para cadenas:
    • = para igualdad total
    • : para la coincidencia parcial de cadenas
  • Para números:
    • <, >, <=, >= para las desigualdades
    • =, != para igualdad
  • Para valores booleanos:
    • = para igualdad
  • Para relaciones lógicas:
    • AND
    • OR
    • NOT o -
  • Para agrupar expresiones:
    • (, ) (paréntesis)
  • Para los arrays:
    • contains(), una función para buscar resultados con un campo de array que contenga al menos un elemento que coincida con el filtro especificado
    • containsOnly(), un para consultar los resultados con un campo de array que solo contenga elementos que coinciden con el filtro especificado
  • Para direcciones IP:
    • inIpRange(), una función para consultar direcciones IP dentro de un rango de CIDR especificado

Filtra direcciones IP

Algunas propiedades de los hallazgos incluyen direcciones IP. Puedes filtrar los resultados según direcciones IP específicas o un rango de direcciones IP.

Las direcciones IP aparecen como cadenas en una variedad de hallazgos y propiedades de resultados. incluidos los siguientes:

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

Para filtrar según una dirección IP específica, puedes usar el operador de igualdad, como se muestra en el siguiente ejemplo:

access.caller_ip="192.0.2.0"

Para filtrar los resultados según un rango de direcciones IP, usa inIpRange. . Con la función inIpRange, filtras los resultados para mostrar solo aquellos resultados que contienen una dirección IP dentro de un rango CIDR especificado. Mediante la operación NOT con inIpRange, puedes filtrar los resultados para mostrar solo aquellos hallazgos que contengan una dirección IP fuera del rango CIDR especificado.

En el siguiente ejemplo, se muestra la sintaxis de la función inIpRange:

inIpRange(IP_FINDING_FIELD, "CIDR_RANGE")

Si la dirección IP está en un elemento de array en un campo de búsqueda que contiene un array, usa la siguiente sintaxis con la función contains y La función inIpRange:

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

En el siguiente ejemplo, la función inIpRange evalúa cada Elemento destination_ip del array que se incluye en connections de resultados para una dirección IP que se encuentre en el rango CIDR definido por 192.0.2.0/24:

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

En el siguiente ejemplo, se muestra un comando de gcloud CLI que usa la función inIpRange para filtrar los resultados que tengan una IP en el campo connections.source_ip que se encuentre dentro de un rango pero no en otra. El campo connections es un array-type. por lo que se usa la función contains:

  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"))

Ejemplo de objeto JSON

En los ejemplos que aparecen más adelante en esta página, se supone que el siguiente objeto JSON es un atributo de resultado:

{
  "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"
    ]
  }
}

Ejemplo de filtrado de resultados

Supongamos que el ejemplo de JSON anterior es un atributo de resultado llamado my_property. En el siguiente ejemplo, se incluyen consultas para los resultados que tienen el objeto como propiedad. También puedes usar estos filtros con otros filtros que usen AND y OR en tu 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\""

Filtra en campos de tipo de array

Al realizar llamadas ListFindings, puedes usar una coincidencia de subcadena :, que hace una única comprobación de un de cadena en todo el contenido de la matriz. Como alternativa, puedes ejecutar un subfiltro directamente en función de los elementos del array y sus subcampos mediante el uso de una una de las siguientes funciones:

  • La función contains() para devolver resultados cuando cualquier elemento del contiene el valor especificado.

  • La función containsOnly() para devolver resultados solo si todos los elementos del coincidan con el subfiltro.

Ambas funciones admiten capacidades de consulta de subfiltros, como lo siguiente:

  • Coincidencia exacta de elementos: hace coincidir los elementos del array que contienen la string exacta, "example".
  • Operaciones numéricas específicas: coincide con los elementos del array que son mayores o iguales que 100.
  • Filtrado complejo con estructuras de array: haz coincidir los elementos del array que contienen la propiedad x con el valor y correspondiente.

Formato de la función contains()

La función contains() tiene el siguiente formato:

contains(ARRAY_ATTRIBUTE_NAME, SUBFILTER)

Reemplaza lo siguiente:

  • ARRAY_ATTRIBUTE_NAME: un campo o subcampo que es del tipo de array (una lista).
  • SUBFILTER: Es una expresión que define los valores que se deben buscar en el array. El formato del subfiltro difiere según si ARRAY_ATTRIBUTE_NAME es un array de objetos o un array de elementos de tipo primitivo. Si la ARRAY_ATTRIBUTE_NAME es un array de objetos que tienen array anidados, puedes usar una subfiltro con alcance para especificar que deseas que se cumplan todas las condiciones dentro del mismo elemento ARRAY_ATTRIBUTE_NAME.

En la API de Security Command Center se muestran resultados en los que ARRAY_ATTRIBUTE_NAME contiene al menos un elemento que cumple con SUBFILTER.

Formato de la función containsOnly()

La función containsOnly() tiene el siguiente formato:

containsOnly(ARRAY_ATTRIBUTE_NAME, SUBFILTER)

Reemplaza lo siguiente:

  • ARRAY_ATTRIBUTE_NAME: Es un campo o subcampo del tipo array (una ). Cuando ejecutas consultas con la API de Security Command Center, puedes usar La función containsOnly() para cualquier atributo de array disponible

  • SUBFILTER: Es una expresión que define los valores que se deben buscar en el array. El formato del subfiltro depende de si ARRAY_ATTRIBUTE_NAME es un array de objetos o un array de elementos de tipo primitivo. Si el botón ARRAY_ATTRIBUTE_NAME es un array de objetos que se anidaron. puedes usar un subfiltro con alcance para especificar querrá que se cumplan todas las condiciones dentro de la misma ARRAY_ATTRIBUTE_NAME.

La API de Security Command Center devuelve resultados en los que todos los Los elementos ARRAY_ATTRIBUTE_NAME coinciden con SUBFILTER.

Subfiltro para un array de objetos

El siguiente es un extracto del ejemplo de JSON anterior. Aquí, el campo list_middle_object es un array de objetos:

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

En el siguiente ejemplo, se consultan los resultados en los que al menos uno de los elementos del campo list_middle_object tiene un subcampo v con un valor mayor o igual que 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 ver ejemplos prácticos que usan las funciones contains() y containsOnly(), consulta lo siguiente: consulta Hallazgos que contienen un array específico de salida.

Subfiltro para un array que contiene elementos de tipo primitivo

Los tipos básicos son strings, números y booleanos. Para usar la función contains() en un array que contiene tipos básicos, usa la palabra clave especial, elem.

El siguiente es un extracto del ejemplo de JSON anterior. Aquí, el campo u es un arreglo de elementos de tipo primitivo:

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

En el siguiente ejemplo de consulta, se muestran los resultados en los que al menos uno de los elementos del campo u es “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 ver ejemplos prácticos que usen la función contains(), consulta Resultados que contienen valores de array específicos.

Subfiltro con permiso

El siguiente es un extracto del ejemplo de JSON anterior. Aquí, el campo list_middle_object es un array de objetos, y los objetos de este array contienen un array anidado.

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

En el siguiente ejemplo de consulta para resultados en los que se cumplen las siguientes condiciones dentro del mismo elemento list_middle_object:

  • El subcampo v tiene un valor mayor o igual que 321.
  • El subcampo w no contiene un elemento con una propiedad 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 ver ejemplos prácticos que usen la función contains(), consulta Resultados que contienen valores de array específicos.

Ejemplo de resultados de ordenamiento

Puedes ordenar los resultados por subcampos estrictos que son tipos básicos: strings, números y booleanos. Supongamos que el ejemplo de JSON anterior es un atributo de resultado llamado my_property. En el siguiente ejemplo, se incluyen consultas para ordenar los campos de resultados. La palabra clave DESC especifica que el campo que sigue debe ordenarse de forma descendente. El orden predeterminado es ascendente.

# 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"

Filtra ejemplos

En las siguientes secciones, se muestran ejemplos prácticos de filtros de resultados.

Filtra los resultados que se produjeron después de un momento determinado

Estos filtros de ejemplo coinciden con los resultados más recientes que se produjeron después del miércoles, 5 de junio de 2019 10:12:05 p.m. GMT. Con el filtro event_time, puedes expresar la hora con los siguientes formatos y tipos:

  • Época Unix (en milisegundos) como literal de número entero

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

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

Filtra en campos de tipo de array

En el siguiente ejemplo, se muestra el uso de una coincidencia parcial de strings en un campo de tipo de array dentro de un filtro:

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

La API de Security Command Center muestra cualquier resultado con una string parcial website.com dentro del array. Por ejemplo, coincide con un resultado con indicator.domains = [\"onewebsite.com\"] porque “website.com” es una substring en un elemento del array.

En las secciones siguientes, los filtros de ejemplo muestran algunas opciones para el uso de filtrado enriquecido por tipo de array con la función contains().

Filtra en el campo vulnerability.cve.references

En el siguiente ejemplo, se muestran los resultados en los que al menos un elemento del array vulnerability.cve.references tiene una propiedad source igual a SOURCE_OF_REFERENCE y una propiedad uri que tiene FILTERED_URI.

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

Reemplaza lo siguiente:

  • SOURCE_OF_REFERENCE: el nombre de la fuente de una referencia de vulnerabilidades y riesgos comunes (CVE), por ejemplo, NVD.
  • FILTERED_URI: Es el URI del SOURCE_OF_REFERENCE.

Filtra en el campo indicator.domains

En el siguiente ejemplo, se muestran los resultados en los que al menos un dominio de indicador tiene mycompanyprefix y .ca.

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

Filtra en el campo indicator.ip_addresses

En el siguiente ejemplo, se muestran los resultados en los que al menos un elemento del array indicator.ip_addresses es igual a IP_ADDRESS.

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

Reemplaza IP_ADDRESS por una dirección IP asociada con los resultados que buscas.

Filtrar a los usuarios asignado al sistema externo

En el siguiente ejemplo, se muestran los resultados en los que al menos un elemento del array external_systems.EXTERNAL_SYSTEM_NAME.assignees es igual a ASSIGNEE.

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

Reemplaza lo siguiente:

  • EXTERNAL_SYSTEM_NAME: el nombre de un sistema SIEM/SOAR de terceros, por ejemplo, demisto
  • ASSIGNEE: un usuario asignado en el sistema externo

Filtra en el campo resource.folders.resource_folder

En el siguiente ejemplo, se muestran los resultados en los que al menos un elemento del array resource.folders.resource_folder no es igual a FOLDER_NAME.

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

Filtra en el campo resource.folders.resource_folder_display_name

En el siguiente ejemplo, se muestran los resultados en los que al menos un elemento del array resource.folders.resource_folder_display_name es igual a DISPLAY_NAME.

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

Reemplaza DISPLAY_NAME por el nombre definido por el usuario de la carpeta asociada con los resultados que buscas.

El filtro solo incluye cuentas de servicio específicas

En el siguiente ejemplo, solo se muestran resultados cuando los valores de cada entrada iam_bindings del miembro es igual a una de las cuentas de servicio proporcionadas.

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

Reemplaza SERVICE_ACCOUNT1, SERVICE_ACCOUNT2 y SERVICE_ACCOUNT3 por las direcciones de correo electrónico de las cuentas de servicio

Para aprender a usar las funciones contains() y containsOnly() en un resultado consulta Filtra según campos de tipo array.

¿Qué sigue?

Obtén más información para configurar las notificaciones de búsquedas.