로깅 데이터 내보내기 시나리오: 보안 및 액세스 분석

이 문서에서는 조직의 클라우드 인프라 환경에 대한 보안 및 분석 요구사항을 충족시키기 위해 Cloud Logging에서 BigQuery, Chronicle 또는 타사 SIEM과 같은 대상으로 로그를 내보내는 방법을 보여줍니다. 조직은 멀웨어, 피싱, 랜섬웨어, 잘못될 수 있는 애셋 구성과 같은 위협을 방지 및 감지하고 대응하기 위해 종종 이러한 보안 분석 도구를 사용합니다. 보안 및 분석 요구사항을 충족하기 위해 이 문서에서는 먼저 관리자 활동 로그 및 데이터 액세스 로그와 같은 감사 로그 외에도 애플리케이션 로그부터 플랫폼 로그까지 Google Cloud 환경에서 다양한 보안 관련 로그에 대해 설명합니다.

먼저 로그 범위 지정 도구를 사용하여 제공되는 가시성 및 위협 감지 범위 측면에서 이러한 보안 관련 로그 유형을 평가할 수 있습니다. 이 도구는 인기 있는 MITRE ATT&CK® 위협 모델부터 이러한 일반적인 위협을 조사하는 데 도움이 되는 특정 Google Cloud 로그 유형까지 위협 기술과 전략을 매핑하여 도움을 줍니다. 이와 비슷하게 사용되는 해당 Google Cloud 로그 소스에 Security Command Center의 Event Threat Detection 모듈을 매핑합니다.

이 시나리오에서 내보낸 모델은 사용자 정의 로깅 필터 외에도 내보내기 중에 구성된 BigQuery의 데이터 세트로 전달됩니다. 로그 액세스를 제한하기 위해 필요에 따라 권한을 부여합니다. 로그 항목의 timestamp 필드를 기준으로 날짜별로 파티션을 나눈 파티션을 나눈 테이블로 데이터를 내보내도록 로그 싱크를 구성하여 데이터 관리 및 쿼리를 단순화할 수 있습니다. 이러한 접근 방법은 쿼리 중에 스캔되는 데이터 양을 줄임으로써 쿼리 비용을 낮추는 데 도움이 될 수 있습니다. 파티션을 나눈 테이블의 또 다른 이점은 개별 테이블 또는 전체 데이터 세트 수준에서 파티션 만료 시간 설정이 가능해서 유용하다고 판단되는 기간만큼만 로깅 데이터를 유지할 수 있다는 점입니다. 예를 들어 감사 로깅 데이터를 3년 동안 보관하면 파티션이 만료되고 만료되면 이전 데이터가 자동으로 삭제됩니다.

이 시나리오는 Cloud Logging 내보내기를 위한 설계 패턴 시리즈의 일부입니다.

내보낼 로그 평가

로그 범위 지정 도구

다음 대화식 로그 범위 지정 도구는 Cloud 감사 로그, 액세스 투명성 로그, 여러 플랫폼 로그를 비롯하여 Google Cloud 간의 중요한 보안 관련 로그를 나열합니다. 고유 보안 및 규정 준수 요구를 충족시키기 위해 내보내고 분석할 로그를 평가할 수 있도록 이 도구는 각 로그 유형을 해당 항목으로 매핑합니다.

로깅 내보내기 설정 섹션에서 사용할 적합한 로그 필터를 자동으로 생성하도록 원하는 로그 유형을 선택합니다.

로그 필터 기록

Cloud Shell에서 앞에서 자동 생성된 로그 필터를 저장하기 위해 변수를 만듭니다. 또한 요구 사항에 맞게 이를 더 세분화할 수 있습니다. 예를 들어 하나 이상의 특정 프로젝트에만 리소스를 필터링(또는 제외)할 수 있습니다.

export LOG_FILTER='log-filter'

로깅 내보내기 설정

다음 다이어그램은 BigQuery로 로깅 내보내기를 사용 설정하는 단계를 보여줍니다.

  • BigQuery에서 로깅 내보내기 데이터 세트를 설정합니다.
  • 모든 Google Cloud 서비스에 감사 로깅을 사용 설정합니다.
  • 특정 Google Cloud 서비스에 대해 플랫폼 로그를 사용 설정합니다.
  • 로깅 내보내기 구성
  • BigQuery 데이터세트에 대한 IAM 정책 권한 설정

BigQuery에 로그 내보내기 사용 설정

BigQuery에서 데이터 세트 설정

내보낸 로그를 호스팅하는 데이터 세트 설정 안내를 따릅니다. 집계된 로그를 사용하는 경우 BigQuery 데이터세트가 조직 내 Google Cloud 프로젝트 중 하나에 있어야 합니다. 단일 프로젝트를 위한 로그 내보내기를 사용하는 경우 BigQuery 데이터세트가 동일한 프로젝트에 있어야 합니다.

