收集 Workday 稽核記錄

支援的國家/地區:

本文說明如何使用 AWS S3,將 Workday 稽核記錄擷取至 Google Security Operations。剖析器會先根據 CSV 資料的模式分析,從記錄中找出特定事件類型。然後,系統會根據識別出的類型擷取並建構相關欄位,將這些欄位對應至統一資料模型 (UDM),以進行一致的安全性分析。

事前準備

請確認您已完成下列事前準備事項:

  • Google SecOps 執行個體
  • AWS 的特殊存取權
  • Workday 特殊存取權

為 Google SecOps 設定 AWS S3 值區和 IAM

  1. 按照這份使用者指南建立 Amazon S3 值區建立值區
  2. 儲存 bucket 的「名稱」和「區域」,以供日後參考 (例如 workday-audit-logs)。
  3. 請按照這份使用者指南建立使用者建立 IAM 使用者
  4. 選取建立的「使用者」
  5. 選取「安全憑證」分頁標籤。
  6. 在「Access Keys」部分中,按一下「Create Access Key」
  7. 選取「第三方服務」做為「用途」
  8. 點選「下一步」
  9. 選用:新增說明標記。
  10. 按一下「建立存取金鑰」
  11. 按一下「下載 CSV 檔案」,儲存「存取金鑰」和「私密存取金鑰」,以供日後參考。
  12. 按一下 [完成]
  13. 選取「權限」分頁標籤。
  14. 在「權限政策」部分中,按一下「新增權限」
  15. 選取「新增權限」
  16. 選取「直接附加政策」
  17. 搜尋並選取 AmazonS3FullAccess 政策。
  18. 點選「下一步」
  19. 按一下「Add permissions」。

建立 Workday Integration System User (ISU)

  1. 在 Workday 中搜尋「Create Integration System User」(建立整合系統使用者) > 點選「OK」(確定)
  2. 填入「User Name」(使用者名稱) (例如 audit_s3_user)。
  3. 按一下「確定」
  4. 依序前往「相關動作」>「安全性」>「重設密碼」,即可重設密碼。
  5. 選取「維持密碼規則」,避免密碼過期。
  6. 搜尋「Create Security Group」>「Integration System Security Group (Unconstrained)」
  7. 提供名稱 (例如 ISU_Audit_S3),並將 ISU 新增至「整合系統使用者」
  8. 搜尋「Domain Security Policies for Functional Area > System」
  9. 在「稽核記錄」部分,依序選取「動作」>「編輯權限」
  10. 在「僅限取得」下方,新增 ISU_Audit_S3 群組。
  11. 依序點選「確定」「啟用待處理的安全政策變更」

設定 Workday 自訂報表

  1. 在 Workday 中搜尋「Create Custom Report」(建立自訂報表)。
  2. 提供下列設定詳細資料:
    • 名稱:輸入不重複的名稱 (例如 Audit_Trail_BP_JSON)。
    • 類型:選取「進階」
    • 資料來源:選取「稽核追蹤記錄 - 業務程序」
    • 按一下「確定」
    • 選用:新增「業務流程類型」或「生效日期」篩選器。
  3. 前往「輸出」分頁。
  4. 選取「啟用為 Web 服務」和「針對效能進行最佳化」,然後選取「JSON 格式」
  5. 依序按一下「確定」>「完成」
  6. 開啟報表,然後依序按一下「共用」> 新增 ISU_Audit_S3 並授予「檢視」權限 >「確定」
  7. 依序前往「相關動作」>「網路服務」>「查看網址」
  8. 複製 JSON 網址 (例如 https://wd-services1.workday.com/ccx/service/customreport2/<tenant>/<user>/Audit_Trail_BP_JSON?format=json)。

設定 S3 上傳的身分與存取權管理政策和角色

  1. 政策 JSON (如果您輸入的 bucket 名稱不同,請替換 workday-audit-logs):

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "AllowPutWorkdayObjects",
          "Effect": "Allow",
          "Action": "s3:PutObject",
          "Resource": "arn:aws:s3:::workday-audit-logs/*"
        }
      ]
    }
    
  2. 依序前往 AWS 管理控制台 > IAM > 政策 > 建立政策 > JSON 分頁

  3. 複製並貼上政策。

  4. 依序點選「Next」>「Create policy」

  5. 依序前往「IAM」>「Roles」>「Create role」>「AWS service」>「Lambda」

  6. 附加新建立的政策。

  7. 為角色命名 WriteWorkdayToS3Role,然後按一下「建立角色」

