Workday HCM 로그 수집
이 문서에서는 서드 파티 API를 사용하여 피드를 설정하여 Workday HCM 로그를 Google Security Operations에 인그레스하는 방법을 설명합니다.
파서는 JSON 형식 로그에서 Workday HCM 사용자 데이터를 추출합니다. 필드 이름 바꾸기, 중첩된 객체 병합, 날짜 파싱, 사용자 속성, 고용 세부정보, 조직 구조의 UDM 필드 채우기 등 다양한 데이터 변환을 처리합니다.
시작하기 전에
다음 기본 요건이 충족되었는지 확인합니다.
- Google SecOps 인스턴스입니다.
- 보안 관리자 또는 이에 상응하는 권한으로 Workday에 대한 권한 액세스
Workday API 인증 구성
통합 시스템 사용자 (ISU) 만들기
- 관리자 권한으로 Workday에 로그인합니다.
- 검색창에 통합 시스템 사용자 만들기를 입력하고 작업을 선택합니다.
- 사용자 이름 (예:
ISU_SecOps_HCM)을 입력합니다. - 비밀번호를 설정합니다.
- ISU가 시간 초과되지 않도록 세션 만료 시간(분)을
0로 설정합니다. - UI 세션 허용 안 함을 사용 설정하여 UI 로그인을 제한함으로써 보안을 강화합니다.
- 비밀번호 규칙 유지 작업으로 이동합니다.
- 통합 시스템 사용자를 비밀번호 만료에서 제외된 시스템 사용자 필드에 추가합니다.
통합 보안 그룹 만들기
- 검색창에 보안 그룹 만들기를 입력하고 작업을 선택합니다.
- Type of Tenanted Security Group(테넌트 보안 그룹 유형) 필드를 찾아 Integration System Security Group (Unconstrained)(통합 시스템 보안 그룹(제약 없음))을 선택합니다.
- 보안 그룹의 이름을 입력합니다 (예:
ISG_SecOps_HCM). - 확인을 클릭합니다.
- 새로 만든 보안 그룹의 수정을 클릭합니다.
- 이전 단계의 통합 시스템 사용자를 보안 그룹에 할당합니다.
- 완료를 클릭합니다.
보안 그룹에 도메인 액세스 권한 부여
Google SecOps 피드는 4개의 Workday REST API 엔드포인트에서 데이터를 가져옵니다. 각 엔드포인트에는 통합 보안 그룹에 부여된 특정 도메인 보안 정책 권한이 필요합니다.
- 검색창에 Maintain Permissions for Security Group(보안 그룹에 대한 권한 관리)을 입력하고 작업을 선택합니다.
- 소스 보안 그룹 목록에서 생성한 보안 그룹 (예:
ISG_SecOps_HCM)을 선택합니다. - 확인을 클릭합니다.
- 도메인 보안 정책 권한으로 이동합니다.
다음 각 도메인에 GET 액세스를 추가합니다.
API 엔드포인트 필수 도메인 보안 정책 /workers- 작업자 목록, 프로필, 현재 인력Worker Data: Public Worker Reports,Worker Data: Current Staffing Information,Person Data: Work Contact Information/workers/{id}/timeOffEntries- 휴가 잔액Worker Data: Time Off (Time Off Balances),Worker Data: Time Off (Time Off Balances Manager View)/workers/{id}/history- 작업자 채용 기록Worker Data: Current Staffing Information/supervisoryOrganizations- 조직 구조Worker Data: Organization Information확인을 클릭합니다.
완료를 클릭하여 변경사항을 저장합니다.
보안 정책 변경사항 활성화
- 검색창에 보류 중인 보안 정책 변경사항 활성화를 입력하고 작업을 선택합니다.
- 댓글 필드에 변경 사유를 입력합니다 (예:
Granting API access for Google SecOps HCM integration). - 확인을 클릭합니다.
- 확인을 선택한 다음 확인을 클릭합니다.
통합을 위한 API 클라이언트 등록
- 검색창에 Register API Client for Integrations를 입력하고 선택합니다.
- 만들기를 클릭합니다.
다음 구성 세부정보를 제공합니다.
- 클라이언트 이름: 이름을 입력합니다 (예:
Google SecOps HCM Client). - 시스템 사용자: 생성한 통합 시스템 사용자를 선택합니다 (예:
ISU_SecOps_HCM). 범위: 다음 범위를 선택합니다.
범위 필수 인력 /workers및/workers/{id}/history엔드포인트연락처 정보 /workers에서 반환된 직장 이메일 및 전화 필드 (UDM 상관관계에 사용됨)휴가 및 휴직 엔드포인트 /workers/{id}/timeOffEntries개조직 및 역할 엔드포인트 /supervisoryOrganizations개테넌트 구성 불가능 모든 OAuth 2.0 API 클라이언트 (시스템 수준 통합 및 토큰 순환)
- 클라이언트 이름: 이름을 입력합니다 (예:
저장을 클릭합니다.
확인을 클릭합니다.
클라이언트 ID와 클라이언트 보안 비밀번호를 즉시 복사하여 저장합니다.
OAuth 2.0 갱신 토큰 생성
- 검색창에 통합의 새로고침 토큰 관리를 입력하고 선택합니다.
- 새로고침 토큰 생성을 클릭합니다.
- Workday 계정 필드에서 통합 시스템 사용자를 검색하여 선택합니다 (예:
ISU_SecOps_HCM). - 생성한 API 클라이언트를 선택하고 확인을 클릭합니다.
- Refresh Token을 복사하여 저장합니다.
API 엔드포인트 URL 가져오기
- 검색창에 View API Clients를 입력하고 선택합니다.
- 통합용 API 클라이언트에서 생성한 클라이언트 (예:
Google SecOps HCM Client)를 찾습니다. 다음 세부정보를 복사하여 저장합니다.
- 토큰 엔드포인트: 액세스 토큰을 가져오는 URL입니다 (예:
https://wd2-impl-services1.workday.com/ccx/oauth2/YOUR_TENANT/token). - Workday REST API 엔드포인트: API 호출의 기준 URL (예:
https://wd2-impl-services1.workday.com/ccx/api/v1/YOUR_TENANT)입니다.
- 토큰 엔드포인트: 액세스 토큰을 가져오는 URL입니다 (예:
OAuth 액세스 토큰 생성
curl 또는 유사한 HTTP 클라이언트를 사용하여 토큰 엔드포인트에 POST 요청을 보냅니다.
curl -X POST "https://HOSTNAME/ccx/oauth2/TENANT/token" \
-d "grant_type=refresh_token" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "refresh_token=YOUR_REFRESH_TOKEN"
그러면 액세스 토큰 (예: "access_token": "abcd1234")이 반환됩니다. 액세스 토큰을 복사하여 저장합니다.
API 액세스 확인
피드를 구성하기 전에 ISU에 주요 엔드포인트에 필요한 권한이 있는지 확인합니다. 변수를 실제 값으로 바꿉니다.
TOKEN="your-access-token"
HOST="your-workday-host"
TENANT="your-tenant"
# Test 1: Workers (should return worker list)
curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer $TOKEN" \
"https://$HOST/ccx/api/v1/$TENANT/workers?limit=1"
# Test 2: Time off entries (replace WORKER_ID with an ID from Test 1)
curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer $TOKEN" \
"https://$HOST/ccx/api/v1/$TENANT/workers/WORKER_ID/timeOffEntries"
# Test 3: Worker history (replace WORKER_ID with an ID from Test 1)
curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer $TOKEN" \
"https://$HOST/ccx/api/v1/$TENANT/workers/WORKER_ID/history"
# Test 4: Supervisory organizations
curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer $TOKEN" \
"https://$HOST/ccx/api/v1/$TENANT/supervisoryOrganizations"
각 테스트는 HTTP 상태 200를 반환해야 합니다. 엔드포인트에서 403를 반환하면 아래의 문제 해결 섹션을 참고하세요.
Workday HCM 데이터를 수집하도록 Google SecOps에서 피드 구성
피드 설정
- SIEM 설정> 피드로 이동합니다.
- 새 피드 추가를 클릭합니다.
- 다음 페이지에서 단일 피드 구성을 클릭합니다.
- 피드 이름 필드에 피드 이름을 입력합니다(예:
Workday HCM). - 소스 유형으로 서드 파티 API를 선택합니다.
- 로그 유형으로 Workday를 선택합니다.
- 다음을 클릭합니다.
피드 매개변수 구성
다음 입력 매개변수의 값을 지정합니다.
API 호스트 이름: Workday REST API 엔드포인트의 정규화된 도메인 이름입니다 (예:
wd2-impl-services1.workday.com).테넌트: Workday 인스턴스를 식별하는 Workday REST API 엔드포인트의 마지막 경로 요소입니다.
액세스 토큰: 이전 섹션에서 생성된 OAuth 액세스 토큰입니다.
고급 옵션:
- 애셋 네임스페이스: 애셋 네임스페이스입니다.
- 수집 라벨: 이 피드의 이벤트에 적용할 라벨입니다.
- 다음을 클릭합니다.
- 확정 화면에서 새 피드 구성을 검토한 다음 제출을 클릭합니다.
문제 해결
특정 엔드포인트에서 403 금지됨 오류 발생
피드에서 오류를 보고하거나 확인 curl 명령어에서 특정 엔드포인트에 대해 403를 반환하는 경우 통합 시스템 사용자에게 권한이 누락된 것입니다.
| 실패한 엔드포인트 | 수정 |
|---|---|
/workers/{id}/timeOffEntries |
Worker Data: Time Off (Time Off Balances) 및 Worker Data: Time Off (Time Off Balances Manager View) 도메인에 GET 액세스 권한 추가 API 클라이언트에 Time Off and Leave 범위를 추가합니다. |
/workers/{id}/history |
Worker Data: Historical Staffing Information 도메인에 GET 액세스 권한 추가 Staffing 범위가 API 클라이언트에 할당되었는지 확인합니다. |
/supervisoryOrganizations |
Manage: Supervisory Organization 또는 View: Supervisory Organization 도메인에 GET 액세스 권한을 추가합니다. API 클라이언트에 조직 및 역할 범위를 추가합니다. |
권한을 변경한 후에는 다음 단계를 따르세요.
- Workday에서 Activate Pending Security Policy Changes를 실행합니다.
- API 클라이언트에 새 범위를 추가한 경우 통합용 갱신 토큰 관리를 통해 새 갱신 토큰을 생성한 다음 새 액세스 토큰을 생성합니다.
- 액세스 토큰이 변경된 경우 새 액세스 토큰으로 피드 구성을 업데이트합니다.
인증 오류
- 401 승인되지 않음: 액세스 토큰이 만료되었습니다. 갱신 토큰을 사용하여 새 토큰을 생성하고 피드를 업데이트합니다.
- 잘못된 클라이언트: 클라이언트 ID와 클라이언트 보안 비밀번호가 올바른지 확인합니다.
- 잘못된 갱신 토큰: 갱신 토큰이 취소되었을 수 있습니다. 통합의 갱신 토큰 관리를 통해 새 토큰을 생성합니다.
UDM 매핑 테이블
| 로그 필드 | UDM 매핑 | 논리 |
|---|---|---|
entity_host_name |
entity.asset.hostname |
직접 매핑됨 |
location.descriptor |
entity.location.city |
직접 매핑됨 |
AU_EFFECTIVE_DATE |
entity.resource.attribute.labels.value |
직접 매핑됨 |
COMPANY_EFFECTIVE_DATE |
entity.resource.attribute.labels.value |
직접 매핑됨 |
ORIG_HIRE_DT |
entity.resource.attribute.labels.value |
직접 매핑됨 |
STATUS_EFFECTIVE_DATE |
entity.resource.attribute.labels.value |
직접 매핑됨 |
href |
entity.url |
직접 매핑됨 |
CONT_START_DTE |
entity.user.attribute.labels.value |
직접 매핑됨 |
EMPL_TYPE |
entity.user.attribute.labels.value |
직접 매핑됨 |
EXEC_CD |
entity.user.attribute.labels.value |
직접 매핑됨 |
EXEC_DESCR |
entity.user.attribute.labels.value |
직접 매핑됨 |
HR_Status |
entity.user.attribute.labels.value |
직접 매핑됨 |
Is_Active |
entity.user.attribute.labels.value |
직접 매핑됨 |
Is_Manager |
entity.user.attribute.labels.value |
직접 매핑됨 |
JOB_CODE |
entity.user.attribute.labels.value |
직접 매핑됨 |
ORG_CD |
entity.user.attribute.labels.value |
직접 매핑됨 |
ORG_Container |
entity.user.attribute.labels.value |
직접 매핑됨 |
ORG_Container_Name |
entity.user.attribute.labels.value |
직접 매핑됨 |
PER_Status |
entity.user.attribute.labels.value |
직접 매핑됨 |
POSITION_NBR |
entity.user.attribute.labels.value |
직접 매핑됨 |
PS_ELID |
entity.user.attribute.labels.value |
직접 매핑됨 |
REG_TEMP |
entity.user.attribute.labels.value |
직접 매핑됨 |
WB_LOGON_ID |
entity.user.attribute.labels.value |
직접 매핑됨 |
ORG_DESCR |
entity.user.department |
병합됨 |
primarySupervisoryOrganization.descriptor |
entity.user.department |
병합됨 |
Email |
entity.user.email_addresses |
병합됨 |
Work_Email |
entity.user.email_addresses |
병합됨 |
primaryWorkEmail |
entity.user.email_addresses |
병합됨 |
EMPLID |
entity.user.employee_id |
직접 매핑됨 |
Employee_ID |
entity.user.employee_id |
직접 매핑됨 |
First_Name |
entity.user.first_name |
직접 매핑됨 |
Legal_Name_First_Name |
entity.user.first_name |
직접 매핑됨 |
HIRE_DATE |
entity.user.hire_date |
RFC 3339로 파싱됨 |
Hire_Date |
entity.user.hire_date |
RFC 3339로 파싱됨 |
Last_Name |
entity.user.last_name |
직접 매핑됨 |
Legal_Name_Last_Name |
entity.user.last_name |
직접 매핑됨 |
gopher-supervisor.primaryWorkEmail |
entity.user.managers.email_addresses |
병합됨 |
Reports_To_EMPLID |
entity.user.managers.employee_id |
직접 매핑됨 |
gopher-supervisor.id |
entity.user.managers.product_object_id |
이름이 변경됨/매핑됨 |
Reports_To_Name |
entity.user.managers.user_display_name |
직접 매핑됨 |
gopher-supervisor.descriptor |
entity.user.managers.user_display_name |
이름이 변경됨/매핑됨 |
primaryWorkPhone |
entity.user.phone_numbers |
병합됨 |
Termination_Date |
entity.user.termination_date |
RFC 3339로 파싱됨 |
timeoff.descriptor |
entity.user.time_off.description |
직접 매핑됨 |
timeoff.date |
entity.user.time_off.interval.start_time |
RFC 3339로 파싱됨 |
HR_JOB_TITLE |
entity.user.title |
직접 매핑됨 |
Job_Profile |
entity.user.title |
직접 매핑됨 |
businessTitle |
entity.user.title |
직접 매핑됨 |
Full_Name |
entity.user.user_display_name |
직접 매핑됨 |
descriptor |
entity.user.user_display_name |
직접 매핑됨 |
udm_metadata |
metadata |
이름이 변경됨/매핑됨 |
metadata_entity_type |
metadata.entity_type |
직접 매핑됨 |
actual_completed_date_and_time |
metadata.event_timestamp |
MM/dd/yyyy HH:mm:ss a로 파싱됨 |
body.time |
metadata.event_timestamp |
UNIX_MS로 파싱됨 |
requestTime |
metadata.event_timestamp |
RFC 3339로 파싱됨 |
timestamp |
metadata.event_timestamp |
RFC 3339로 파싱됨 |
EMPLID |
metadata.product_entity_id |
직접 매핑됨 |
Employee_ID |
metadata.product_entity_id |
직접 매핑됨 |
id |
metadata.product_entity_id |
직접 매핑됨 |
Source_Name |
metadata.product_name |
직접 매핑됨 |
userAgent |
network.http.parsed_user_agent |
이름이 변경됨/매핑됨 |
userAgent |
network.http.user_agent |
직접 매핑됨 |
sessionId |
network.session_id |
직접 매핑됨 |
ipAddress |
principal.ip |
병합됨 |
taskId |
principal.process.pid |
직접 매핑됨 |
activityAction_label |
principal.resource.attribute.labels |
병합됨 |
body.event.Submitted_By |
principal.user.userid |
직접 매핑됨 |
body.event.Response_Message |
security_result.action_details |
직접 매핑됨 |
body.event.Messages |
security_result.description |
직접 매핑됨 |
actual_start_date_and_time_label |
security_result.detection_fields |
병합됨 |
background_process_is_running_label |
security_result.detection_fields |
병합됨 |
by_person_label |
security_result.detection_fields |
병합됨 |
created_from_trigger_label |
security_result.detection_fields |
병합됨 |
items_processed_label |
security_result.detection_fields |
병합됨 |
percent_complete_label |
security_result.detection_fields |
병합됨 |
processing_time_label |
security_result.detection_fields |
병합됨 |
scheduled_start_date_and_time_label |
security_result.detection_fields |
병합됨 |
sent_on_label |
security_result.detection_fields |
병합됨 |
total_duration_label |
security_result.detection_fields |
병합됨 |
body.event.Integration_Event_Status |
security_result.summary |
직접 매핑됨 |
body.event.Integration_System |
target.application |
직접 매핑됨 |
target_data.id |
target.resource.product_object_id |
직접 매핑됨 |
deviceType |
target.resource.resource_subtype |
직접 매핑됨 |
deviceType |
target.resource.type |
매핑됨: (?i)(Desktop/Laptop/Mobile) → DEVICE |
user_display_name |
target.user.user_display_name |
직접 매핑됨 |
systemAccount |
target.user.userid |
직접 매핑됨 |
| 해당 사항 없음 | entity.resource.attribute.labels.key |
상수: COMPANY_EFFECTIVE_DATE |
| 해당 사항 없음 | entity.user.attribute.labels.key |
상수: ORG_Container |
| 해당 사항 없음 | metadata.product_name |
상수: HCM |
| 해당 사항 없음 | metadata.vendor_name |
상수: Workday |
| 해당 사항 없음 | target.resource.type |
상수: DEVICE |
변경 로그
도움이 더 필요하신가요? 커뮤니티 회원 및 Google SecOps 전문가에게 문의하여 답변을 받으세요.