모든 서비스에 감사 로깅 사용 설정

BigQuery를 제외한 데이터 액세스 감사 로그는 기본적으로 사용 중지되어 있습니다. Google Cloud Console에서 직접 데이터 액세스 감사 로그를 구성하려면 데이터 액세스 감사 로그 구성을 참조하세요. 또는 IAM 정책 객체를 사용하여 gcloud로 데이터 액세스 감사 로그를 구성할 수 있습니다. 모든 서비스와 사용자에 데이터 액세스 감사 로그를 사용 설정하는 광범위한 IAM 정책 구성의 예시는 모든 데이터 액세스 감사 로그 사용 설정을 참조하세요.

서비스별 플랫폼 로그 사용 설정

일반적으로 리소스 수준에서 플랫폼 로그를 서비스별 기준으로 사용 설정해야 합니다. 예를 들어 Cloud DNS 로그는 VPC 네트워크 수준에서 사용 설정되고, VPC 흐름 로그는 서브넷의 모든 VM에 대해 서브넷 수준에서, 방화벽 규칙은 개별 방화벽 규칙 수준에서 사용 설정됩니다. 특정 로그 유형을 사용 설정하는 방법에 대한 자세한 내용을 보려면 로그 범위 지정 도구를 참조하고, 각 행에서 사용 설정 링크를 클릭하세요.

로깅 내보내기 구성

Google Cloud CLI에서 gcloud logging sinks create 명령어 또는 organizations.sinks.create API 호출을 사용하여 적절한 로깅 필터로 싱크를 만듭니다. 아래의 gcloud 예시 명령어는 조직에 gcp_logging_sink_bq라는 싱크를 만듭니다. 이 싱크는 모든 하위 프로젝트를 포함하며 위에서 만든 $LOG_FILTER 변수에 저장된 로그 필터를 지정합니다.

gcloud logging sinks create gcp_logging_sink_bq \
     bigquery.googleapis.com/projects/compliance-logging-export/datasets/gcp_logging_export \
     --use-partitioned-tables \
     --log-filter='$LOG_FILTER' \
     --include-children \
     --organization=324989855333

명령어 결과는 다음과 비슷합니다.