建立 Lambda 函式

設定
名稱 workday_audit_to_s3
執行階段 Python 3.13
架構 x86_64
執行角色 WriteWorkdayToS3Role
  1. 建立函式後,開啟「程式碼」分頁,刪除存根並貼上下列程式碼 (workday_audit_to_s3.py)。

    #!/usr/bin/env python3
    
    import os, json, gzip, io, uuid, base64, datetime as dt, urllib.request, urllib.error
    import boto3
    
    WD_USER   = os.environ["WD_USER"]
    WD_PASS   = os.environ["WD_PASS"]
    WD_URL    = os.environ["WD_URL"]
    S3_BUCKET = os.environ["S3_BUCKET_NAME"]
    
    def fetch_report() -> bytes:
        credentials = f"{WD_USER}:{WD_PASS}".encode()
        auth_header = b"Basic " + base64.b64encode(credentials)
        req = urllib.request.Request(WD_URL, headers={"Authorization": auth_header.decode()})
        with urllib.request.urlopen(req, timeout=30) as r:
            return r.read()  # raw JSON bytes
    
    def upload(payload: bytes, ts: dt.datetime) -> None:
        key = f"{ts:%Y/%m/%d}/workday-audit-{uuid.uuid4()}.json.gz"
        buf = io.BytesIO()
        with gzip.GzipFile(fileobj=buf, mode="w") as gz:
            gz.write(payload)
        buf.seek(0)
        boto3.client("s3").upload_fileobj(buf, S3_BUCKET, key)
    
    def lambda_handler(event=None, context=None):
        now = dt.datetime.utcnow().replace(microsecond=0)
        data = fetch_report()
        upload(data, now)
        print(f"Uploaded Workday audit report ({len(data)} bytes raw)")
    
    if __name__ == "__main__":
        lambda_handler()
    
  2. 依序前往「Configuration」>「Environment variables」>「Edit」>「Add new environment variable」

  3. 輸入下列環境變數,並將 換成您的值。

    環境變數

    範例值
    WD_USER audit_s3_user
    WD_PASS Wrokday-Password
    WD_URL https://.../Audit_Trail_BP_JSON?format=json
    S3_BUCKET_NAME workday-audit-logs
  4. 建立函式後,請留在函式頁面 (或依序開啟「Lambda」>「Functions」>「your‑function」)。

  5. 選取「設定」分頁標籤。

  6. 在「一般設定」面板中,按一下「編輯」

  7. 將「Timeout」(逾時間隔) 變更為「5 minutes (300 seconds)」(5 分鐘 (300 秒)),然後按一下「Save」(儲存)

排定 Lambda 函式 (EventBridge 排程器)

  1. 依序前往「Configuration」>「Triggers」>「Add trigger」>「EventBridge Scheduler」>「Create rule」
  2. 提供下列設定詳細資料:
    • 名稱daily-workday-audit export
    • 排程模式Cron 運算式
    • 運算式20 2 * * ? * (每天世界標準時間 02:20 執行)。
  3. 其餘設定保留預設值,然後點選「建立」

在 Google SecOps 中設定動態饋給,擷取 Workday 稽核記錄

  1. 依序前往「SIEM 設定」>「動態饋給」
  2. 按一下「+ 新增動態消息」
  3. 在「動態饋給名稱」欄位中輸入動態饋給名稱 (例如 Workday Audit Logs)。
  4. 選取「Amazon S3 V2」做為「來源類型」
  5. 選取「Workday Audit」(Workday 稽核) 做為「Log type」(記錄類型)
  6. 按一下「取得服務帳戶」
  7. 點選「下一步」
  8. 指定下列輸入參數的值:
    • S3 URI:值區 URI
      • s3://workday-audit-logs/
        • 請將 workday-audit-logs 替換為實際值區名稱。
    • 來源刪除選項:根據偏好設定選取刪除選項。
    • 檔案存在時間上限:包含在過去天數內修改的檔案。預設值為 180 天。
    • 存取金鑰 ID:具有 S3 值區存取權的使用者存取金鑰。
    • 存取密鑰:具有 S3 bucket 存取權的使用者私密金鑰。
    • 資產命名空間資產命名空間
    • 擷取標籤:要套用至這個動態饋給事件的標籤。
  9. 點選「下一步」
  10. 在「Finalize」畫面上檢查新的動態饋給設定,然後按一下「Submit」

