Workday 監査ログを収集する
このドキュメントでは、AWS S3 を使用して Workday 監査ログを Google Security Operations に取り込む方法について説明します。パーサーは、まず CSV データのパターン分析に基づいて、ログから特定のイベントタイプを特定します。次に、特定されたタイプに従って関連するフィールドを抽出して構造化し、一貫したセキュリティ分析のために統合データモデル(UDM)にマッピングします。
始める前に
次の前提条件を満たしていることを確認してください。
- Google SecOps インスタンス
- AWS への特権アクセス
- Workday への特権アクセス
Google SecOps 用に AWS S3 バケットと IAM を構成する
- バケットの作成のユーザーガイドに沿って、Amazon S3 バケットを作成します。
- 後で参照できるように、バケットの名前とリージョンを保存します(例:
workday-audit-logs
)。 - IAM ユーザーの作成のユーザーガイドに沿って、ユーザーを作成します。
- 作成したユーザーを選択します。
- [セキュリティ認証情報] タブを選択します。
- [アクセスキー] セクションで [アクセスキーを作成] をクリックします。
- [ユースケース] で [サードパーティ サービス] を選択します。
- [次へ] をクリックします。
- 省略可: 説明タグを追加します。
- [アクセスキーを作成] をクリックします。
- [CSV ファイルをダウンロード] をクリックし、[アクセスキー] と [シークレット アクセスキー] を保存して、今後の参照に備えます。
- [完了] をクリックします。
- [権限] タブを選択します。
- [権限ポリシー] セクションで [権限を追加] をクリックします。
- [権限を追加] を選択します。
- [ポリシーを直接アタッチする] を選択します。
- AmazonS3FullAccess ポリシーを検索して選択します。
- [次へ] をクリックします。
- [権限を追加] をクリックします。
Workday 統合システム ユーザー(ISU)を作成する
- Workday で、[Create Integration System User] を検索 > [OK] をクリックします。
- [ユーザー名](例:
audit_s3_user
)を入力します。 - [OK] をクリックします。
- [Related Actions] > [Security] > [Reset Password] に移動して、パスワードをリセットします。
- [パスワード ルールの維持] を選択して、パスワードの有効期限が切れないようにします。
- [Create Security Group] > [Integration System Security Group (Unconstrained)] を検索します。
- 名前(例:
ISU_Audit_S3
)を指定し、ISU を [Integration System Users] に追加します。 - 機能領域 > システムのドメイン セキュリティ ポリシーを検索します。
- [監査証跡] で、[アクション>権限を編集] を選択します。
- [Get Only] で、
ISU_Audit_S3
グループを追加します。 - [OK > Activate Pending Security Policy Changes] をクリックします。
Workday カスタム レポートを構成する
- Workday で「Create Custom Report」を検索します。
- 次の構成の詳細を入力します。
- 名前: 一意の名前を入力します(例:
Audit_Trail_BP_JSON
)。 - Type: [Advanced] を選択します。
- データソース: [監査証跡 - ビジネス プロセス] を選択します。
- [OK] をクリックします。
- 省略可: [ビジネス プロセス タイプ] または [有効日] にフィルタを追加します。
- 名前: 一意の名前を入力します(例:
- [出力] タブに移動します。
- [Enable as Web Service]、[Optimized for Performance] を選択し、[JSON Format] を選択します。
- [OK>完了] をクリックします。
- レポートを開き、[共有> 閲覧権限を持つ
ISU_Audit_S3
を追加> OK] をクリックします。 - [Related Actions] > [Web Service] > [View URLs] に移動します。
- JSON URL(例:
https://wd-services1.workday.com/ccx/service/customreport2/<tenant>/<user>/Audit_Trail_BP_JSON?format=json
)をコピーします。
S3 アップロードの IAM ポリシーとロールを構成する
ポリシー JSON(別のバケット名を入力した場合は
workday-audit-logs
を置き換えます):{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowPutWorkdayObjects", "Effect": "Allow", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::workday-audit-logs/*" } ] }
AWS コンソール > IAM > ポリシー > ポリシーの作成 > [JSON] タブ に移動します。
ポリシーをコピーして貼り付けます。
[次へ> ポリシーを作成] をクリックします。
[IAM] > [ロール] > [ロールの作成] > [AWS サービス] > [Lambda] に移動します。
新しく作成したポリシーを関連付けます。
ロールに「
WriteWorkdayToS3Role
」という名前を付けて、[ロールを作成] をクリックします。
Lambda 関数を作成する
設定 | 値 |
---|---|
名前 | workday_audit_to_s3 |
ランタイム | Python 3.13 |
アーキテクチャ | x86_64 |
実行ロール | WriteWorkdayToS3Role |
関数を作成したら、[コード] タブを開き、スタブを削除して、次のコード(
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()
[構成> 環境変数> 編集> 新しい環境変数を追加] に移動します。
次の環境変数を入力し、値を置き換えます。
環境変数
キー 値の例 WD_USER
audit_s3_user
WD_PASS
Wrokday-Password
WD_URL
https://.../Audit_Trail_BP_JSON?format=json
S3_BUCKET_NAME
workday-audit-logs
関数が作成されたら、そのページにとどまるか、[Lambda] > [関数] > [your‑function] を開きます。
[CONFIGURATION] タブを選択します。
[全般設定] パネルで、[編集] をクリックします。
[Timeout] を [5 minutes (300 seconds)] に変更し、[Save] をクリックします。
Lambda 関数をスケジュールする(EventBridge Scheduler)
- [構成> トリガー> トリガーを追加> EventBridge Scheduler > ルールを作成] に移動します。
- 次の構成の詳細を入力します。
- 名前:
daily-workday-audit export
。 - スケジュール パターン: Cron 式。
- 式:
20 2 * * ? *
(毎日 02:20 UTC に実行)。
- 名前:
- 残りの設定はデフォルトのままにして、[作成] をクリックします。
Workday 監査ログを取り込むように Google SecOps でフィードを構成する
- [SIEM 設定] > [フィード] に移動します。
- [+ 新しいフィードを追加] をクリックします。
- [フィード名] フィールドに、フィードの名前を入力します(例:
Workday Audit Logs
)。 - [ソースタイプ] として [Amazon S3 V2] を選択します。
- [ログタイプ] として [Workday Audit] を選択します。
- [サービス アカウントを取得する] をクリックします。
- [次へ] をクリックします。
- 次の入力パラメータの値を指定します。
- S3 URI: バケット URI
s3://workday-audit-logs/
。workday-audit-logs
は、バケットの実際の名前に置き換えます。
- Source deletion options: 必要に応じて削除オプションを選択します。
- ファイルの最大経過日数: 指定した日数以内に変更されたファイルを含めます。デフォルトは 180 日です。
- アクセスキー ID: s3 バケットにアクセスできるユーザー アクセスキー。
- シークレット アクセスキー: s3 バケットにアクセスできるユーザーのシークレット キー。
- アセットの名前空間: アセットの名前空間。
- Ingestion labels: このフィードのイベントに適用されるラベル。
- S3 URI: バケット URI
- [次へ] をクリックします。
- [Finalize] 画面で新しいフィードの設定を確認し、[送信] をクリックします。
UDM マッピング テーブル
ログフィールド | UDM マッピング | ロジック |
---|---|---|
Account |
metadata.event_type | 「Account」フィールドが空でない場合、「metadata.event_type」フィールドは「USER_RESOURCE_UPDATE_CONTENT」に設定されます。 |
Account |
principal.user.primaryId | ユーザー ID は、Grok パターンを使用して「Account」フィールドから抽出され、principal.user.primaryId にマッピングされます。 |
Account |
principal.user.primaryName | ユーザーの表示名は、Grok パターンを使用して「Account」フィールドから抽出され、「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 | 「Area」フィールドから直接マッピングされます。 |
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 | userid は Grok パターンを使用して「CreatedBy」フィールドから抽出され、「principal.user.userid」にマッピングされます。 |
CreatedBy |
principal.user.user_display_name | ユーザーの表示名は、grok パターンを使用して「CreatedBy」フィールドから抽出され、「principal.user.user_display_name」にマッピングされます。 |
Domain |
about.domain.name | 「Domain」フィールドから直接マッピングされます。 |
EffectiveDate |
@timestamp | 「yyyy-MM-dd HH:mm:ss.SSSZ」形式に変換された後、「@timestamp」に解析されます。 |
EntryMoment |
@timestamp | 「ISO8601」形式に変換してから「@timestamp」に解析されます。 |
EventType |
security_result.description | 「EventType」フィールドから直接マッピングされます。 |
Form |
target.resource.name | 「Form」フィールドから直接マッピングされます。 |
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」に設定されます。それ以外の場合は、「Failed login occurred」に設定されます。 |
IsDeviceManaged |
additional.fields.additional2.value.string_value | 「IsDeviceManaged」フィールドが「N」の場合、値は「Successful」に設定されます。それ以外の場合は、「Invalid Credentials」に設定されます。 |
IsDeviceManaged |
additional.fields.additional3.value.string_value | 「IsDeviceManaged」フィールドが「N」の場合、値は「Successful」に設定されます。それ以外の場合は、「Account Locked」に設定されます。 |
IsDeviceManaged |
security_result.action_details | 「IsDeviceManaged」フィールドから直接マッピングされます。 |
OutputFiles |
about.file.full_path | 「OutputFiles」フィールドから直接マッピングされます。 |
Person |
principal.user.primaryId | 「Person」フィールドが「INT」で始まる場合、userid は Grok パターンを使用して抽出され、「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」フィールドの値は、「Enterprise Interface Builder」というキーで「additional.fields」配列内に配置されます。 |
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 | 「Status」フィールドから直接マッピングされます。 |
SystemAccount |
principal.user.email_addresses | メールアドレスは、Grok パターンを使用して「SystemAccount」フィールドから抽出され、「principal.user.email_addresses」にマッピングされます。 |
SystemAccount |
principal.user.primaryId | userid は、grok パターンを使用して「SystemAccount」フィールドから抽出され、「principal.user.primaryId」にマッピングされます。 |
SystemAccount |
principal.user.primaryName | ユーザーの表示名は、grok パターンを使用して「SystemAccount」フィールドから抽出され、「principal.user.primaryName」にマッピングされます。 |
SystemAccount |
src.user.userid | セカンダリ ユーザー ID は、grok パターンを使用して「SystemAccount」フィールドから抽出され、「src.user.userid」にマッピングされます。 |
SystemAccount |
src.user.user_display_name | セカンダリ ユーザーの表示名は、grok パターンを使用して「SystemAccount」フィールドから抽出され、「src.user.user_display_name」にマッピングされます。 |
SystemAccount |
target.user.userid | ターゲット ユーザー ID は、Grok パターンを使用して「SystemAccount」フィールドから抽出され、「target.user.userid」にマッピングされます。 |
Target |
target.user.user_display_name | 「Target」フィールドから直接マッピングされます。 |
Template |
about.resource.name | 「Template」フィールドから直接マッピングされます。 |
Tenant |
target.asset.hostname | 「Tenant」フィールドから直接マッピングされます。 |
TlsVersion |
network.tls.version | 「TlsVersion」フィールドから直接マッピングされます。 |
Transaction |
security_result.action_details | 「Transaction」フィールドから直接マッピングされます。 |
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 | userid は、grok パターンを使用して「WorkdayAccount」フィールドから抽出され、「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 のプロフェッショナルから回答を得ることができます。