Created [https://logging.googleapis.com/v2/organizations/324989855333/sinks/gcp_logging_sink_bq].
Please remember to grant `serviceAccount:gcp-logging-sink-bq@logging-o324989855333.iam.gserviceaccount.com` the WRITER role on the dataset..
More information about sinks can be found at /logging/docs/export/configure_export

API 호출에서 반환된 serviceAccount 항목에서 gcp-logging-sink-bq@logging-o324989855333.iam.gserviceaccount.com이라는 ID가 응답에 포함되어 있습니다. 이 ID는 로그 내보내기를 위해 특별히 생성된 Google Cloud 서비스 계정을 나타냅니다. 이 ID에 BigQuery 데이터 세트에 대한 쓰기 액세스 권한을 부여하기 전까지 이 싱크에서 수행되는 로그 항목 내보내기는 실패합니다. 자세한 내용은 다음 섹션을 참조하세요.

BigQuery 데이터세트에 대한 IAM 정책 권한 설정

편집자 권한이있는 gcp_logging_export 데이터세트에 서비스 계정 gcp-logging-sink-bq@logging-o324989855333.iam.gserviceaccount.com을 추가하면 서비스 계정에 대상에 쓸 수 있는 권한이 부여됩니다. 이러한 권한을 추가할 때까지는 싱크 내보내기가 실패합니다.

서비스 계정에 이 권한을 추가하려면 다음 단계를 따르세요.

  1. Cloud Console에서 BigQuery로 이동합니다.

    BigQuery로 이동

  2. 새로 만든 gcp_logging_export 데이터 세트를 엽니다.

  3. 데이터 세트 정보 탭에서 공유 드롭다운 메뉴를 클릭한 다음 권한을 클릭합니다.

  4. 데이터 세트 권한 측면 패널에서 주 구성원 추가를 클릭합니다.

  5. 새 주 구성원 필드에 서비스 계정을 입력합니다. 다음 이미지와 같이 역할 드롭다운 메뉴에서 BigQuery 데이터 편집기를 선택합니다.

    IAM 정책 권한 - 편집자

이 필터를 사용하여 로깅 내보내기를 만든 후에는 구성된 프로젝트에서 BigQuery 데이터세트가 로그 파일로 채워집니다.

예제 권한 집합으로 다음을 수행할 수 있습니다.

  • BigQuery 데이터세트 권한에서 중요하지 않은 모든 사용자를 삭제합니다.
  • BigQuery 관리자에게 전체 권한을 추가합니다.
  • 내보내기 서비스 계정에 내보내기 로그를 쓸 수 있는 권한을 부여합니다.
  • 다른 개별 사용자에게 Google Cloud 로깅 내보내기에 대한 뷰어 액세스 권한을 부여합니다.

내보낸 로그 사용

로그를 BigQuery 데이터 세트로 내보내면 Cloud Logging은 내보낸 로그 항목을 보관할 테이블을 만듭니다. 로그 항목은 항목의 로그 이름을 기반으로 이름이 지정되고 항목의 타임스탬프에 따라 파티션을 나눈 테이블에 배치됩니다. 예를 들어 데이터 액세스 감사 로그는 다음 이미지와 같이 cloudaudit_googleapis_com_data_access 테이블로 라우팅됩니다.

스키마가 있는 테이블 목록

관리자 활동 로그와 데이터 액세스 로그는 모두 protoPayload 형식을 사용해 BigQuery에 로드됩니다. BigQuery에 쓰기 전에 Cloud Logging이 수행하는 스키마 변환에 대한 자세한 내용은 내보낸 감사 로그의 필드를 참조하세요.

샘플 질문과 쿼리

감사 로그에는 다양한 쿼리를 실행할 수 있습니다. 이러한 쿼리는 Google Cloud의 데이터에 액세스하거나 데이터를 수정하는 사용자를 파악하기 위해 분석을 수행합니다. gcp_logging_export를 BigQuery 데이터 세트 이름으로 바꿉니다.

지난 주 데이터에 가장 많이 액세스한 사용자

다음 쿼리는 데이터 액세스 감사 로그를 사용하여 지난 주 BigQuery 테이블 데이터에 가장 자주 액세스한 사용자 ID를 찾습니다.

SELECT
  protopayload_auditlog.authenticationInfo.principalEmail,
  COUNT(*) AS COUNTER
FROM `gcp_logging_export.cloudaudit_googleapis_com_data_access`
WHERE
  (protopayload_auditlog.methodName = "google.cloud.bigquery.v2.JobService.InsertJob" OR
   protopayload_auditlog.methodName = "google.cloud.bigquery.v2.JobService.Query")
  AND timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
GROUP BY
  1
ORDER BY
  2 desc, 1
LIMIT
  100

지난 달 'accounts' 테이블에서 데이터에 액세스한 사용자

다음 쿼리는 데이터 액세스 감사 로그를 사용하여 지난 달 동안 'accounts' 테이블에 쿼리를 가장 많이 실행한 사용자 계정을 찾습니다. MY_PROJECT_IDMY_DATASET를 각각 프로젝트 ID와 데이터 세트로 바꿉니다.

SELECT
  protopayload_auditlog.authenticationInfo.principalEmail,
  COUNT(*) AS COUNTER
FROM `gcp_logging_export.cloudaudit_googleapis_com_data_access`,
  UNNEST(protopayload_auditlog.authorizationInfo) authorizationInfo
WHERE
  (protopayload_auditlog.methodName = "google.cloud.bigquery.v2.JobService.InsertJob" OR
   protopayload_auditlog.methodName = "google.cloud.bigquery.v2.JobService.Query")
  AND authorizationInfo.permission = "bigquery.tables.getData"
  AND authorizationInfo.resource = "projects/MY_PROJECT_ID/datasets/MY_DATASET/tables/accounts"
  AND timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)
GROUP BY
  1
ORDER BY
  2 desc, 1
LIMIT
  100

지난 주 VM을 삭제한 사용자

다음 쿼리는 Admin Activity 감사 로그를 사용하여 지난 주 VM을 삭제한 사용자 ID를 찾습니다.

SELECT
  timestamp,
  resource.labels.instance_id,
  protopayload_auditlog.authenticationInfo.principalEmail,
  protopayload_auditlog.resourceName,
  protopayload_auditlog.methodName
FROM `gcp_logging_export.cloudaudit_googleapis_com_activity`
WHERE
  resource.type = "gce_instance"
  AND protopayload_auditlog.methodName = "v1.compute.instances.delete"
  AND operation.first IS TRUE
  AND timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
ORDER BY
  timestamp desc,
  resource.labels.instance_id
LIMIT
  1000

다음 쿼리는 Admin Activity 감사 로그를 사용하여 지난 달 자동 확장이 사용된 횟수를 찾습니다.

SELECT
  protopayload_auditlog.methodName,
  COUNT(*) AS counter
FROM `gcp_logging_export.cloudaudit_googleapis_com_activity`
WHERE
  resource.type = "gce_instance_group_manager"
  AND timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)
GROUP BY
  1
ORDER BY
  1
LIMIT
  1000

