Analiza secretos con Cloud Asset Inventory

En este tema, aprenderás a aprovechar Cloud Asset Inventory para analizar los recursos de Secret Manager.

Este es un tema avanzado de Secret Manager. Antes de leer esta guía, te recomendamos que revises lo siguiente:

Descripción general

Secret Manager está integrado en Cloud Asset Inventory, el sistema de inventario de metadatos administrados de Google Cloud. Con esta integración, puedes identificar y auditar los secretos de tu organización, carpeta o proyecto, y descubrir cualquier configuración que no cumpla con los requisitos de tu organización. En esta guía, se describe cómo supervisar tus elementos, exportarlos a BigQuery y muestras de consultas de Cloud Asset Inventory a través de los recursos de Secret Manager.

Notas

  • Aunque todas las consultas tienen muestras escritas con Google Cloud CLI y BigQuery, te recomendamos exportar las versiones de los secretos y los secretos a BigQuery. Si exportas tus elementos a BigQuery, puedes escribir consultas similares a las de SQL para producir y almacenar análisis significativos.
  • Secret Manager no está integrado en Busca recursos ni en el Analizador de políticas. Las siguientes consultas aprovechan las propiedades nativas de Google Cloud CLI y BigQuery para buscar en los recursos.
  • Cloud Asset Inventory es compatible con la exportación y la enumeración de instantáneas solo de las últimas cinco semanas.

Supervisar cambios en los recursos

Cloud Asset Inventory realiza un seguimiento de las actualizaciones en tiempo real y admite la supervisión de estos cambios. Puedes configurar feeds para enviar notificaciones a un conjunto de temas de Pub/Sub configurados cada vez que haya una modificación en tus recursos. Además, Cloud Asset Inventory es compatible con la configuración de condiciones en tus feeds para que puedas supervisar cambios específicos en ciertos tipos de recursos. Consulta la documentación de Pub/Sub si deseas obtener información para activar flujos de trabajo en los cambios de recursos.

Exporta elementos a BigQuery

Exportar tus secretos y versiones de secretos a BigQuery te permite ejecutar consultas similares a las de SQL sobre grandes cantidades de datos y producir estadísticas significativas sobre tus recursos. Antes de exportar tus elementos, asegúrate de que tus cuentas de servicio y conjunto de datos estén configuradas de forma correcta. Para exportar tus recursos, ejecuta el siguiente comando:

gcloud

$ gcloud asset export \
   --content-type CONTENT_TYPE \
   --project PROJECT_ID \
   --snapshot-time SNAPSHOT_TIME \
   --bigquery-table BIGQUERY_TABLE \
   --output-bigquery-force

Donde:

  • CONTENT_TYPE: Tipo de contenido del recurso (RESOURCE)
  • PROJECT_ID: ID del proyecto que contiene recursos que se deben supervisar.
  • SNAPSHOT_TIME: Hora en la que se toman las instantáneas de los recursos. Entre el momento actual y las 5 semanas anteriores
  • BIGQUERY_TABLE: Tabla a la cual exportar los datos, en el formato projects/PROJECT_ID/datasets/DATASET_ID/tables/TABLE_NAME.

Para obtener más información, consulta Exporta a BigQuery.

Consultas de muestra

Secreto creado en las últimas dos semanas

Descubre todos los secretos (y sus propiedades) que se agregaron a tu organización en las últimas dos semanas:

BigQuery

SELECT name, FROM PROJECT_ID.DATASET_ID.TABLE_NAME
WHERE asset_type='secretmanager.googleapis.com/Secret' AND
DATE(JSON_VALUE(resource.data, '$.createTime')) > DATE_SUB(CURRENT_DATE(), INTERVAL 2 WEEK);

gcloud

$ NOW=$(TZ=GMT date +"%Y-%m-%dT%H:%M:%SZ")
$ gcloud asset list --project=PROJECT_ID \
    --asset-types='secretmanager.googleapis.com/Secret' \
    --snapshot-time=$NOW \
    --content-type='resource' \
    --filter="resource.data.createTime>-P2W"

