SailPoint IAM 로그 수집
이 문서에서는 Google Cloud Storage를 사용하여 SailPoint IAM 로그를 Google Security Operations에 수집하는 방법을 설명합니다. SailPoint Identity Security Cloud는 엔터프라이즈 애플리케이션 전반에서 사용자 액세스, 규정 준수, 보안을 관리하기 위한 ID 거버넌스 및 관리 기능을 제공합니다.
시작하기 전에
다음 기본 요건이 충족되었는지 확인합니다.
- Google SecOps 인스턴스
- Cloud Storage API가 사용 설정된 GCP 프로젝트
- GCS 버킷을 만들고 관리할 수 있는 권한
- GCS 버킷의 IAM 정책을 관리할 수 있는 권한
- Cloud Run 서비스, Pub/Sub 주제, Cloud Scheduler 작업을 만들 수 있는 권한
- SailPoint Identity Security Cloud 테넌트 또는 API에 대한 액세스 권한
Google Cloud Storage 버킷 만들기
- Google Cloud Console로 이동합니다.
- 프로젝트를 선택하거나 새 프로젝트를 만듭니다.
- 탐색 메뉴에서 Cloud Storage> 버킷으로 이동합니다.
- 버킷 만들기를 클릭합니다.
다음 구성 세부정보를 제공합니다.
설정 값 버킷 이름 지정 전역적으로 고유한 이름 (예: sailpoint-iam-logs)을 입력합니다.위치 유형 필요에 따라 선택 (리전, 이중 리전, 멀티 리전) 위치 위치를 선택합니다 (예: us-central1).스토리지 클래스 Standard (자주 액세스하는 로그에 권장) 액세스 제어 균일 (권장) 보호 도구 선택사항: 객체 버전 관리 또는 보관 정책 사용 설정 만들기를 클릭합니다.
SailPoint Identity Security Cloud API 사용자 인증 정보 수집
- 관리자로 SailPoint Identity Security Cloud Admin Console에 로그인합니다.
- 관리 > 전역 > 보안 설정 > API 관리로 이동합니다.
- API 클라이언트 만들기를 클릭합니다.
- 부여 유형으로 클라이언트 사용자 인증 정보를 선택합니다.
- 다음 구성 세부정보를 제공합니다.
- 이름: 설명이 포함된 이름을 입력합니다 (예:
Chronicle Export API). - 설명: API 클라이언트의 설명을 입력합니다.
- 범위: sp:scopes:all (또는 감사 이벤트에 적합한 읽기 범위)을 선택합니다.
- 이름: 설명이 포함된 이름을 입력합니다 (예:
- 만들기를 클릭하고 생성된 API 사용자 인증 정보를 안전하게 복사합니다.
- SailPoint 테넌트 기본 URL (예:
https://tenant.api.identitynow.com)을 기록합니다. 다음 세부정보를 복사하여 안전한 위치에 저장합니다.
IDN_CLIENT_IDIDN_CLIENT_SECRETIDN_BASE
API 액세스 테스트
통합을 진행하기 전에 사용자 인증 정보를 테스트하세요.
# Replace with your actual credentials IDN_CLIENT_ID="your-client-id" IDN_CLIENT_SECRET="your-client-secret" IDN_BASE="https://tenant.api.identitynow.com" # Get OAuth token TOKEN=$(curl -s -X POST "${IDN_BASE}/oauth/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=client_credentials&client_id=${IDN_CLIENT_ID}&client_secret=${IDN_CLIENT_SECRET}&scope=sp:scopes:all" | jq -r '.access_token') # Test API access curl -v -H "Authorization: Bearer ${TOKEN}" "${IDN_BASE}/v3/search" \ -H "Content-Type: application/json" \ -d '{"indices":["events"],"query":{"query":"*"},"limit":1}'
Cloud Run 함수의 서비스 계정 만들기
Cloud Run 함수에는 GCS 버킷에 쓸 수 있는 권한이 있는 서비스 계정이 필요합니다.
서비스 계정 만들기
- GCP 콘솔에서 IAM 및 관리자 > 서비스 계정으로 이동합니다.
- 서비스 계정 만들기를 클릭합니다.
- 다음 구성 세부정보를 제공합니다.
- 서비스 계정 이름:
sailpoint-iam-collector-sa을 입력합니다. - 서비스 계정 설명:
Service account for Cloud Run function to collect SailPoint IAM logs을 입력합니다.
- 서비스 계정 이름:
- 만들고 계속하기를 클릭합니다.
- 이 서비스 계정에 프로젝트에 대한 액세스 권한 부여 섹션에서 다음 단계를 따르세요.
- 역할 선택을 클릭합니다.
- 스토리지 객체 관리자를 검색하여 선택합니다.
- + 다른 역할 추가를 클릭합니다.
- Cloud Run 호출자를 검색하여 선택합니다.
- + 다른 역할 추가를 클릭합니다.
- Cloud Functions 호출자를 검색하여 선택합니다.
- 계속을 클릭합니다.
- 완료를 클릭합니다.
이러한 역할은 다음 작업에 필요합니다.
- 스토리지 객체 관리자: GCS 버킷에 로그를 쓰고 상태 파일을 관리합니다.
- Cloud Run 호출자: Pub/Sub가 함수를 호출하도록 허용
- Cloud Functions 호출자: 함수 호출 허용
GCS 버킷에 대한 IAM 권한 부여
GCS 버킷에 대한 쓰기 권한을 서비스 계정에 부여합니다.
- Cloud Storage> 버킷으로 이동합니다.
- 버킷 이름을 클릭합니다.
- 권한 탭으로 이동합니다.
- 액세스 권한 부여를 클릭합니다.
- 다음 구성 세부정보를 제공합니다.
- 주 구성원 추가: 서비스 계정 이메일을 입력합니다.
- 역할 할당: 스토리지 객체 관리자를 선택합니다.
- 저장을 클릭합니다.
게시/구독 주제 만들기
Cloud Scheduler가 게시하고 Cloud Run 함수가 구독할 Pub/Sub 주제를 만듭니다.
- GCP Console에서 Pub/Sub > 주제로 이동합니다.
- 주제 만들기를 클릭합니다.
- 다음 구성 세부정보를 제공합니다.
- 주제 ID:
sailpoint-iam-trigger를 입력합니다. - 다른 설정은 기본값으로 둡니다.
- 주제 ID:
- 만들기를 클릭합니다.
로그를 수집하는 Cloud Run 함수 만들기
Cloud Run 함수는 Cloud Scheduler의 Pub/Sub 메시지에 의해 트리거되어 SailPoint Identity Security Cloud API에서 로그를 가져오고 GCS에 기록합니다.
- GCP 콘솔에서 Cloud Run으로 이동합니다.
- 서비스 만들기를 클릭합니다.
- 함수를 선택합니다 (인라인 편집기를 사용하여 함수 만들기).
구성 섹션에서 다음 구성 세부정보를 제공합니다.
설정 값 서비스 이름 sailpoint-iam-collector리전 GCS 버킷과 일치하는 리전을 선택합니다 (예: us-central1).런타임 Python 3.12 이상 선택 트리거 (선택사항) 섹션에서 다음을 수행합니다.
- + 트리거 추가를 클릭합니다.
- Cloud Pub/Sub를 선택합니다.
- Cloud Pub/Sub 주제 선택에서 Pub/Sub 주제 (
sailpoint-iam-trigger)를 선택합니다. - 저장을 클릭합니다.
인증 섹션에서 다음을 구성합니다.
- 인증 필요를 선택합니다.
- ID 및 액세스 관리 (IAM)를 확인합니다.
아래로 스크롤하고 컨테이너, 네트워킹, 보안을 펼칩니다.
보안 탭으로 이동합니다.
- 서비스 계정: 서비스 계정 (
sailpoint-iam-collector-sa)을 선택합니다.
- 서비스 계정: 서비스 계정 (
컨테이너 탭으로 이동합니다.
- 변수 및 보안 비밀을 클릭합니다.
- 각 환경 변수에 대해 + 변수 추가를 클릭합니다.
변수 이름 예시 값 GCS_BUCKETsailpoint-iam-logsGCS_PREFIXsailpoint/iam/STATE_KEYsailpoint/iam/state.jsonWINDOW_SECONDS3600HTTP_TIMEOUT60MAX_RETRIES3USER_AGENTsailpoint-iam-to-gcs/1.0IDN_BASEhttps://tenant.api.identitynow.comIDN_CLIENT_IDyour-client-idIDN_CLIENT_SECRETyour-client-secretIDN_SCOPEsp:scopes:allPAGE_SIZE250MAX_PAGES20변수 및 보안 비밀 탭에서 요청까지 아래로 스크롤합니다.
- 요청 제한 시간:
600초 (10분)를 입력합니다.
- 요청 제한 시간:
컨테이너의 설정 탭으로 이동합니다.
- 리소스 섹션에서 다음을 수행합니다.
- 메모리: 512MiB 이상을 선택합니다.
- CPU: 1을 선택합니다.
- 완료를 클릭합니다.
- 리소스 섹션에서 다음을 수행합니다.
실행 환경까지 아래로 스크롤합니다.
- 기본을 선택합니다 (권장).
버전 확장 섹션에서 다음을 수행합니다.
- 최소 인스턴스 수:
0를 입력합니다. - 최대 인스턴스 수:
100을 입력합니다 (또는 예상 부하에 따라 조정).
- 최소 인스턴스 수:
만들기를 클릭합니다.
서비스가 생성될 때까지 기다립니다 (1~2분).
서비스가 생성되면 인라인 코드 편집기가 자동으로 열립니다.
함수 코드 추가
- 함수 진입점에 main을 입력합니다.
인라인 코드 편집기에서 다음 두 파일을 만듭니다.
- 첫 번째 파일: main.py:
import functions_framework from google.cloud import storage import json import os import urllib3 from datetime import datetime, timezone import time import uuid # Initialize HTTP client http = urllib3.PoolManager() # Initialize Storage client storage_client = storage.Client() # Get environment variables GCS_BUCKET = os.environ.get('GCS_BUCKET') GCS_PREFIX = os.environ.get('GCS_PREFIX', 'sailpoint/iam/') STATE_KEY = os.environ.get('STATE_KEY', 'sailpoint/iam/state.json') WINDOW_SEC = int(os.environ.get('WINDOW_SECONDS', '3600')) HTTP_TIMEOUT = int(os.environ.get('HTTP_TIMEOUT', '60')) IDN_BASE = os.environ.get('IDN_BASE') CLIENT_ID = os.environ.get('IDN_CLIENT_ID') CLIENT_SECRET = os.environ.get('IDN_CLIENT_SECRET') SCOPE = os.environ.get('IDN_SCOPE', 'sp:scopes:all') PAGE_SIZE = int(os.environ.get('PAGE_SIZE', '250')) MAX_PAGES = int(os.environ.get('MAX_PAGES', '20')) MAX_RETRIES = int(os.environ.get('MAX_RETRIES', '3')) USER_AGENT = os.environ.get('USER_AGENT', 'sailpoint-iam-to-gcs/1.0') def _load_state(bucket): """Load state from GCS.""" try: blob = bucket.blob(STATE_KEY) if blob.exists(): state_data = blob.download_as_text() return json.loads(state_data) except Exception as e: print(f'Warning: Could not load state: {str(e)}') return {} def _save_state(bucket, st): """Save state to GCS.""" try: blob = bucket.blob(STATE_KEY) blob.upload_from_string( json.dumps(st, separators=(',', ':')), content_type='application/json' ) except Exception as e: print(f'Warning: Could not save state: {str(e)}') def _iso(ts): """Convert timestamp to ISO format.""" return time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime(ts)) def _get_oauth_token(): """Get OAuth2 access token using Client Credentials flow.""" token_url = f"{IDN_BASE.rstrip('/')}/oauth/token" fields = { 'grant_type': 'client_credentials', 'client_id': CLIENT_ID, 'client_secret': CLIENT_SECRET, 'scope': SCOPE } headers = { 'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': USER_AGENT } response = http.request( 'POST', token_url, fields=fields, headers=headers, timeout=HTTP_TIMEOUT ) token_data = json.loads(response.data.decode('utf-8')) return token_data['access_token'] def _search_events(access_token, created_from, search_after=None): """Search for audit events using SailPoint's /v3/search API. IMPORTANT: SailPoint requires colons in ISO8601 timestamps to be escaped with backslashes. Example: 2024-01-15T10:30:00Z must be sent as 2024-01-15T10\\:30\\:00Z For more information, see: - https://developer.sailpoint.com/docs/api/standard-collection-parameters/ - https://developer.sailpoint.com/docs/api/v3/search-post/ """ search_url = f"{IDN_BASE.rstrip('/')}/v3/search" # Escape colons in timestamp for SailPoint search query escaped_timestamp = created_from.replace(':', '\\:') query_str = f'created:>={escaped_timestamp}' payload = { 'indices': ['events'], 'query': { 'query': query_str }, 'sort': ['created', '+id'], 'limit': PAGE_SIZE } if search_after: payload['searchAfter'] = search_after attempt = 0 while True: headers = { 'Content-Type': 'application/json', 'Accept': 'application/json', 'Authorization': f'Bearer {access_token}', 'User-Agent': USER_AGENT } try: response = http.request( 'POST', search_url, body=json.dumps(payload).encode('utf-8'), headers=headers, timeout=HTTP_TIMEOUT ) response_data = json.loads(response.data.decode('utf-8')) # Handle different response formats if isinstance(response_data, list): return response_data return response_data.get('results', response_data.get('data', [])) except Exception as e: attempt += 1 print(f'HTTP error on attempt {attempt}: {e}') if attempt > MAX_RETRIES: raise # Exponential backoff with jitter time.sleep(min(60, 2 ** attempt) + (time.time() % 1)) def _put_events_data(bucket, events, from_ts, to_ts, page_num): """Write events to GCS in JSONL format (one JSON object per line).""" # Create unique GCS key for events data ts_path = time.strftime('%Y/%m/%d', time.gmtime(to_ts)) uniq = f"{int(time.time() * 1e6)}_{uuid.uuid4().hex[:8]}" key = f"{GCS_PREFIX}{ts_path}/sailpoint_iam_{int(from_ts)}_{int(to_ts)}_p{page_num:03d}_{uniq}.jsonl" # Convert events list to JSONL format (one JSON object per line) jsonl_lines = [json.dumps(event, separators=(',', ':')) for event in events] jsonl_content = '\n'.join(jsonl_lines) blob = bucket.blob(key) blob.metadata = { 'source': 'sailpoint-iam', 'from_timestamp': str(int(from_ts)), 'to_timestamp': str(int(to_ts)), 'page_number': str(page_num), 'events_count': str(len(events)), 'format': 'jsonl' } blob.upload_from_string( jsonl_content, content_type='application/x-ndjson' ) return key def _get_item_id(item): """Extract ID from event item, trying multiple possible fields.""" for field in ('id', 'uuid', 'eventId', '_id'): if field in item and item[field]: return str(item[field]) return '' @functions_framework.cloud_event def main(cloud_event): """ Cloud Run function triggered by Pub/Sub to fetch SailPoint IAM logs and write to GCS. Args: cloud_event: CloudEvent object containing Pub/Sub message """ if not all([GCS_BUCKET, IDN_BASE, CLIENT_ID, CLIENT_SECRET]): print('Error: Missing required environment variables') return try: bucket = storage_client.bucket(GCS_BUCKET) st = _load_state(bucket) now = time.time() from_ts = float(st.get('last_to_ts') or (now - WINDOW_SEC)) to_ts = now # Get OAuth token access_token = _get_oauth_token() created_from = _iso(from_ts) print(f'Fetching SailPoint IAM events from: {created_from}') # Handle pagination state last_created = st.get('last_created') last_id = st.get('last_id') search_after = [last_created, last_id] if (last_created and last_id) else None pages = 0 total_events = 0 written_keys = [] newest_created = last_created or created_from newest_id = last_id or '' while pages < MAX_PAGES: events = _search_events(access_token, created_from, search_after) if not events: break # Write page to GCS in JSONL format key = _put_events_data(bucket, events, from_ts, to_ts, pages + 1) written_keys.append(key) total_events += len(events) # Update pagination state from last item last_event = events[-1] last_event_created = last_event.get('created') or last_event.get('metadata', {}).get('created') last_event_id = _get_item_id(last_event) if last_event_created: newest_created = last_event_created if last_event_id: newest_id = last_event_id search_after = [newest_created, newest_id] pages += 1 # If we got less than page size, we're done if len(events) < PAGE_SIZE: break print(f'Successfully retrieved {total_events} events across {pages} pages') # Save state for next run st['last_to_ts'] = to_ts st['last_created'] = newest_created st['last_id'] = newest_id st['last_successful_run'] = now _save_state(bucket, st) print(f'Wrote {len(written_keys)} files to GCS') except Exception as e: print(f'Error processing logs: {str(e)}') raise- 두 번째 파일: requirements.txt:
functions-framework==3.* google-cloud-storage==2.* urllib3>=2.0.0 ```배포를 클릭하여 함수를 저장하고 배포합니다.
배포가 완료될 때까지 기다립니다 (2~3분).
Cloud Scheduler 작업 만들기
Cloud Scheduler는 일정 간격으로 Pub/Sub 주제에 메시지를 게시하여 Cloud Run 함수를 트리거합니다.
- GCP Console에서 Cloud Scheduler로 이동합니다.
- 작업 만들기를 클릭합니다.
다음 구성 세부정보를 제공합니다.
설정 값 이름 sailpoint-iam-collector-hourly리전 Cloud Run 함수와 동일한 리전 선택 주파수 0 * * * *(매시간 정각)시간대 시간대 선택 (UTC 권장) 타겟 유형 Pub/Sub 주제 Pub/Sub 주제 ( sailpoint-iam-trigger)를 선택합니다.메일 본문 {}(빈 JSON 객체)만들기를 클릭합니다.
일정 빈도 옵션
로그 볼륨 및 지연 시간 요구사항에 따라 빈도를 선택합니다.
빈도 크론 표현식 사용 사례 5분마다 */5 * * * *대용량, 저지연 15분마다 */15 * * * *검색량 보통 1시간마다 0 * * * *일반(권장) 6시간마다 0 */6 * * *양이 적은 일괄 처리 매일 0 0 * * *이전 데이터 수집
스케줄러 작업 테스트
- Cloud Scheduler 콘솔에서 작업을 찾습니다.
- 강제 실행을 클릭하여 수동으로 트리거합니다.
- 몇 초간 기다린 후 Cloud Run > 서비스 > sailpoint-iam-collector > 로그로 이동합니다.
- 함수가 성공적으로 실행되었는지 확인합니다.
- GCS 버킷을 확인하여 로그가 작성되었는지 확인합니다.
Google SecOps 서비스 계정 가져오기
Google SecOps는 고유한 서비스 계정을 사용하여 GCS 버킷에서 데이터를 읽습니다. 이 서비스 계정에 버킷에 대한 액세스 권한을 부여해야 합니다.
서비스 계정 이메일 가져오기
- SIEM 설정> 피드로 이동합니다.
- 새 피드 추가를 클릭합니다.
- 단일 피드 구성을 클릭합니다.
- 피드 이름 필드에 피드 이름을 입력합니다(예:
SailPoint IAM logs). - 소스 유형으로 Google Cloud Storage V2를 선택합니다.
- 로그 유형으로 SailPoint IAM을 선택합니다.
서비스 계정 가져오기를 클릭합니다. 고유한 서비스 계정 이메일이 표시됩니다. 예를 들면 다음과 같습니다.
chronicle-12345678@chronicle-gcp-prod.iam.gserviceaccount.com다음 단계에서 사용할 수 있도록 이 이메일 주소를 복사합니다.
Google SecOps 서비스 계정에 IAM 권한 부여
Google SecOps 서비스 계정에는 GCS 버킷에 대한 스토리지 객체 뷰어 역할이 필요합니다.
- Cloud Storage> 버킷으로 이동합니다.
- 버킷 이름을 클릭합니다.
- 권한 탭으로 이동합니다.
- 액세스 권한 부여를 클릭합니다.
- 다음 구성 세부정보를 제공합니다.
- 주 구성원 추가: Google SecOps 서비스 계정 이메일을 붙여넣습니다.
- 역할 할당: 스토리지 객체 뷰어를 선택합니다.
저장을 클릭합니다.
SailPoint IAM 로그를 수집하도록 Google SecOps에서 피드 구성
- SIEM 설정> 피드로 이동합니다.
- 새 피드 추가를 클릭합니다.
- 단일 피드 구성을 클릭합니다.
- 피드 이름 필드에 피드 이름을 입력합니다(예:
SailPoint IAM logs). - 소스 유형으로 Google Cloud Storage V2를 선택합니다.
- 로그 유형으로 SailPoint IAM을 선택합니다.
- 다음을 클릭합니다.
다음 입력 매개변수의 값을 지정합니다.
스토리지 버킷 URL: 다음 접두사 경로를 사용하여 GCS 버킷 URI를 입력합니다.
gs://sailpoint-iam-logs/sailpoint/iam/다음과 같이 바꿉니다.
sailpoint-iam-logs: GCS 버킷 이름입니다.sailpoint/iam/: 로그가 저장되는 선택적 접두사/폴더 경로입니다 (루트의 경우 비워 둠).
예:
- 루트 버킷:
gs://company-logs/ - 접두사 사용:
gs://company-logs/sailpoint-logs/ - 하위 폴더 사용:
gs://company-logs/sailpoint/iam/
- 루트 버킷:
소스 삭제 옵션: 환경설정에 따라 삭제 옵션을 선택합니다.
- 삭제 안함: 전송 후 파일을 삭제하지 않습니다 (테스트에 권장).
- 전송된 파일 삭제: 전송이 완료되면 파일을 삭제합니다.
전송된 파일 및 빈 디렉터리 삭제: 전송이 완료되면 파일과 빈 디렉터리를 삭제합니다.
최대 파일 기간: 지난 일수 동안 수정된 파일을 포함합니다. 기본값은 180일입니다.
애셋 네임스페이스: 애셋 네임스페이스입니다.
수집 라벨: 이 피드의 이벤트에 적용할 라벨입니다.
다음을 클릭합니다.
확정 화면에서 새 피드 구성을 검토한 다음 제출을 클릭합니다.
UDM 매핑 테이블
| 로그 필드 | UDM 매핑 | 로직 |
|---|---|---|
| action | metadata.description | 원시 로그의 작업 필드 값입니다. |
| actor.name | principal.user.user_display_name | 원시 로그의 actor.name 필드 값입니다. |
| attributes.accountName | principal.user.group_identifiers | 원시 로그의 attributes.accountName 필드 값입니다. |
| attributes.appId | target.asset_id | 'App ID: '와 원시 로그의 attributes.appId 필드 값을 연결한 값입니다. |
| attributes.attributeName | additional.fields[0].value.string_value | 추가.fields 객체 내에 배치된 원시 로그의 attributes.attributeName 필드 값입니다. 키는 '속성 이름'으로 설정됩니다. |
| attributes.attributeValue | additional.fields[1].value.string_value | 추가.fields 객체 내에 배치된 원시 로그의 attributes.attributeValue 필드 값입니다. 키는 '속성 값'으로 설정됩니다. |
| attributes.cloudAppName | target.application | 원시 로그의 attributes.cloudAppName 필드 값입니다. |
| attributes.hostName | target.hostname, target.asset.hostname | 원시 로그의 attributes.hostName 필드 값입니다. |
| attributes.interface | additional.fields[2].value.string_value | 추가.fields 객체 내에 배치된 원시 로그의 attributes.interface 필드 값입니다. 키가 'Interface'로 설정됩니다. |
| attributes.operation | security_result.action_details | 원시 로그의 attributes.operation 필드 값입니다. |
| attributes.previousValue | additional.fields[3].value.string_value | 추가.fields 객체 내에 배치된 원시 로그의 attributes.previousValue 필드 값입니다. 키가 '이전 값'으로 설정됩니다. |
| attributes.provisioningResult | security_result.detection_fields.value | 원시 로그의 attributes.provisioningResult 필드 값으로, security_result.detection_fields 객체 내에 배치됩니다. 키는 '프로비저닝 결과'로 설정됩니다. |
| attributes.sourceId | principal.labels[0].value | 원시 로그의 attributes.sourceId 필드 값으로, principal.labels 객체 내에 배치됩니다. 키가 '소스 ID'로 설정됩니다. |
| attributes.sourceName | principal.labels[1].value | 원시 로그의 attributes.sourceName 필드 값으로, principal.labels 객체 내에 배치됩니다. 키가 '소스 이름'으로 설정되어 있습니다. |
| auditClassName | metadata.product_event_type | 원시 로그의 auditClassName 필드 값입니다. |
| 생성됨 | metadata.event_timestamp.seconds, metadata.event_timestamp.nanos | 원시 로그에서 생성된 필드의 값입니다. instant.epochSecond가 없는 경우 타임스탬프로 변환됩니다. |
| id | metadata.product_log_id | 원시 로그의 ID 필드 값입니다. |
| instant.epochSecond | metadata.event_timestamp.seconds | 타임스탬프에 사용되는 원시 로그의 instant.epochSecond 필드 값입니다. |
| ipAddress | principal.asset.ip, principal.ip | 원시 로그의 ipAddress 필드 값입니다. |
| 인터페이스 | additional.fields[0].value.string_value | 추가.fields 객체 내에 배치된 원시 로그의 인터페이스 필드 값입니다. 키가 'interface'로 설정됩니다. |
| loggerName | intermediary.application | 원시 로그의 loggerName 필드 값입니다. |
| 메시지 | metadata.description, security_result.description | 메타데이터 및 security_result에 설명을 설정하고 XML 콘텐츠를 추출하는 등 다양한 용도로 사용됩니다. |
| 이름 | security_result.description | 원시 로그의 이름 필드 값입니다. |
| 작업 | target.resource.attribute.labels[0].value, metadata.product_event_type | 원시 로그의 작업 필드 값으로, target.resource.attribute.labels 객체 내에 배치됩니다. 키는 'operation'으로 설정됩니다. metadata.product_event_type에도 사용됩니다. |
| org | principal.administrative_domain | 원시 로그의 org 필드 값입니다. |
| 포드 | principal.location.name | 원시 로그의 포드 필드 값입니다. |
| referenceClass | additional.fields[1].value.string_value | 추가.fields 객체 내에 배치된 원시 로그의 referenceClass 필드 값입니다. 키는 'referenceClass'로 설정됩니다. |
| referenceId | additional.fields[2].value.string_value | 추가.fields 객체 내에 배치된 원시 로그의 referenceId 필드 값입니다. 키는 'referenceId'로 설정됩니다. |
| sailPointObjectName | additional.fields[3].value.string_value | 추가.fields 객체 내에 배치된 원시 로그의 sailPointObjectName 필드 값입니다. 키는 'sailPointObjectName'으로 설정됩니다. |
| serverHost | principal.hostname, principal.asset.hostname | 원시 로그의 serverHost 필드 값입니다. |
| 스택 | additional.fields[4].value.string_value | 추가.fields 객체 내에 배치된 원시 로그의 스택 필드 값입니다. 키가 'Stack'으로 설정됩니다. |
| 상태 | security_result.severity_details | 원시 로그의 상태 필드 값입니다. |
| target | additional.fields[4].value.string_value | 추가.fields 객체 내에 배치된 원시 로그의 타겟 필드 값입니다. 키가 'target'으로 설정됩니다. |
| target.name | principal.user.userid | 원시 로그의 target.name 필드 값입니다. |
| technicalName | security_result.summary | 원시 로그의 technicalName 필드 값입니다. |
| thrown.cause.message | xml_body, detailed_message | XML 콘텐츠를 추출하는 데 사용되는 원시 로그의 thrown.cause.message 필드 값입니다. |
| thrown.message | xml_body, detailed_message | XML 콘텐츠를 추출하는 데 사용되는 원시 로그의 thrown.message 필드 값입니다. |
| trackingNumber | additional.fields[5].value.string_value | 추가.fields 객체 내에 배치된 원시 로그의 trackingNumber 필드 값입니다. 키가 '운송장 번호'로 설정됩니다. |
| 유형 | metadata.product_event_type | 원시 로그의 유형 필드 값입니다. |
| _version | metadata.product_version | 원시 로그의 _version 필드 값입니다. |
| 해당 사항 없음 | metadata.event_timestamp | instant.epochSecond 또는 created 필드에서 파생됩니다. |
| 해당 사항 없음 | metadata.event_type | has_principal_user, has_target_application, technicalName, action 등 다양한 필드를 기반으로 파서 로직에 의해 결정됩니다. 기본값은 'GENERIC_EVENT'입니다. |
| 해당 사항 없음 | metadata.log_type | 'SAILPOINT_IAM'으로 설정합니다. |
| 해당 사항 없음 | metadata.product_name | 'IAM'으로 설정합니다. |
| 해당 사항 없음 | metadata.vendor_name | 'SAILPOINT'로 설정합니다. |
| 해당 사항 없음 | extensions.auth.type | 특정 조건에서 'AUTHTYPE_UNSPECIFIED'로 설정됩니다. |
| 해당 사항 없음 | target.resource.attribute.labels[0].key | 'operation'으로 설정합니다. |
도움이 더 필요한가요? 커뮤니티 회원 및 Google SecOps 전문가에게 문의하여 답변을 받으세요.