다음 쿼리를 사용하면 시간 경과에 따른 Compute Engine 인스턴스 관리자 작업의 트렌드를 일별로 구분하여 시각화할 수 있습니다.

SELECT
  TIMESTAMP_TRUNC(timestamp, DAY) AS day,
  protopayload_auditlog.methodName AS methodName,
  COUNT(*) AS counter
FROM `gcp_logging_export.cloudaudit_googleapis_com_activity`
WHERE
  resource.type = "gce_instance_group_manager"
  AND timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)
GROUP BY
  1, 2
ORDER BY
  1, 2

다음 그래프에 표시된 것처럼 이전 쿼리를 Google Data Studio에서 데이터 소스 커스텀 쿼리로 사용해서 시간 경과에 따른 추세를 시각화할 수 있습니다.

Data Studio 시각화

자세한 내용은 Data Studio 커스텀 쿼리를 참조하세요.

가장 많이 액세스된 테이블과 액세스한 사용자

다음 쿼리는 데이터 액세스 감사 로그를 사용하여 지난 1개월 동안 가장 자주 읽고 수정한 데이터가 포함된 BigQuery 테이블을 찾습니다. 데이터를 읽은 횟수와 수정한 총 횟수를 분석하여 관련 사용자 ID를 표시합니다.

SELECT
  protopayload_auditlog.resourceName,
  protopayload_auditlog.authenticationInfo.principalEmail,
  COUNTIF(JSON_EXTRACT(protopayload_auditlog.metadataJson, "$.tableDataRead") IS NOT NULL) AS dataReadEvents,
  COUNTIF(JSON_EXTRACT(protopayload_auditlog.metadataJson, "$.tableDataChange") IS NOT NULL) AS dataChangeEvents,
  COUNT(*) AS totalEvents
FROM `gcp_logging_export.cloudaudit_googleapis_com_data_access`
WHERE
  STARTS_WITH(resource.type, 'bigquery') IS TRUE
  AND (JSON_EXTRACT(protopayload_auditlog.metadataJson, "$.tableDataRead") IS NOT NULL
    OR JSON_EXTRACT(protopayload_auditlog.metadataJson, "$.tableDataChange") IS NOT NULL)
  AND timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)
GROUP BY
  1, 2
ORDER BY
  5 DESC, 1, 2
LIMIT 1000

지난 주 BigQuery에서 수행된 최상위 10개 쿼리

다음 쿼리는 데이터 액세스 감사 로그를 사용하여 지난 주 동안 가장 일반적인 쿼리를 찾습니다. 또한 해당 사용자와 참조된 테이블이 나열됩니다.

SELECT
  COALESCE(
   JSON_EXTRACT_SCALAR(protopayload_auditlog.metadataJson, "$.jobChange.job.jobConfig.queryConfig.query"),
   JSON_EXTRACT_SCALAR(protopayload_auditlog.metadataJson, "$.jobInsertion.job.jobConfig.queryConfig.query")) as query,
  STRING_AGG(DISTINCT protopayload_auditlog.authenticationInfo.principalEmail, ',') as users,
  ANY_VALUE(COALESCE(
   JSON_EXTRACT_ARRAY(protopayload_auditlog.metadataJson, "$.jobChange.job.jobStats.queryStats.referencedTables"),
   JSON_EXTRACT_ARRAY(protopayload_auditlog.metadataJson, "$.jobInsertion.job.jobStats.queryStats.referencedTables"))) as tables,
  COUNT(*) AS counter
FROM `gcp_logging_export.cloudaudit_googleapis_com_data_access`
WHERE
  (resource.type = 'bigquery_project' OR resource.type = 'bigquery_dataset')
  AND operation.last IS TRUE
  AND (JSON_EXTRACT(protopayload_auditlog.metadataJson, "$.jobChange") IS NOT NULL
    OR JSON_EXTRACT(protopayload_auditlog.metadataJson, "$.jobInsertion") IS NOT NULL)
  AND timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY)
GROUP BY
  query
ORDER BY
  counter DESC
LIMIT 10

지난 달 데이터 액세스 로그에 기록된 가장 일반적인 작업

다음 쿼리는 모든 Cloud 감사 로그를 사용하여 지난달에 기록된 가장 자주 발생한 작업 100개를 찾습니다.

SELECT
  ANY_VALUE(_TABLE_SUFFIX),
  protopayload_auditlog.methodName,
  protopayload_auditlog.serviceName,
  resource.type,
  COUNT(*) AS counter
FROM `gcp_logging_export.cloudaudit_googleapis_com_*`
WHERE
  timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 30 DAY)
GROUP BY
  protopayload_auditlog.methodName,
  protopayload_auditlog.serviceName,
  resource.type
ORDER BY
  counter DESC
LIMIT 100

다음 단계