Secretos replicados de forma automática

Encuentra todos los secretos replicados de forma automática:

BigQuery

SELECT * FROM PROJECT_ID.DATASET_ID.TABLE_NAME
WHERE asset_type='secretmanager.googleapis.com/Secret' AND
JSON_EXTRACT(resource.data, '$.replication.automatic') IS NOT NULL;

gcloud

$ NOW=$(TZ=GMT date +"%Y-%m-%dT%H:%M:%SZ")
$ gcloud asset list --project=PROJECT_ID \
    --asset-types='secretmanager.googleapis.com/Secret' \
    --snapshot-time=$NOW \
    --content-type='resource' \
    --filter="resource.data.replication.automatic != NULL"

Secreto replicado en una región específica

Busca todos los secretos replicados en us-central1:

BigQuery

SELECT * FROM PROJECT_ID.DATASET_ID.TABLE_NAME
WHERE
(
  SELECT * FROM
  UNNEST(JSON_EXTRACT_ARRAY(resource.data, '$.replication.userManaged.replicas')) AS location
  WHERE JSON_VALUE(JSON_EXTRACT(location, '$.location')) = "us-central1"
)
IS NOT NULL;

gcloud

$ NOW=$(TZ=GMT date +"%Y-%m-%dT%H:%M:%SZ")
$ gcloud asset list --project=PROJECT_ID \
    --asset-types='secretmanager.googleapis.com/Secret' \
    --snapshot-time=$NOW \
    --content-type='resource' \
    --filter="resource.data.replication.userManaged.replicas.location=us-central1"

Versiones de Secrets habilitadas con más de 180 días de antigüedad

Enumera todas las versiones de los secretos que se crearon hace más de 180 días:

BigQuery

SELECT * FROM PROJECT_ID.DATASET_ID.TABLE_NAME
WHERE asset_type='secretmanager.googleapis.com/SecretVersion' AND
DATE(JSON_VALUE(resource.data, '$.createTime')) < DATE_SUB(CURRENT_DATE(), INTERVAL 180 DAY) AND
JSON_VALUE(resource.data, '$.state') = "ENABLED";

gcloud

$ NOW=$(TZ=GMT date +"%Y-%m-%dT%H:%M:%SZ")
$ gcloud asset list --project=PROJECT_ID \
    --asset-types='secretmanager.googleapis.com/SecretVersion' \
    --snapshot-time=$NOW \
    --content-type='resource' \
    --filter="resource.data.createTime < P6M AND resource.data.state=ENABLED"

Secreto sin CMEK configurado

Enumera todos los secretos (automáticos y administrados por el usuario) que no están encriptados con claves de encriptación de administrador del cliente (CMEK):

BigQuery

SELECT * FROM PROJECT_ID.DATASET_ID.TABLE_NAME
WHERE asset_type='secretmanager.googleapis.com/Secret'
  AND (
    JSON_VALUE(resource.data, "$.replication.automatic.customerManagedEncryption.kmsKeyName") IS NULL
    AND JSON_VALUE(resource.data, "$.replication.userManaged.replicas[0].customerManagedEncryption.kmsKeyName") IS NULL
  );

gcloud

$ NOW=$(TZ=GMT date +"%Y-%m-%dT%H:%M:%SZ")
$ gcloud asset list --project=PROJECT_ID \
    --asset-types='secretmanager.googleapis.com/Secret' \
    --snapshot-time=$NOW \
    --content-type='resource' \
    --filter="resource.data.replication.userManaged.replicas.customerManagedEncryption = NULL OR resource.data.replication.automatic.customerManagedEncryption=NULL"

Secreto con CMEK configurado

Enumera todos los secretos (automáticos y administrados por el usuario) que se encriptan con CMEK:

BigQuery