UDM 對應表

記錄欄位 UDM 對應 邏輯
Account metadata.event_type 如果「帳戶」欄位不為空白,「metadata.event_type」欄位會設為「USER_RESOURCE_UPDATE_CONTENT」。
Account principal.user.primaryId 系統會使用 grok 模式從「帳戶」欄位擷取使用者 ID,並對應至 principal.user.primaryId
Account principal.user.primaryName 系統會使用 grok 模式從「帳戶」欄位擷取使用者顯示名稱,並對應至「principal.user.primaryName」。
ActivityCategory metadata.event_type 如果「ActivityCategory」欄位為「READ」,「metadata.event_type」欄位會設為「RESOURCE_READ」。如果是「WRITE」,則會設為「RESOURCE_WRITTEN」。
ActivityCategory metadata.product_event_type 直接從「ActivityCategory」欄位對應。
AffectedGroups target.user.group_identifiers 直接從「AffectedGroups」欄位對應。
Area target.resource.attribute.labels.area.value 直接從「區域」欄位對應。
AuthType extensions.auth.auth_details 直接從「AuthType」欄位對應。
AuthType extensions.auth.type 根據特定值,從「AuthType」欄位對應至 UDM 中定義的不同驗證類型。
CFIPdeConexion src.domain.name 如果「CFIPdeConexion」欄位不是有效的 IP 位址,系統會將其對應至「src.domain.name」。
CFIPdeConexion target.ip 如果「CFIPdeConexion」欄位是有效的 IP 位址,則會對應至「target.ip」。
ChangedRelationship metadata.description 直接從「ChangedRelationship」欄位對應。
ClassOfInstance target.resource.attribute.labels.class_instance.value 直接從「ClassOfInstance」欄位對應。
column18 about.labels.utub.value 直接從「column18」欄位對應。
CreatedBy principal.user.userid 系統會使用 grok 模式從「CreatedBy」欄位擷取使用者 ID,並對應至「principal.user.userid」。
CreatedBy principal.user.user_display_name 系統會使用 grok 模式從「CreatedBy」欄位擷取使用者顯示名稱,並對應至「principal.user.user_display_name」。
Domain about.domain.name 直接從「網域」欄位對應。
EffectiveDate @timestamp 轉換為「yyyy-MM-dd HH:mm:ss.SSSZ」格式後,會剖析為「@timestamp」。
EntryMoment @timestamp 轉換為「ISO8601」格式後,剖析為「@timestamp」。
EventType security_result.description 直接從「EventType」欄位對應。
Form target.resource.name 直接從「表單」欄位對應。
InstancesAdded about.resource.attribute.labels.instances_added.value 直接從「InstancesAdded」欄位對應。
InstancesAdded target.user.attribute.roles.instances_added.name 直接從「InstancesAdded」欄位對應。
InstancesRemoved about.resource.attribute.labels.instances_removed.value 直接從「InstancesRemoved」欄位對應。
InstancesRemoved target.user.attribute.roles.instances_removed.name 直接從「InstancesRemoved」欄位對應。
IntegrationEvent target.resource.attribute.labels.integration_event.value 直接從「IntegrationEvent」欄位對應。
IntegrationStatus security_result.action_details 直接從「IntegrationStatus」欄位對應。
IntegrationSystem target.resource.name 直接從「IntegrationSystem」欄位對應。
IP src.domain.name 如果「IP」欄位不是有效的 IP 位址,系統會將其對應至「src.domain.name」。
IP src.ip 如果「IP」欄位是有效的 IP 位址,則會對應至「src.ip」。
IsDeviceManaged additional.fields.additional1.value.string_value 如果「IsDeviceManaged」欄位為「N」,則值會設為「Successful」。否則會設為「發生登入失敗情形」。
IsDeviceManaged additional.fields.additional2.value.string_value 如果「IsDeviceManaged」欄位為「N」,則值會設為「Successful」。否則會設為「憑證無效」。
IsDeviceManaged additional.fields.additional3.value.string_value 如果「IsDeviceManaged」欄位為「N」,則值會設為「Successful」。否則會設為「帳戶已鎖定」。
IsDeviceManaged security_result.action_details 直接對應至「IsDeviceManaged」欄位。
OutputFiles about.file.full_path 直接從「OutputFiles」欄位對應。
Person principal.user.primaryId 如果「Person」欄位開頭為「INT」,系統會使用 grok 模式擷取使用者 ID,並對應至「principal.user.primaryId」。
Person principal.user.primaryName 如果「Person」欄位開頭為「INT」,系統會使用 grok 模式擷取使用者顯示名稱,並對應至「principal.user.primaryName」。
Person principal.user.user_display_name 如果「Person」欄位開頭不是「INT」,則會直接對應至「principal.user.user_display_name」。
Person metadata.event_type 如果「Person」欄位不為空白,「metadata.event_type」欄位會設為「USER_RESOURCE_UPDATE_CONTENT」。
ProcessedTransaction target.resource.attribute.creation_time 轉換為「dd/MM/yyyy HH:mm:ss,SSS (ZZZ)」、「dd/MM/yyyy, HH:mm:ss,SSS (ZZZ)」或「MM/dd/yyyy, HH:mm:ss.SSS A ZZZ」格式後,會剖析為「target.resource.attribute.creation_time」。
ProgramBy principal.user.userid 直接從「ProgramBy」欄位對應。
RecurrenceEndDate principal.resource.attribute.last_update_time 轉換為「yyyy-MM-dd」格式後,剖析為「principal.resource.attribute.last_update_time」。
RecurrenceStartDate principal.resource.attribute.creation_time 轉換為「yyyy-MM-dd」格式後,剖析為「principal.resource.attribute.creation_time」。
RequestName metadata.description 直接從「RequestName」欄位對應。
ResponseMessage security_result.summary 直接從「ResponseMessage」欄位對應。
RestrictedToEnvironment security_result.about.hostname 直接從「RestrictedToEnvironment」欄位對應。
RevokedSecurity security_result.outcomes.outcomes.value 直接對應至「RevokedSecurity」欄位。
RunFrequency principal.resource.attribute.labels.run_frequency.value 直接從「RunFrequency」欄位對應。
ScheduledProcess principal.resource.name 直接從「ScheduledProcess」欄位對應。
SecuredTaskExecuted target.resource.name 直接從「SecuredTaskExecuted」欄位對應。
SecureTaskExecuted metadata.event_type 如果「SecureTaskExecuted」欄位包含「Create」,「metadata.event_type」欄位會設為「USER_RESOURCE_CREATION」。
SecureTaskExecuted target.resource.name 直接從「SecureTaskExecuted」欄位對應。
SentTime @timestamp 轉換為「ISO8601」格式後,剖析為「@timestamp」。
SessionId network.session_id 直接從「SessionId」欄位對應。
ShareBy target.user.userid 直接從「ShareBy」欄位對應。
SignOffTime additional.fields.additional4.value.string_value 「AuthFailMessage」欄位值會放在「additional.fields」陣列中,並以「Enterprise Interface Builder」做為鍵。
SignOffTime metadata.description 直接從「AuthFailMessage」欄位對應。
SignOffTime metadata.event_type 如果「SignOffTime」欄位空白,「metadata.event_type」欄位會設為「USER_LOGIN」。否則會設為「USER_LOGOUT」。
SignOffTime principal.user.attribute.last_update_time 轉換為「ISO8601」格式後,剖析為「principal.user.attribute.last_update_time」。
SignOnIp src.domain.name 如果「SignOnIp」欄位不是有效的 IP 位址,系統會將其對應至「src.domain.name」。
SignOnIp src.ip 如果「SignOnIp」欄位是有效的 IP 位址,則會對應至「src.ip」。
Status metadata.product_event_type 直接從「狀態」欄位對應。
SystemAccount principal.user.email_addresses 系統會使用 grok 模式從「SystemAccount」欄位擷取電子郵件地址,並對應至「principal.user.email_addresses」。
SystemAccount principal.user.primaryId 系統會使用 grok 模式從「SystemAccount」欄位擷取使用者 ID,並對應至「principal.user.primaryId」。
SystemAccount principal.user.primaryName 系統會使用 grok 模式從「SystemAccount」欄位擷取使用者顯示名稱,並對應至「principal.user.primaryName」。
SystemAccount src.user.userid 系統會使用 grok 模式從「SystemAccount」欄位擷取次要使用者 ID,並對應至「src.user.userid」。
SystemAccount src.user.user_display_name 系統會使用 grok 模式從「SystemAccount」欄位擷取次要使用者顯示名稱,並對應至「src.user.user_display_name」。
SystemAccount target.user.userid 系統會使用 grok 模式從「SystemAccount」欄位擷取目標使用者 ID,並對應至「target.user.userid」。
Target target.user.user_display_name 直接從「目標」欄位對應。
Template about.resource.name 直接從「範本」欄位對應。
Tenant target.asset.hostname 直接從「租戶」欄位對應。
TlsVersion network.tls.version 直接對應至「TlsVersion」欄位。
Transaction security_result.action_details 直接從「交易」欄位對應。
TransactionType security_result.summary 直接從「TransactionType」欄位對應。
TypeForm target.resource.resource_subtype 直接從「TypeForm」欄位對應。
UserAgent network.http.parsed_user_agent 使用「useragent」篩選器從「UserAgent」欄位剖析。
UserAgent network.http.user_agent 直接從「UserAgent」欄位對應。
WorkdayAccount target.user.user_display_name 系統會使用 grok 模式從「WorkdayAccount」欄位擷取使用者顯示名稱,並對應至「target.user.user_display_name」。
WorkdayAccount target.user.userid 系統會使用 grok 模式從「WorkdayAccount」欄位擷取使用者 ID,並對應至「target.user.userid」。
additional.fields.additional1.key 設為「FailedSignOn」。
additional.fields.additional2.key 設為「InvalidCredentials」。
additional.fields.additional3.key 設為「AccountLocked」。
additional.fields.additional4.key 設為「Enterprise Interface Builder」。
metadata.event_type 一開始設為「GENERIC_EVENT」,然後根據涉及其他欄位的邏輯更新。
metadata.event_type 針對特定事件類型設為「USER_CHANGE_PERMISSIONS」。
metadata.event_type 針對特定事件類型,請設為「RESOURCE_WRITTEN」。
metadata.log_type 硬式編碼為「WORKDAY_AUDIT」。
metadata.product_name 硬式編碼為「Enterprise Interface Builder」。
metadata.vendor_name 硬式編碼為「Workday」。
principal.asset.category 如果「DeviceType」欄位為「Phone」,請設為「Phone」。
principal.resource.resource_type 如果「ScheduledProcess」欄位不為空白,則會硬式編碼為「TASK」。
security_result.action 根據「FailedSignOn」、「IsDeviceManaged」、「InvalidCredentials」和「AccountLocked」欄位的值,設為「ALLOW」或「FAIL」。
security_result.summary 根據「FailedSignOn」、「IsDeviceManaged」、「InvalidCredentials」和「AccountLocked」欄位的值,設為「Successful」或特定錯誤訊息。
target.resource.resource_type 針對特定事件類型硬式編碼為「TASK」。
target.resource.resource_type 如果「TypeForm」欄位不為空白,則會硬式編碼為「DATASET」。
message principal.user.email_addresses 使用 grok 模式從「message」欄位擷取電子郵件地址,並在符合特定模式時,將其合併至「principal.user.email_addresses」。
message src.user.userid 如果「event.idm.read_only_udm.principal.user.userid」欄位與從「message」欄位擷取的「user_target」相符,則清除該欄位。
message src.user.user_display_name 如果「event.idm.read_only_udm.principal.user.userid」欄位與從「message」欄位擷取的「user_target」相符,則清除該欄位。
message target.user.userid 使用 grok 模式從「message」欄位擷取 userid,並在符合特定模式時將其對應至「target.user.userid」。

還有其他問題嗎?向社群成員和 Google SecOps 專業人員尋求答案。