이 주제에서는 Cloud 애셋 인벤토리를 활용하여 Secret Manager 리소스를 분석하는 방법을 알아봅니다.
이 내용은 Secret Manager에 대한 고급 주제입니다. 이 가이드를 읽기 전에 다음 사항을 검토하는 것이 좋습니다.
- Google Cloud 환경에 대한 전반적인 이해를 돕기 위한 플랫폼 개요
- Secret Manager에 대한 이해를 돕기 위한 Secret Manager 개요
- Cloud 애셋 인벤토리에 대한 이해를 돕고 포괄적인 애셋 관리 기능을 확인하기 위한 Cloud 애셋 인벤토리 개요
개요
Secret Manager는 Google Cloud의 관리형 메타데이터 인벤토리 시스템인 Cloud 애셋 인벤토리와 통합됩니다. 이 통합을 통해 조직, 폴더 또는 프로젝트에서 보안 비밀을 식별하고 감사할 수 있으며 조직의 요구사항을 준수하지 않는 구성을 검색할 수 있습니다. 이 가이드에서는 애셋 모니터링, BigQuery로 애셋 내보내기, Secret Manager 리소스에 대한 Cloud 애셋 인벤토리 쿼리 샘플을 다룹니다.
참고
- 모든 쿼리에 Google Cloud CLI 및 BigQuery로 작성된 샘플이 있지만 보안 비밀 및 보안 비밀 버전을 BigQuery로 내보내는 것이 좋습니다. 애셋을 BigQuery로 내보내면 SQL과 유사한 쿼리를 작성하여 의미 있는 분석을 생성하고 저장할 수 있습니다.
- Secret Manager는 애셋 검색 또는 정책 분석자와 통합되지 않습니다. 아래 쿼리는 Google Cloud CLI 명령줄 도구와 BigQuery의 기본 속성을 활용하여 애셋을 검색합니다.
- Cloud 애셋 인벤토리는 지난 5주 동안만의 스냅샷 내보내기 및 나열을 지원합니다.
애셋 변경사항 모니터링
Cloud 애셋 인벤토리는 실시간 업데이트를 추적하고 이러한 변경사항 모니터링을 지원합니다. 피드를 구성하여 리소스가 수정될 때마다 구성된 Pub/Sub 주제 모음에 알림을 보낼 수 있습니다. 또한 Cloud 애셋 인벤토리는 피드의 조건 구성을 지원하므로 특정 애셋 유형의 특정 변경사항을 모니터링할 수 있습니다. 애셋 변경에 대한 워크플로를 트리거하는 방법은 Pub/Sub 문서를 참조하세요.
BigQuery로 애셋 내보내기
보안 비밀과 보안 비밀 버전을 BigQuery로 내보내면 대규모 데이터에 대해 SQL과 유사한 쿼리를 실행하고 애셋에 대한 의미 있는 정보를 생성할 수 있습니다. 애셋을 내보내기 전에 데이터 세트 및 서비스 계정이 올바르게 구성되었는지 확인하세요. 애셋을 내보내려면 다음 명령어를 실행합니다.
gcloud
$ gcloud asset export \ --content-type CONTENT_TYPE \ --project PROJECT_ID \ --snapshot-time SNAPSHOT_TIME \ --bigquery-table BIGQUERY_TABLE \ --output-bigquery-force
각 항목의 의미는 다음과 같습니다.
- CONTENT_TYPE: 애셋 콘텐츠 유형(
RESOURCE
)입니다. - PROJECT_ID: 모니터링할 애셋이 포함된 프로젝트 ID입니다.
- SNAPSHOT_TIME: 리소스의 스냅샷을 만들 시간이며, 현재와 지난 5주 이내입니다.
- BIGQUERY_TABLE:
projects/PROJECT_ID/datasets/DATASET_ID/tables/TABLE_NAME
형식으로 데이터를 내보낼 테이블입니다.
자세한 내용은 BigQuery로 내보내기를 참조하세요.
샘플 쿼리
지난 2주 동안 생성된 보안 비밀
지난 2주 동안 조직에 추가된 보안 비밀과 그 속성을 검색합니다.
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"
자동으로 복제된 보안 비밀
자동으로 복제된 모든 보안 비밀을 찾습니다.
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"
지정된 리전에 복제된 보안 비밀
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"
180일 이상 사용 설정된 보안 비밀 버전
180일 이전에 생성된 모든 보안 비밀 버전을 나열합니다.
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"
CMEK가 구성되지 않은 보안 비밀
고객 관리자 암호화 키(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"
CMEK가 구성된 보안 비밀
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"
특정 CMEK로 암호화된 보안 비밀
특정 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") = 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"
CMEK가 구성되지 않은 보안 비밀 버전
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"
특정 CMEK로 암호화된 보안 비밀 버전
특정 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") = 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"
순환이 구성되지 않은 보안 비밀
순환 일정이 없는 모든 보안 비밀을 찾습니다.
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"
특정 순환 기간이 있는 보안 비밀
90일 미만마다 한 번 순환하도록 예약된 모든 보안 비밀을 찾습니다.
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"
향후 30일 이내에 만료되는 보안 비밀
향후 30일 이내에 만료되는 보안 비밀을 나열합니다.
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"
Pub/Sub 주제가 구성된 보안 비밀
Pub/Sub 주제가 하나 이상 구성된 모든 보안 비밀을 나열합니다.
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"
다음 단계
- 다른 제품에서 Secret Manager 사용에 대해 자세히 알아보기