SELECT * FROM PROJECT_ID.DATASET_ID.TABLE_NAME
WHERE asset_type='secretmanager.googleapis.com/Secret'
AND (
  JSON_VALUE(resource.data, "$.replication.automatic.customerManagedEncryption.kmsKeyName") IS NOT NULL
  OR JSON_VALUE(resource.data, "$.replication.userManaged.replicas[0].customerManagedEncryption.kmsKeyName") IS NOT NULL
);

gcloud

$ NOW=$(TZ=GMT date +"%Y-%m-%dT%H:%M:%SZ")
$ gcloud asset list --project=PROJECT_ID \
    --asset-types='secretmanager.googleapis.com/Secret' \
    --snapshot-time=$NOW \
    --content-type='resource' \
    --filter="resource.data.replication.userManaged.replicas.customerManagedEncryption != NULL OR resource.data.replication.automatic.customerManagedEncryption!=NULL"

Secretos encriptados con una CMEK específica

Busca los secretos que sean versiones encriptadas de secretos con una CMEK determinada:

BigQuery

SELECT * FROM PROJECT_ID.DATASET_ID.TABLE_NAME
WHERE asset_type='secretmanager.googleapis.com/Secret'
  AND (
    JSON_VALUE(resource.data, "$.replication.automatic.customerManagedEncryption.kmsKeyName") = KMS_KEY_NAME
    OR JSON_VALUE(resource.data, "$.replication.userManaged.replicas[0].customerManagedEncryption.kmsKeyName") = KMS_KEY_NAME
  );

gcloud

$ NOW=$(TZ=GMT date +"%Y-%m-%dT%H:%M:%SZ")
$ gcloud asset list --project=PROJECT_ID \
    --asset-types='secretmanager.googleapis.com/Secret' \
    --snapshot-time=$NOW \
    --content-type='resource' \
    --filter="resource.data.replication.userManaged.replicas.customerManagedEncryption.kmsKeyName=KMS_KEY_NAME"

Versiones de secretos sin CMEK configuradas

Busca todas las versiones de secreto habilitadas que no estén encriptadas con CMEK:

BigQuery

SELECT * FROM PROJECT_ID.DATASET_ID.TABLE_NAME
WHERE asset_type='secretmanager.googleapis.com/SecretVersion'
AND (
  JSON_VALUE(resource.data, "$.replicationStatus.automatic.customerManagedEncryption.kmsKeyVersionName") IS NULL
  AND JSON_VALUE(resource.data, "$.replicationStatus.userManaged.replicas[0].customerManagedEncryption.kmsKeyVersionName") IS NULL
)
AND JSON_VALUE(resource.data, "$.state") = "ENABLED";

gcloud

$ NOW=$(TZ=GMT date +"%Y-%m-%dT%H:%M:%SZ")
$ gcloud asset list --project=PROJECT_ID \
    --asset-types='secretmanager.googleapis.com/SecretVersion' \
    --snapshot-time=$NOW \
    --content-type='resource' \
    --filter="(resource.data.replicationStatus.userManaged.replicas.customerManagedEncryption = NULL OR resource.data.replicationStatus.automatic.customerManagedEncryption=NULL) AND resource.data.state=ENABLED"

Versiones de los secretos encriptadas con una CMEK específica

Enumera todas las versiones de secretos habilitadas que se encriptaron con una versión de CMEK específica:

BigQuery

SELECT * FROM PROJECT_ID.DATASET_ID.TABLE_NAME
WHERE asset_type='secretmanager.googleapis.com/SecretVersion'
AND (
  JSON_VALUE(resource.data, "$.replicationStatus.automatic.customerManagedEncryption.kmsKeyVersionName") = KMS_KEY_VERSION_NAME
  OR JSON_VALUE(resource.data, "$.replicationStatus.userManaged.replicas[0].customerManagedEncryption.kmsKeyVersionName") = KMS_KEY_VERSION_NAME
)
AND JSON_VALUE(resource.data,"$.state")="ENABLED";

gcloud

