ServiceNow Security 로그 수집
이 문서에서는 비즈니스 규칙을 통해 구성된 아웃바운드 웹훅을 사용하여 ServiceNow 보안 이벤트를 Google Security Operations로 내보내는 방법을 설명합니다. 수집 라벨은 원시 로그 데이터를 구조화된 UDM 형식으로 정규화하는 파서를 식별합니다.
통합 아키텍처
이 통합은 ServiceNow 비즈니스 규칙을 사용하여 보안 이벤트를 Google SecOps에 실시간으로 푸시합니다.
ServiceNow Security Tables ↓ (Business Rules trigger on insert/update) ServiceNow RESTMessageV2 API ↓ (HTTP POST) Google Security Operations Webhook Endpoint ↓ (Parser: SERVICENOW_SECURITY) Unified Data Model (UDM)
통합 특성:
- 이벤트 기반 푸시: 생성되거나 업데이트될 때 즉시 전송되는 이벤트
- 실시간: 짧은 지연 시간 (초)
- 선택적 내보내기: 내보낼 테이블 및 이벤트 구성
- 대량 내보내기 아님: 이전 데이터를 전송하지 않음
시작하기 전에
다음 기본 요건이 충족되었는지 확인합니다.
- Google SecOps 인스턴스
- 보안 사고 대응 (SIR) 플러그인이 설치된 ServiceNow 인스턴스
- 다음 역할이 있는 ServiceNow 사용자 계정:
admin또는sn_si.admin(비즈니스 규칙 만들기)- 시스템 정의 > 비즈니스 규칙에 대한 액세스
- 시스템 정의> 스크립트 포함에 대한 액세스
- Google Google Cloud 콘솔에 대한 권한 있는 액세스 (API 키 생성용)
내보낼 ServiceNow Security 테이블
다음 표에는 SIEM 분석을 위한 보안 관련 데이터가 포함되어 있습니다.
| 표 | API 이름 | 설명 | 우선순위 |
|---|---|---|---|
| 보안 사고 | sn_si_incident |
보안 사고, 조사 | 높음 |
| 모니터링 가능성 | sn_si_observable |
IOC: IP 주소, 도메인, 파일 해시 | 높음 |
| 시스템 로그 | syslog |
인증 이벤트, 로그인 실패 | MEDIUM |
| 감사 | sys_audit |
필드 수준 변경사항, 권한 수정 | MEDIUM |
| 사용자 역할 할당 | sys_user_has_role |
역할 부여/취소 | LOW |
| 보안 발견 항목 | sn_si_finding |
보안 감지 및 발견 항목 | LOW |
이 가이드에서는 우선순위가 '높음'인 테이블의 비즈니스 규칙 예를 제공합니다. 동일한 패턴을 사용하여 통합을 추가 테이블로 확장할 수 있습니다.
ServiceNow Security 이벤트를 수집하도록 Google SecOps에서 피드 구성
웹훅 피드 설정
- SIEM 설정> 피드로 이동합니다.
- 새 피드 추가를 클릭합니다.
- 다음 페이지에서 단일 피드 구성을 클릭합니다.
- 피드 이름 필드에 피드 이름을 입력합니다(예:
ServiceNow Security Events). - 소스 유형으로 웹훅을 선택합니다.
- 로그 유형으로 ServiceNow Security를 선택합니다.
- 다음을 클릭합니다.
피드 매개변수 구성
다음 입력 매개변수의 값을 지정합니다.
- 분할 구분 기호:
\n를 입력하여 로그 줄을 구분합니다. - 애셋 네임스페이스: 애셋 네임스페이스입니다.
- 수집 라벨: 이 피드의 모든 이벤트에 적용되는 라벨입니다.
- 분할 구분 기호:
다음을 클릭합니다.
확정 화면에서 새 피드 구성을 검토한 다음 제출을 클릭합니다.
보안 비밀 키 생성 및 엔드포인트 URL 검색
- 보안 비밀 키 생성을 클릭하여 이 피드를 인증하기 위한 보안 비밀 키를 생성합니다.
보안 비밀 키를 복사하여 안전한 위치에 저장합니다.
세부정보 탭으로 이동합니다.
엔드포인트 정보 필드에서 피드 엔드포인트 URL을 복사합니다.
- 엔드포인트 URL의 예:
https://malachiteingestion-pa.googleapis.com/v2/unstructured/projects/PROJECT_ID/locations/LOCATION/instances/INSTANCE_ID/logTypes/SERVICENOW_SECURITY:import
- 엔드포인트 URL의 예:
완료를 클릭합니다.
인증을 위한 API 키 만들기
- Google Cloud 콘솔 사용자 인증 정보 페이지로 이동합니다.
- 사용자 인증 정보 만들기를 클릭한 후 API 키를 선택합니다.
- 키 제한을 클릭합니다.
- API 제한사항에서 다음을 수행합니다.
- 키 제한을 선택합니다.
- Google SecOps API (Chronicle API)를 선택합니다.
- 저장을 클릭합니다.
- API 키를 복사하여 안전한 위치에 저장합니다.
ServiceNow 통합 사용자 인증 정보 구성
안전한 액세스를 위해 Google SecOps 사용자 인증 정보를 ServiceNow 시스템 속성으로 저장합니다.
- ServiceNow에서 System Properties(시스템 속성) > sys_properties.list로 이동합니다.
- New(새로 만들기)를 클릭합니다.
- 첫 번째 속성을 만듭니다.
- 이름:
x_chronicle.endpoint_url - 값: 이전 단계에서 복사한 피드 엔드포인트 URL을 붙여넣습니다.
- 유형:
string
- 이름:
- 제출을 클릭합니다.
- 새로 만들기를 클릭하여 두 번째 속성을 만듭니다.
- 이름:
x_chronicle.api_key - 값: Google Cloud API 키를 붙여넣습니다.
- 유형:
password(값을 암호화함)
- 이름:
- 제출을 클릭합니다.
- 새로 만들기를 클릭하여 세 번째 속성을 만듭니다.
- 이름:
x_chronicle.secret_key - 값: Google SecOps 피드 보안 비밀 키를 붙여넣습니다.
- 유형:
password(값을 암호화함)
- 이름:
- 제출을 클릭합니다.
재사용 가능한 웹훅 유틸리티 스크립트 포함 만들기
이 스크립트 포함은 비즈니스 규칙에서 Google SecOps로 이벤트를 전송하기 위한 재사용 가능한 함수를 제공합니다.
- 시스템 정의 > 스크립트 포함으로 이동합니다.
- New(새로 만들기)를 클릭합니다.
- 다음 구성 세부정보를 제공합니다.
- 이름:
ChronicleWebhookUtil - API 이름:
ChronicleWebhookUtil - 클라이언트 호출 가능: 선택되지 않음
- 활성: 선택됨
- 이름:
스크립트 필드에 다음 코드를 입력합니다.
var ChronicleWebhookUtil = Class.create(); ChronicleWebhookUtil.prototype = { initialize: function() { // Read credentials from System Properties this.endpointURL = gs.getProperty('x_chronicle.endpoint_url'); this.apiKey = gs.getProperty('x_chronicle.api_key'); this.secretKey = gs.getProperty('x_chronicle.secret_key'); }, sendEvent: function(eventData, eventType) { try { // Validate credentials if (!this.endpointURL || !this.apiKey || !this.secretKey) { gs.error('[Chronicle] Missing configuration. Check System Properties: x_chronicle.*'); return false; } // Prepare payload var payload = { event_type: eventType, timestamp: new GlideDateTime().getDisplayValue(), data: eventData, source: "ServiceNow", source_instance: gs.getProperty('instance_name') }; // Create REST message var request = new sn_ws.RESTMessageV2(); request.setEndpoint(this.endpointURL + '?key=' + this.apiKey); request.setHttpMethod('POST'); // Set headers request.setRequestHeader('Content-Type', 'application/json'); request.setRequestHeader('x-chronicle-auth', this.secretKey); // Set request body request.setRequestBody(JSON.stringify(payload)); // Execute request var response = request.execute(); var statusCode = response.getStatusCode(); var responseBody = response.getBody(); // Check response if (statusCode == 200 || statusCode == 201 || statusCode == 204) { gs.info('[Chronicle] Event sent successfully: ' + eventType + ' | Status: ' + statusCode); return true; } else { gs.error('[Chronicle] Failed to send event: ' + eventType + ' | Status: ' + statusCode + ' | Response: ' + responseBody); return false; } } catch (ex) { gs.error('[Chronicle] Exception sending event: ' + ex.message); return false; } }, type: 'ChronicleWebhookUtil' };제출을 클릭합니다.
이벤트 내보내기를 위한 비즈니스 규칙 만들기
비즈니스 규칙은 ServiceNow 테이블에서 레코드가 생성되거나 업데이트될 때 자동으로 트리거됩니다. Google SecOps로 내보낼 각 테이블에 대해 비즈니스 규칙을 만듭니다.
비즈니스 규칙: 보안 사고
이 비즈니스 규칙은 보안 사고 이벤트를 Google SecOps로 내보냅니다.
- 시스템 정의 > 비즈니스 규칙으로 이동합니다.
- New(새로 만들기)를 클릭합니다.
다음 구성 세부정보를 제공합니다.
실행 시점:
필드 값 이름 Chronicle - Export Security Incident표 Security Incident [sn_si_incident]활성 선택됨 고급 선택됨 시기 after삽입 선택됨 업데이트 선택됨 삭제 선택사항 (삭제를 추적하려면 선택) Order 100고급 탭을 클릭하고 스크립트 필드로 이동하여 다음 코드를 입력합니다.
(function executeRule(current, previous /*null when async*/) { // Extract incident data var incidentData = { sys_id: current.getValue('sys_id'), number: current.getValue('number'), short_description: current.getValue('short_description'), description: current.getValue('description'), state: current.getDisplayValue('state'), priority: current.getDisplayValue('priority'), severity: current.getDisplayValue('severity'), risk_score: current.getValue('risk_score'), category: current.getDisplayValue('category'), subcategory: current.getDisplayValue('subcategory'), assigned_to: current.getDisplayValue('assigned_to'), assignment_group: current.getDisplayValue('assignment_group'), caller: current.getDisplayValue('caller'), affected_user: current.getDisplayValue('affected_user'), opened_at: current.getValue('opened_at'), closed_at: current.getValue('closed_at'), resolved_at: current.getValue('resolved_at'), sys_created_on: current.getValue('sys_created_on'), sys_updated_on: current.getValue('sys_updated_on'), sys_created_by: current.getValue('sys_created_by'), sys_updated_by: current.getValue('sys_updated_by'), work_notes: current.getValue('work_notes'), close_notes: current.getValue('close_notes') }; // Send to Chronicle var chronicleUtil = new ChronicleWebhookUtil(); chronicleUtil.sendEvent(incidentData, 'security_incident'); })(current, previous);제출을 클릭합니다.
비즈니스 규칙: 관찰 가능 항목 (IOC)
이 비즈니스 규칙은 관측 가능한 데이터 (IP 주소, 도메인, 파일 해시)를 Google SecOps로 내보냅니다.
- 시스템 정의 > 비즈니스 규칙으로 이동합니다.
- New(새로 만들기)를 클릭합니다.
다음 구성 세부정보를 제공합니다.
필드 값 이름 Chronicle - Export Observable표 Observable [sn_si_observable]활성 선택됨 고급 선택됨 시기 after삽입 선택됨 업데이트 선택됨 Order 100고급 탭을 클릭하고 스크립트 필드로 이동하여 다음 코드를 입력합니다.
(function executeRule(current, previous) { var observableData = { sys_id: current.getValue('sys_id'), value: current.getValue('value'), type: current.getDisplayValue('type'), finding: current.getDisplayValue('finding'), sighting_count: current.getValue('sighting_count'), notes: current.getValue('notes'), security_tags: current.getValue('security_tags'), mitre_technique: current.getDisplayValue('mitre_technique'), mitre_tactic: current.getDisplayValue('mitre_tactic'), mitre_malware: current.getDisplayValue('mitre_malware'), sys_created_on: current.getValue('sys_created_on'), sys_created_by: current.getValue('sys_created_by') }; var chronicleUtil = new ChronicleWebhookUtil(); chronicleUtil.sendEvent(observableData, 'observable'); })(current, previous);제출을 클릭합니다.
비즈니스 규칙: 시스템 로그인 이벤트
이 비즈니스 규칙은 인증 및 로그인 이벤트를 Google SecOps로 내보냅니다.
- 시스템 정의 > 비즈니스 규칙으로 이동합니다.
- New(새로 만들기)를 클릭합니다.
다음 구성 세부정보를 제공합니다.
필드 값 이름 Chronicle - Export System Log표 System Log [syslog]활성 선택됨 고급 선택됨 시기 after삽입 선택됨 Order 100조건 current.level == "error" || current.source.indexOf("login") != -1고급 탭을 클릭하고 스크립트 필드로 이동하여 다음 코드를 입력합니다.
(function executeRule(current, previous) { var logData = { sys_id: current.getValue('sys_id'), level: current.getValue('level'), source: current.getValue('source'), message: current.getValue('message'), sys_created_on: current.getValue('sys_created_on'), sys_created_by: current.getValue('sys_created_by') }; var chronicleUtil = new ChronicleWebhookUtil(); chronicleUtil.sendEvent(logData, 'system_log'); })(current, previous);제출을 클릭합니다.
비즈니스 규칙: 감사 추적 (권한 변경)
이 비즈니스 규칙은 감사 추적 목적으로 필드 수준 변경사항을 내보냅니다.
- 시스템 정의 > 비즈니스 규칙으로 이동합니다.
- New(새로 만들기)를 클릭합니다.
다음 구성 세부정보를 제공합니다.
필드 값 이름 Chronicle - Export Audit Changes표 Audit [sys_audit]활성 선택됨 고급 선택됨 시기 after삽입 선택됨 Order 100조건 다음 스크립트를 참고하세요. 조건 (중요한 변경사항만 필터링):
```javascript current.tablename == 'sys_user_has_role' || current.tablename == 'sys_user_group_member' || current.tablename == 'sn_si_incident' || current.fieldname == 'active' || current.fieldname == 'locked_out' ```고급 탭을 클릭하고 스크립트 필드로 이동하여 다음 코드를 입력합니다.
(function executeRule(current, previous) { var auditData = { sys_id: current.getValue('sys_id'), tablename: current.getValue('tablename'), documentkey: current.getValue('documentkey'), fieldname: current.getValue('fieldname'), oldvalue: current.getValue('oldvalue'), newvalue: current.getValue('newvalue'), user: current.getDisplayValue('user'), reason: current.getValue('reason'), sys_created_on: current.getValue('sys_created_on') }; var chronicleUtil = new ChronicleWebhookUtil(); chronicleUtil.sendEvent(auditData, 'audit_change'); })(current, previous);제출을 클릭합니다.
선택사항: 내보낼 추가 테이블
사용자 역할 할당 변경
보안 감사를 위해 역할 부여 및 취소를 내보냅니다.
sys_user_has_role테이블에 비즈니스 규칙을 만듭니다.(function executeRule(current, previous) { var roleData = { sys_id: current.getValue('sys_id'), user: current.getDisplayValue('user'), role: current.getDisplayValue('role'), granted_by: current.getDisplayValue('granted_by'), state: current.getValue('state'), sys_created_on: current.getValue('sys_created_on') }; var chronicleUtil = new ChronicleWebhookUtil(); chronicleUtil.sendEvent(roleData, 'role_assignment'); })(current, previous);
보안 발견 항목
보안 감지 및 발견 항목을 내보냅니다.
sn_si_finding테이블에 비즈니스 규칙을 만듭니다.(function executeRule(current, previous) { var findingData = { sys_id: current.getValue('sys_id'), finding: current.getValue('finding'), confidence: current.getValue('confidence'), severity: current.getDisplayValue('severity'), observable: current.getDisplayValue('observable'), sys_created_on: current.getValue('sys_created_on') }; var chronicleUtil = new ChronicleWebhookUtil(); chronicleUtil.sendEvent(findingData, 'finding'); })(current, previous);
Google SecOps 피드에 대한 자세한 내용은 Google SecOps 피드 문서를 참고하세요. 각 피드 유형의 요구사항은 유형별 피드 구성을 참고하세요.
피드를 만들 때 문제가 발생하면 Google SecOps 지원팀에 문의하세요.
UDM 매핑 테이블
| ServiceNow 필드 | UDM 매핑 | 논리 |
|---|---|---|
number |
metadata.product_event_type |
문제 또는 이벤트 번호 |
short_description |
security_result.summary |
보안 이벤트에 대한 간단한 설명 |
severity |
security_result.severity |
이벤트 심각도 수준 |
priority |
security_result.priority |
이벤트 우선순위 |
caller |
principal.user.userid |
이벤트를 신고하거나 트리거한 사용자 |
affected_user |
target.user.userid |
보안 이벤트의 영향을 받은 사용자 |
assigned_to |
security_result.action_details |
인시던트에 할당된 분석가 |
sys_created_on |
metadata.event_timestamp |
이벤트 생성 타임스탬프 |
value (관찰 가능) |
network.ip 또는 network.dns.questions.name |
관측 가능한 값 (IP, 도메인, 해시) |
type (관찰 가능) |
security_result.detection_fields.value |
관찰 가능한 유형 (IP 주소, 도메인, 파일 해시) |
도움이 더 필요하신가요? 커뮤니티 회원 및 Google SecOps 전문가에게 문의하여 답변을 받으세요.