$ NOW=$(TZ=GMT date +"%Y-%m-%dT%H:%M:%SZ")
$ gcloud asset list --project=PROJECT_ID \
    --asset-types='secretmanager.googleapis.com/SecretVersion' \
    --snapshot-time=$NOW \
    --content-type='resource' \
    --filter="resource.data.replicationStatus.userManaged.replicas.customerManagedEncryption.kmsKeyVersionName=$FULL_KMS_KEY_VERSION_RESOURCE_NAME AND resource.data.status=ENABLED"

Secretos sin rotación configurada

Busca todos los secretos que no tengan un programa de rotación:

BigQuery

SELECT name FROM PROJECT_ID.DATASET_ID.TABLE_NAME
WHERE asset_type='secretmanager.googleapis.com/Secret' AND
JSON_EXTRACT(resource.data, '$.rotation') IS NULL;

gcloud

$ NOW=$(TZ=GMT date +"%Y-%m-%dT%H:%M:%SZ")
$ gcloud asset list --project=PROJECT_ID \
    --asset-types='secretmanager.googleapis.com/Secret' \
    --snapshot-time=$NOW \
    --content-type='resource' \
    --filter="resource.data.rotation=NULL"

Secretos con un período de rotación específico

Busca todos los secretos programados para rotar menos de una vez cada 90 días:

BigQuery

SELECT *
FROM PROJECT_ID.DATASET_ID.TABLE_NAME
WHERE
  CAST(
    TRIM(
      JSON_VALUE(JSON_EXTRACT(resource.data, "$.rotation.rotationPeriod")),"s")
    AS INT64)
< 86400 * 90 #Rotation period in seconds (86400s in 1 day * 90 days)

gcloud

$ NOW=$(TZ=GMT date +"%Y-%m-%dT%H:%M:%SZ")
$ ROTATION_PERIOD_SECONDS=$((90 * 24 * 60 * 60))
$ gcloud asset list --project=PROJECT_ID \
    --asset-types='secretmanager.googleapis.com/Secret' \
    --snapshot-time=$NOW \
    --content-type='resource' \
    --filter="resource.data.rotation != null AND resource.data.rotation.rotationPeriod < ${ROTATION_PERIOD_SECONDS}s"

Los secretos que vencerán en los próximos 30 días

Enumera los secretos que vencerán en los próximos 30 días:

BigQuery

SELECT * FROM PROJECT_ID.DATASET_ID.TABLE_NAME
WHERE asset_type='secretmanager.googleapis.com/Secret' AND
DATE(JSON_VALUE(resource.data, '$.expireTime')) < DATE_ADD(CURRENT_DATE(), INTERVAL 30 DAY);

gcloud

$ NOW=$(TZ=GMT date +"%Y-%m-%dT%H:%M:%SZ")
$ gcloud asset list --project=PROJECT_ID \
    --asset-types='secretmanager.googleapis.com/Secret' \
    --snapshot-time=$NOW \
    --content-type='resource' \
    --filter="resource.data.expireTime < PD30"

Secretos con un tema de Pub/Sub configurado

Enumera todos los secretos que tengan al menos un tema de Pub/Sub configurado:

BigQuery

SELECT name, ARRAY_LENGTH(JSON_EXTRACT_ARRAY(resource.data, '$.topics')) AS topics_count,
FROM PROJECT_ID.DATASET_ID.TABLE_NAME
WHERE asset_type='secretmanager.googleapis.com/Secret' AND
ARRAY_LENGTH(JSON_EXTRACT_ARRAY(resource.data, '$.topics')) > 0

gcloud

$ NOW=$(TZ=GMT date +"%Y-%m-%dT%H:%M:%SZ")
$ gcloud asset list --project=PROJECT_ID \
    --asset-types='secretmanager.googleapis.com/Secret' \
    --snapshot-time=$NOW \
    --content-type='resource' \
    --filter="resource.data.topics !=NULL"

¿Qué sigue?