diff --git a/packages/workday/_dev/build/build.yml b/packages/workday/_dev/build/build.yml index 32921896292..ac5efe47b5c 100644 --- a/packages/workday/_dev/build/build.yml +++ b/packages/workday/_dev/build/build.yml @@ -1,3 +1,3 @@ dependencies: ecs: - reference: git@v9.3.0 + reference: git@v9.4.0 diff --git a/packages/workday/_dev/build/docs/README.md b/packages/workday/_dev/build/docs/README.md index a259d6a13c5..4e99ee0d0c2 100644 --- a/packages/workday/_dev/build/docs/README.md +++ b/packages/workday/_dev/build/docs/README.md @@ -4,35 +4,36 @@ [Workday](https://www.workday.com/en-in/homepage.html) is a cloud-based ERP system that manages business processes and allows organizations to use an integrated application. Workday is a coherent cloud ERP system for financial analysis, analytical solutions, HCM suites, and better business processes. -The Workday integration for Elastic collects `Activity Logs` via **API** and visualizes them in Kibana. +The Workday integration for Elastic collects `Activity` logs via the **Workday API** and `Sign-on` logs via the **Workday Custom Report API**, and visualizes them in Kibana. ### Compatibility -The Workday integration is compatible with API version **v1**. +- The **Activity** data stream is compatible with Workday API version **v1**. +- The **Sign-on** data stream is compatible with Workday Custom Reports exposed via the **Reports as a Service (RaaS)** JSON endpoint (`/ccx/service/customreport2/...?format=json`). ### How it works -This integration periodically queries the Workday API to retrieve logs. +- **Activity**: This integration periodically queries the Workday API to retrieve Activity logs. +- **Sign-on**: This integration periodically downloads a Workday Custom Report (for example, a Sign-on report that lists sign-on records along with their key attributes) and ingests each report row as a single event. ## What data does this integration collect? -This integration collects log messages of the following type: +This integration collects log messages of the following types: -- `Activity`: Collects [Activity Logs](https://community.workday.com/sites/default/files/file-hosting/restapi/#privacy/v1/get-/activityLogging) logs via Workday API (endpoint: `/activityLogging`). +- `Activity`: Collects [Activity Logs](https://community.workday.com/sites/default/files/file-hosting/restapi/#privacy/v1/get-/activityLogging) via the Workday API (endpoint: `/activityLogging`). +- `Sign-on`: Collects sign-on information from a Workday Custom Report via the Workday Reports as a Service (RaaS) JSON endpoint. ### Supported use cases -Integrating Workday with Elastic gives security and IT teams centralized visibility into **Workday activity logging**, so you can monitor configuration and usage changes, support audits, and investigate suspicious behavior from Kibana. +Integrating Workday with Elastic gives security and IT teams centralized visibility into **Workday activity logging** and **Workday sign-on data**, so you can monitor configuration and usage changes, track sign-on activity and access patterns, support audits, and investigate suspicious or unusual authentication behavior from Kibana. -The **Activity** dashboard summarizes key patterns such as **activity volume over time** and **top actors**, helping you spot unusual spikes and focus on the users and operations that matter. - -Built-in filters make it easier to narrow events by attributes such as **task**, **system account**, and **IP address**, which supports faster triage and a more consistent investigation workflow across your Workday telemetry. +The **Activity** dashboard summarizes key patterns such as **activity volume over time** and **top actors**, helping you spot unusual spikes and focus on the users and operations that matter. Built-in filters make it easier to narrow events by attributes such as **task**, **system account**, and **IP address**, which supports faster triage and a more consistent investigation workflow across your Workday telemetry. ## What do I need to use this integration? ### From Workday -#### Collect Workday API credentials +#### For the Activity data stream ##### Enable User Activity Logging @@ -43,7 +44,7 @@ Built-in filters make it easier to narrow events by attributes such as **task**, **Note:** Once enabled, Workday records all user activity in a secure tenant database. Activity logging must be enabled before any logs are available for export. -#### Create Integration System User (ISU) +##### Create Integration System User (ISU) 1. In the Workday search bar, search for Create Integration System User. 2. Enter a User Name (for example, ISU_SIEM_Export) and a strong Password. @@ -54,7 +55,7 @@ Built-in filters make it easier to narrow events by attributes such as **task**, 7. Search for View Domain and locate the User Activity Logging domain. Grant Get access to the ISU security group for this domain. 8. Search for Activate Pending Security Policy Changes and activate the changes. -#### Register API client for OAuth +##### Register API client for OAuth 1. In the Workday search bar, search for Register API Client for Integrations. 2. Enter a Client Name (for example, SIEM_OAuth_Client). @@ -69,7 +70,7 @@ Built-in filters make it easier to narrow events by attributes such as **task**, 9. Generate a new refresh token for the API client. 10. Copy and save the Refresh Token. -#### Determine tenant URL +##### Determine tenant URL The API endpoint is based on your Workday tenant. The format is: @@ -83,6 +84,43 @@ Activity Logging API | https://HOST/ccx/api/privacy/v1/TENANT/activityLogging **Note:** For additional Workday API security context, see [Generating API Keys for the Workday API](https://workday.my.site.com/customercenter/article?no=000013105&redirect=false). +#### For the Sign-on data stream + +##### Build the Sign-on custom report + +1. Sign in to your Workday tenant as a user with report-authoring privileges. +2. In the Workday search bar, search for **Create Custom Report**. +3. Create an Advanced report on a data source that exposes sign-on activity (for example, `Signons and Attempted Signons`). +4. Add the columns required for sign-on analytics (for example, `System Account`, `Session Start`, `Session End`, `Authentication Type for Signon`, `Failed Signon`, `Invalid Credentials`, `Account Locked, Disabled or Expired`, `Browser Type`, `Operating System`, `Device Type`, `Request Originator`, `SAML Identity Provider`). +5. On the **Advanced** tab, select **Enable As Web Service** so the report is exposed as Reports as a Service (RaaS). +6. Save the report and note the **Report Name** and the **Report Owner** (the Workday account that owns the report). + +##### Create the Integration System User (ISU) + +1. In the Workday search bar, search for **Create Integration System User**. +2. Enter a User Name (for example, `ISU_SIEM_Export`) and a strong Password. +3. Clear the **Require New Password at Next Sign In** checkbox. +4. Click **OK**. +5. Search for **Create Security Group** and create an Integration System Security Group (Unconstrained). +6. Add the ISU (`ISU_SIEM_Export`) to this security group. +7. Grant the ISU security group access to the domain protecting the custom report's data source (for example, the `System Auditing` domain). +8. Search for **Activate Pending Security Policy Changes** and activate the changes. + +##### Determine the report URL + +The Custom Report endpoint URL has the following format: + +``` +https://HOST/ccx/service/customreport2/TENANT/REPORT_OWNER/REPORT_NAME?format=json +``` + +Where: + +- `HOST` is your Workday hostname. +- `TENANT` is your Workday tenant name. +- `REPORT_OWNER` is the Workday account that owns the custom report. +- `REPORT_NAME` is the name of the custom report you created above. + ## How do I deploy this integration? This integration supports both Elastic Agentless-based and Agent-based installations. @@ -105,7 +143,7 @@ Elastic Agent must be installed. For more details, check the Elastic Agent [inst 4. Select **Add Workday** to add the integration. 5. Enable and configure only the collection methods which you will use. - * To **Collect Workday logs via API**, you'll need to: + * To **Collect Workday Activity logs via API**, you'll need to: - Configure **Hostname**. - Configure **Tenant**. @@ -114,6 +152,12 @@ Elastic Agent must be installed. For more details, check the Elastic Agent [inst - Configure **Refresh Token**. - Adjust the integration configuration parameters if required, including the **Interval**, **Initial Interval**, **Preserve original event** etc. to enable data collection. + * To **Collect Workday Sign-on logs via Custom Report API**, you'll need to: + + - Configure **Report URL** with the full Workday Custom Report (RaaS) URL noted above. + - Configure **Username** and **Password** for basic authentication against the Workday Custom Report API. + - Adjust the integration configuration parameters if required, including the **Interval** and **Preserve original event** etc. to enable data collection. + 6. Select **Save and continue** to save the integration. ### Validation @@ -140,6 +184,10 @@ For more information on architectures that can be used for scaling this integrat {{fields "activity"}} +#### Sign-on + +{{fields "sign_on"}} + ### Example event #### Activity @@ -148,12 +196,17 @@ For more information on architectures that can be used for scaling this integrat ### Inputs used -These input is used in the integration: +These inputs are used in the integration: - [CEL](https://www.elastic.co/docs/reference/beats/filebeat/filebeat-input-cel) ### API usage -This integration uses the following Workday API: +This integration uses the following Workday APIs: + +- **Activity**: [Workday Activity API documentation](https://community.workday.com/sites/default/files/file-hosting/restapi/#privacy/v1/get-/activityLogging). +- **Sign-on**: The Workday **Reports as a Service (RaaS)** JSON endpoint is used to fetch a user-defined Sign-on custom report: -**Activity**: [Workday Activity API documentation](https://community.workday.com/sites/default/files/file-hosting/restapi/#privacy/v1/get-/activityLogging). +``` +GET https://HOST/ccx/service/customreport2/TENANT/REPORT_OWNER/REPORT_NAME?format=json +``` diff --git a/packages/workday/changelog.yml b/packages/workday/changelog.yml index 64f62bfd0f8..7eff2e05b06 100644 --- a/packages/workday/changelog.yml +++ b/packages/workday/changelog.yml @@ -1,4 +1,9 @@ # newer versions go on top +- version: '0.1.1' + changes: + - description: Add support for sign_on data stream. + type: enhancement + link: https://github.com/elastic/integrations/pull/20039 - version: '0.1.0' changes: - description: Add support for activity data stream. diff --git a/packages/workday/data_stream/activity/_dev/test/system/test-common-config.yml b/packages/workday/data_stream/activity/_dev/test/system/test-common-config.yml index d6481a8aa12..504f7a4207d 100644 --- a/packages/workday/data_stream/activity/_dev/test/system/test-common-config.yml +++ b/packages/workday/data_stream/activity/_dev/test/system/test-common-config.yml @@ -1,11 +1,6 @@ input: cel service: workday vars: - hostname: "{{Hostname}}:{{Port}}" - tenant: tenant - client_id: client_id - client_secret: client_secret - refresh_token: refresh_token ssl: | certificate_authorities: - | @@ -30,6 +25,11 @@ vars: -----END CERTIFICATE----- data_stream: vars: + hostname: "{{Hostname}}:{{Port}}" + tenant: tenant + client_id: client_id + client_secret: client_secret + refresh_token: refresh_token preserve_original_event: true batch_size: 2 assert: diff --git a/packages/workday/data_stream/activity/manifest.yml b/packages/workday/data_stream/activity/manifest.yml index 5ee7d2ba5ea..d07e5730eea 100644 --- a/packages/workday/data_stream/activity/manifest.yml +++ b/packages/workday/data_stream/activity/manifest.yml @@ -6,6 +6,41 @@ streams: description: Collect Activity logs from Workday. template_path: cel.yml.hbs vars: + - name: hostname + type: text + title: Hostname + description: 'Hostname of Workday instance. Example: .workday.com' + required: true + show_user: true + - name: tenant + type: text + title: Tenant + description: Tenant of Workday instance. + required: true + show_user: true + - name: client_id + type: text + title: Client ID + multi: false + required: true + show_user: true + description: Client ID. + - name: client_secret + type: password + title: Client Secret + multi: false + required: true + show_user: true + secret: true + description: Client Secret. + - name: refresh_token + type: text + title: Refresh Token + description: Refresh token for Workday instance. + multi: false + required: true + show_user: true + secret: true - name: initial_interval type: text title: Initial Interval diff --git a/packages/workday/data_stream/sign_on/_dev/test/pipeline/test-sign-on.log b/packages/workday/data_stream/sign_on/_dev/test/pipeline/test-sign-on.log new file mode 100644 index 00000000000..059ce5778f2 --- /dev/null +++ b/packages/workday/data_stream/sign_on/_dev/test/pipeline/test-sign-on.log @@ -0,0 +1,10 @@ +{"Account_Locked__Disabled_or_Expired":"0","Active_Session":"0","Authentication_Type_for_Signon":"SAML","Browser_Type":"Chrome","Device_Type":"Desktop","Device_is_Trusted":"0","Failed_Signon":"0","Forgotten_Password_Reset_Request":"0","Invalid_Credentials":"0","Is_Device_Managed":"0","Operating_System":"Mac OS X","Password_Changed":"0","Request_Originator":"UI","SAML_Identity_Provider":"IdP_Acme","Session_End":"2026-06-18T23:25:22-07:00","Session_Start":"2026-06-18T16:59:32-07:00","System_Account":"user534.acme / User 534"} +{"Account_Locked__Disabled_or_Expired":"0","Active_Session":"0","Authentication_Type_for_Signon":"OAuth 2.0","Device_is_Trusted":"0","Failed_Signon":"0","Forgotten_Password_Reset_Request":"0","Invalid_Credentials":"0","Is_Device_Managed":"0","Password_Changed":"0","Request_Originator":"Internal","Session_End":"2026-06-18T22:55:34-07:00","Session_Start":"2026-06-18T16:55:34-07:00","System_Account":"ISU_Integration_049"} +{"Account_Locked__Disabled_or_Expired":"0","Active_Session":"0","Authentication_Failure_Message":"Mobile PIN has expired. To reset your PIN, first sign in using your user name and password.","Authentication_Type_for_Signon":"Biometric","Browser_Type":"Workday Phone App","Device_Type":"Phone","Device_is_Trusted":"0","Failed_Signon":"1","Forgotten_Password_Reset_Request":"0","Invalid_Credentials":"0","Is_Device_Managed":"0","Operating_System":"iOS","Password_Changed":"0","Request_Originator":"UI","Session_Start":"2026-06-18T16:52:43-07:00","System_Account":"user179.acme / User 179","UI_Client_Type":"iPhone Native"} +{"Account_Locked__Disabled_or_Expired":"0","Active_Session":"0","Authentication_Type_for_Signon":"SAML","Browser_Type":"Workday Phone App","Device_Type":"Phone","Device_is_Trusted":"0","Failed_Signon":"0","Forgotten_Password_Reset_Request":"0","Invalid_Credentials":"0","Is_Device_Managed":"0","Operating_System":"iOS","Password_Changed":"0","Request_Originator":"UI","SAML_Identity_Provider":"IdP_Acme","Session_End":"2026-06-18T22:59:33-07:00","Session_Start":"2026-06-18T16:57:04-07:00","System_Account":"user179.acme / User 179"} +{"Account_Locked__Disabled_or_Expired":"0","Active_Session":"1","Authentication_Type_for_Signon":"User Name Password","Device_is_Trusted":"0","Failed_Signon":"0","Forgotten_Password_Reset_Request":"0","Invalid_Credentials":"0","Is_Device_Managed":"0","Password_Changed":"0","Request_Originator":"Web Services","Session_Start":"2026-06-18T13:18:51-07:00","System_Account":"ISU_Integration_001"} +{"Authentication_Type":"SAML","Browser_Type":"Chrome","Created_Moment":"2026-06-22T01:08:10.374-07:00","Device_Type":"Desktop","Device_is_Trusted":"0","Operating_System":"Mac OS X","Prompt_-_Positive_Integer":"linda.andersson / Linda Andersson","Request_Originator":"UI","SAML_Identity_Provider":"Okta E2","Session_ID":"4562a3","Sign-on_Time":"2026-06-22T01:08:10-07:00","Signoff_Time":"2026-06-22T02:09:01-07:00","Signon_IP_Address":"81.2.69.142","Signon_Worker":"Linda Andersson (006193)","User_Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36","userName":"linda.andersson"} +{"Authentication_Type":"User Name Password","Browser_Type":"Chrome","Created_Moment":"2026-06-22T00:44:17.617-07:00","Device_Type":"Desktop","Device_is_Trusted":"0","Operating_System":"Mac OS X","Prompt_-_Positive_Integer":"alina.goajga / Alina Garagancea","Request_Originator":"UI","Session_ID":"b40162","Sign-on_Time":"2026-06-22T00:44:17-07:00","Signoff_Time":"2026-06-22T03:35:15-07:00","Signon_IP_Address":"81.2.69.144","Signon_Worker":"Alina Garagancea (002036)","User_Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36","userName":"alina.goajga"} +{"Authentication_Type":"Trusted","Created_Moment":"2026-06-22T00:04:11.094-07:00","Device_Type":"Desktop","Device_is_Trusted":"0","Prompt_-_Positive_Integer":"ISU_Adaptive_Insights_User_Provisioning","Request_Originator":"Internal","Session_ID":"89d613","Sign-on_Time":"2026-06-22T00:04:11-07:00","Signoff_Time":"2026-06-22T01:04:11-07:00","Signon_IP_Address":"Workday Internal","userName":"ISU_Adaptive_Insights_User_Provisioning"} +{"Authentication_Type":"OAuth 2.0","Created_Moment":"2026-06-22T04:29:16.382-07:00","Device_is_Trusted":"0","Prompt_-_Positive_Integer":"ISU_WD_Logs","Request_Originator":"Internal","Session_ID":"87ed78","Sign-on_Time":"2026-06-22T04:29:16-07:00","Signoff_Time":"2026-06-22T05:29:16-07:00","Signon_IP_Address":"89.160.20.112","userName":"ISU_WD_Logs"} +{"Authentication_Failure_Message":"Invalid password","Authentication_Type":"User Name Password","Browser_Type":"Chrome","Created_Moment":"2026-06-22T06:41:11.320-07:00","Device_Type":"Desktop","Device_is_Trusted":"0","Operating_System":"Mac OS X","Prompt_-_Positive_Integer":"chris.carnes / Chris Carnes","Request_Originator":"UI","Sign-on_Time":"2026-06-22T06:41:11-07:00","Signon_IP_Address":"175.16.199.1","Signon_Worker":"Chris Carnes (006423)","User_Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36","userName":"chris.carnes"} diff --git a/packages/workday/data_stream/sign_on/_dev/test/pipeline/test-sign-on.log-expected.json b/packages/workday/data_stream/sign_on/_dev/test/pipeline/test-sign-on.log-expected.json new file mode 100644 index 00000000000..d5adbaa3c5e --- /dev/null +++ b/packages/workday/data_stream/sign_on/_dev/test/pipeline/test-sign-on.log-expected.json @@ -0,0 +1,651 @@ +{ + "expected": [ + { + "@timestamp": "2026-06-18T23:59:32.000Z", + "device": { + "type": "Desktop" + }, + "ecs": { + "version": "9.4.0" + }, + "event": { + "action": "user-signon", + "category": [ + "authentication", + "session" + ], + "end": "2026-06-19T06:25:22.000Z", + "kind": "event", + "original": "{\"Account_Locked__Disabled_or_Expired\":\"0\",\"Active_Session\":\"0\",\"Authentication_Type_for_Signon\":\"SAML\",\"Browser_Type\":\"Chrome\",\"Device_Type\":\"Desktop\",\"Device_is_Trusted\":\"0\",\"Failed_Signon\":\"0\",\"Forgotten_Password_Reset_Request\":\"0\",\"Invalid_Credentials\":\"0\",\"Is_Device_Managed\":\"0\",\"Operating_System\":\"Mac OS X\",\"Password_Changed\":\"0\",\"Request_Originator\":\"UI\",\"SAML_Identity_Provider\":\"IdP_Acme\",\"Session_End\":\"2026-06-18T23:25:22-07:00\",\"Session_Start\":\"2026-06-18T16:59:32-07:00\",\"System_Account\":\"user534.acme / User 534\"}", + "outcome": "success", + "start": "2026-06-18T23:59:32.000Z", + "type": [ + "start", + "end" + ] + }, + "host": { + "entity": { + "attributes": { + "managed": false + }, + "lifecycle": { + "last_activity": "2026-06-18T23:59:32.000Z" + } + }, + "os": { + "name": "Mac OS X" + } + }, + "user_agent": { + "name": "Chrome" + }, + "workday": { + "sign_on": { + "Account_Locked__Disabled_or_Expired": false, + "Active_Session": false, + "Authentication_Type_for_Signon": "SAML", + "Browser_Type": "Chrome", + "Device_is_Trusted": false, + "Failed_Signon": false, + "Forgotten_Password_Reset_Request": false, + "Invalid_Credentials": false, + "Is_Device_Managed": false, + "Password_Changed": false, + "Request_Originator": "UI", + "SAML_Identity_Provider": "IdP_Acme", + "System_Account": "user534.acme / User 534" + } + } + }, + { + "@timestamp": "2026-06-18T23:55:34.000Z", + "ecs": { + "version": "9.4.0" + }, + "event": { + "action": "user-signon", + "category": [ + "authentication", + "session" + ], + "end": "2026-06-19T05:55:34.000Z", + "kind": "event", + "original": "{\"Account_Locked__Disabled_or_Expired\":\"0\",\"Active_Session\":\"0\",\"Authentication_Type_for_Signon\":\"OAuth 2.0\",\"Device_is_Trusted\":\"0\",\"Failed_Signon\":\"0\",\"Forgotten_Password_Reset_Request\":\"0\",\"Invalid_Credentials\":\"0\",\"Is_Device_Managed\":\"0\",\"Password_Changed\":\"0\",\"Request_Originator\":\"Internal\",\"Session_End\":\"2026-06-18T22:55:34-07:00\",\"Session_Start\":\"2026-06-18T16:55:34-07:00\",\"System_Account\":\"ISU_Integration_049\"}", + "outcome": "success", + "start": "2026-06-18T23:55:34.000Z", + "type": [ + "start", + "end" + ] + }, + "host": { + "entity": { + "attributes": { + "managed": false + }, + "lifecycle": { + "last_activity": "2026-06-18T23:55:34.000Z" + } + } + }, + "workday": { + "sign_on": { + "Account_Locked__Disabled_or_Expired": false, + "Active_Session": false, + "Authentication_Type_for_Signon": "OAuth 2.0", + "Device_is_Trusted": false, + "Failed_Signon": false, + "Forgotten_Password_Reset_Request": false, + "Invalid_Credentials": false, + "Is_Device_Managed": false, + "Password_Changed": false, + "Request_Originator": "Internal", + "System_Account": "ISU_Integration_049" + } + } + }, + { + "@timestamp": "2026-06-18T23:52:43.000Z", + "device": { + "type": "Phone" + }, + "ecs": { + "version": "9.4.0" + }, + "event": { + "action": "user-signon", + "category": [ + "authentication", + "session" + ], + "kind": "event", + "original": "{\"Account_Locked__Disabled_or_Expired\":\"0\",\"Active_Session\":\"0\",\"Authentication_Failure_Message\":\"Mobile PIN has expired. To reset your PIN, first sign in using your user name and password.\",\"Authentication_Type_for_Signon\":\"Biometric\",\"Browser_Type\":\"Workday Phone App\",\"Device_Type\":\"Phone\",\"Device_is_Trusted\":\"0\",\"Failed_Signon\":\"1\",\"Forgotten_Password_Reset_Request\":\"0\",\"Invalid_Credentials\":\"0\",\"Is_Device_Managed\":\"0\",\"Operating_System\":\"iOS\",\"Password_Changed\":\"0\",\"Request_Originator\":\"UI\",\"Session_Start\":\"2026-06-18T16:52:43-07:00\",\"System_Account\":\"user179.acme / User 179\",\"UI_Client_Type\":\"iPhone Native\"}", + "outcome": "failure", + "reason": "Mobile PIN has expired. To reset your PIN, first sign in using your user name and password.", + "start": "2026-06-18T23:52:43.000Z", + "type": [ + "start" + ] + }, + "host": { + "entity": { + "attributes": { + "managed": false + }, + "lifecycle": { + "last_activity": "2026-06-18T23:52:43.000Z" + } + }, + "os": { + "name": "iOS" + } + }, + "user_agent": { + "name": "Workday Phone App" + }, + "workday": { + "sign_on": { + "Account_Locked__Disabled_or_Expired": false, + "Active_Session": false, + "Authentication_Type_for_Signon": "Biometric", + "Browser_Type": "Workday Phone App", + "Device_is_Trusted": false, + "Failed_Signon": true, + "Forgotten_Password_Reset_Request": false, + "Invalid_Credentials": false, + "Is_Device_Managed": false, + "Password_Changed": false, + "Request_Originator": "UI", + "System_Account": "user179.acme / User 179", + "UI_Client_Type": "iPhone Native" + } + } + }, + { + "@timestamp": "2026-06-18T23:57:04.000Z", + "device": { + "type": "Phone" + }, + "ecs": { + "version": "9.4.0" + }, + "event": { + "action": "user-signon", + "category": [ + "authentication", + "session" + ], + "end": "2026-06-19T05:59:33.000Z", + "kind": "event", + "original": "{\"Account_Locked__Disabled_or_Expired\":\"0\",\"Active_Session\":\"0\",\"Authentication_Type_for_Signon\":\"SAML\",\"Browser_Type\":\"Workday Phone App\",\"Device_Type\":\"Phone\",\"Device_is_Trusted\":\"0\",\"Failed_Signon\":\"0\",\"Forgotten_Password_Reset_Request\":\"0\",\"Invalid_Credentials\":\"0\",\"Is_Device_Managed\":\"0\",\"Operating_System\":\"iOS\",\"Password_Changed\":\"0\",\"Request_Originator\":\"UI\",\"SAML_Identity_Provider\":\"IdP_Acme\",\"Session_End\":\"2026-06-18T22:59:33-07:00\",\"Session_Start\":\"2026-06-18T16:57:04-07:00\",\"System_Account\":\"user179.acme / User 179\"}", + "outcome": "success", + "start": "2026-06-18T23:57:04.000Z", + "type": [ + "start", + "end" + ] + }, + "host": { + "entity": { + "attributes": { + "managed": false + }, + "lifecycle": { + "last_activity": "2026-06-18T23:57:04.000Z" + } + }, + "os": { + "name": "iOS" + } + }, + "user_agent": { + "name": "Workday Phone App" + }, + "workday": { + "sign_on": { + "Account_Locked__Disabled_or_Expired": false, + "Active_Session": false, + "Authentication_Type_for_Signon": "SAML", + "Browser_Type": "Workday Phone App", + "Device_is_Trusted": false, + "Failed_Signon": false, + "Forgotten_Password_Reset_Request": false, + "Invalid_Credentials": false, + "Is_Device_Managed": false, + "Password_Changed": false, + "Request_Originator": "UI", + "SAML_Identity_Provider": "IdP_Acme", + "System_Account": "user179.acme / User 179" + } + } + }, + { + "@timestamp": "2026-06-18T20:18:51.000Z", + "ecs": { + "version": "9.4.0" + }, + "event": { + "action": "user-signon", + "category": [ + "authentication", + "session" + ], + "kind": "event", + "original": "{\"Account_Locked__Disabled_or_Expired\":\"0\",\"Active_Session\":\"1\",\"Authentication_Type_for_Signon\":\"User Name Password\",\"Device_is_Trusted\":\"0\",\"Failed_Signon\":\"0\",\"Forgotten_Password_Reset_Request\":\"0\",\"Invalid_Credentials\":\"0\",\"Is_Device_Managed\":\"0\",\"Password_Changed\":\"0\",\"Request_Originator\":\"Web Services\",\"Session_Start\":\"2026-06-18T13:18:51-07:00\",\"System_Account\":\"ISU_Integration_001\"}", + "outcome": "success", + "start": "2026-06-18T20:18:51.000Z", + "type": [ + "start" + ] + }, + "host": { + "entity": { + "attributes": { + "managed": false + }, + "lifecycle": { + "last_activity": "2026-06-18T20:18:51.000Z" + } + } + }, + "workday": { + "sign_on": { + "Account_Locked__Disabled_or_Expired": false, + "Active_Session": true, + "Authentication_Type_for_Signon": "User Name Password", + "Device_is_Trusted": false, + "Failed_Signon": false, + "Forgotten_Password_Reset_Request": false, + "Invalid_Credentials": false, + "Is_Device_Managed": false, + "Password_Changed": false, + "Request_Originator": "Web Services", + "System_Account": "ISU_Integration_001" + } + } + }, + { + "@timestamp": "2026-06-22T08:08:10.000Z", + "device": { + "type": "Desktop" + }, + "ecs": { + "version": "9.4.0" + }, + "event": { + "action": "user-signon", + "category": [ + "authentication", + "session" + ], + "created": "2026-06-22T08:08:10.374Z", + "end": "2026-06-22T09:09:01.000Z", + "kind": "event", + "original": "{\"Authentication_Type\":\"SAML\",\"Browser_Type\":\"Chrome\",\"Created_Moment\":\"2026-06-22T01:08:10.374-07:00\",\"Device_Type\":\"Desktop\",\"Device_is_Trusted\":\"0\",\"Operating_System\":\"Mac OS X\",\"Prompt_-_Positive_Integer\":\"linda.andersson / Linda Andersson\",\"Request_Originator\":\"UI\",\"SAML_Identity_Provider\":\"Okta E2\",\"Session_ID\":\"4562a3\",\"Sign-on_Time\":\"2026-06-22T01:08:10-07:00\",\"Signoff_Time\":\"2026-06-22T02:09:01-07:00\",\"Signon_IP_Address\":\"81.2.69.142\",\"Signon_Worker\":\"Linda Andersson (006193)\",\"User_Agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36\",\"userName\":\"linda.andersson\"}", + "outcome": "success", + "start": "2026-06-22T08:08:10.000Z", + "type": [ + "start", + "end" + ] + }, + "host": { + "entity": { + "lifecycle": { + "last_activity": "2026-06-22T08:08:10.000Z" + } + }, + "os": { + "name": "Mac OS X" + } + }, + "related": { + "ip": [ + "81.2.69.142" + ], + "user": [ + "linda.andersson", + "Linda Andersson (006193)" + ] + }, + "source": { + "geo": { + "city_name": "London", + "continent_name": "Europe", + "country_iso_code": "GB", + "country_name": "United Kingdom", + "location": { + "lat": 51.5142, + "lon": -0.0931 + }, + "region_iso_code": "GB-ENG", + "region_name": "England" + }, + "ip": "81.2.69.142" + }, + "user": { + "full_name": "Linda Andersson (006193)", + "name": "linda.andersson" + }, + "user_agent": { + "device": { + "name": "Mac" + }, + "name": "Chrome", + "original": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36", + "os": { + "full": "Mac OS X 10.15.7", + "name": "Mac OS X", + "version": "10.15.7" + }, + "version": "149.0.0.0" + }, + "workday": { + "sign_on": { + "Authentication_Type": "SAML", + "Browser_Type": "Chrome", + "Device_is_Trusted": false, + "Prompt___Positive_Integer": "linda.andersson / Linda Andersson", + "Request_Originator": "UI", + "SAML_Identity_Provider": "Okta E2", + "Session_ID": "4562a3" + } + } + }, + { + "@timestamp": "2026-06-22T07:44:17.000Z", + "device": { + "type": "Desktop" + }, + "ecs": { + "version": "9.4.0" + }, + "event": { + "action": "user-signon", + "category": [ + "authentication", + "session" + ], + "created": "2026-06-22T07:44:17.617Z", + "end": "2026-06-22T10:35:15.000Z", + "kind": "event", + "original": "{\"Authentication_Type\":\"User Name Password\",\"Browser_Type\":\"Chrome\",\"Created_Moment\":\"2026-06-22T00:44:17.617-07:00\",\"Device_Type\":\"Desktop\",\"Device_is_Trusted\":\"0\",\"Operating_System\":\"Mac OS X\",\"Prompt_-_Positive_Integer\":\"alina.goajga / Alina Garagancea\",\"Request_Originator\":\"UI\",\"Session_ID\":\"b40162\",\"Sign-on_Time\":\"2026-06-22T00:44:17-07:00\",\"Signoff_Time\":\"2026-06-22T03:35:15-07:00\",\"Signon_IP_Address\":\"81.2.69.144\",\"Signon_Worker\":\"Alina Garagancea (002036)\",\"User_Agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36\",\"userName\":\"alina.goajga\"}", + "outcome": "success", + "start": "2026-06-22T07:44:17.000Z", + "type": [ + "start", + "end" + ] + }, + "host": { + "entity": { + "lifecycle": { + "last_activity": "2026-06-22T07:44:17.000Z" + } + }, + "os": { + "name": "Mac OS X" + } + }, + "related": { + "ip": [ + "81.2.69.144" + ], + "user": [ + "alina.goajga", + "Alina Garagancea (002036)" + ] + }, + "source": { + "geo": { + "city_name": "London", + "continent_name": "Europe", + "country_iso_code": "GB", + "country_name": "United Kingdom", + "location": { + "lat": 51.5142, + "lon": -0.0931 + }, + "region_iso_code": "GB-ENG", + "region_name": "England" + }, + "ip": "81.2.69.144" + }, + "user": { + "full_name": "Alina Garagancea (002036)", + "name": "alina.goajga" + }, + "user_agent": { + "device": { + "name": "Mac" + }, + "name": "Chrome", + "original": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36", + "os": { + "full": "Mac OS X 10.15.7", + "name": "Mac OS X", + "version": "10.15.7" + }, + "version": "149.0.0.0" + }, + "workday": { + "sign_on": { + "Authentication_Type": "User Name Password", + "Browser_Type": "Chrome", + "Device_is_Trusted": false, + "Prompt___Positive_Integer": "alina.goajga / Alina Garagancea", + "Request_Originator": "UI", + "Session_ID": "b40162" + } + } + }, + { + "@timestamp": "2026-06-22T07:04:11.000Z", + "device": { + "type": "Desktop" + }, + "ecs": { + "version": "9.4.0" + }, + "event": { + "action": "user-signon", + "category": [ + "authentication", + "session" + ], + "created": "2026-06-22T07:04:11.094Z", + "end": "2026-06-22T08:04:11.000Z", + "kind": "event", + "original": "{\"Authentication_Type\":\"Trusted\",\"Created_Moment\":\"2026-06-22T00:04:11.094-07:00\",\"Device_Type\":\"Desktop\",\"Device_is_Trusted\":\"0\",\"Prompt_-_Positive_Integer\":\"ISU_Adaptive_Insights_User_Provisioning\",\"Request_Originator\":\"Internal\",\"Session_ID\":\"89d613\",\"Sign-on_Time\":\"2026-06-22T00:04:11-07:00\",\"Signoff_Time\":\"2026-06-22T01:04:11-07:00\",\"Signon_IP_Address\":\"Workday Internal\",\"userName\":\"ISU_Adaptive_Insights_User_Provisioning\"}", + "outcome": "success", + "start": "2026-06-22T07:04:11.000Z", + "type": [ + "start", + "end" + ] + }, + "host": { + "entity": { + "lifecycle": { + "last_activity": "2026-06-22T07:04:11.000Z" + } + } + }, + "related": { + "user": [ + "ISU_Adaptive_Insights_User_Provisioning" + ] + }, + "user": { + "name": "ISU_Adaptive_Insights_User_Provisioning" + }, + "workday": { + "sign_on": { + "Authentication_Type": "Trusted", + "Device_is_Trusted": false, + "Prompt___Positive_Integer": "ISU_Adaptive_Insights_User_Provisioning", + "Request_Originator": "Internal", + "Session_ID": "89d613", + "signon_ip_address_string": "Workday Internal" + } + } + }, + { + "@timestamp": "2026-06-22T11:29:16.000Z", + "ecs": { + "version": "9.4.0" + }, + "event": { + "action": "user-signon", + "category": [ + "authentication", + "session" + ], + "created": "2026-06-22T11:29:16.382Z", + "end": "2026-06-22T12:29:16.000Z", + "kind": "event", + "original": "{\"Authentication_Type\":\"OAuth 2.0\",\"Created_Moment\":\"2026-06-22T04:29:16.382-07:00\",\"Device_is_Trusted\":\"0\",\"Prompt_-_Positive_Integer\":\"ISU_WD_Logs\",\"Request_Originator\":\"Internal\",\"Session_ID\":\"87ed78\",\"Sign-on_Time\":\"2026-06-22T04:29:16-07:00\",\"Signoff_Time\":\"2026-06-22T05:29:16-07:00\",\"Signon_IP_Address\":\"89.160.20.112\",\"userName\":\"ISU_WD_Logs\"}", + "outcome": "success", + "start": "2026-06-22T11:29:16.000Z", + "type": [ + "start", + "end" + ] + }, + "host": { + "entity": { + "lifecycle": { + "last_activity": "2026-06-22T11:29:16.000Z" + } + } + }, + "related": { + "ip": [ + "89.160.20.112" + ], + "user": [ + "ISU_WD_Logs" + ] + }, + "source": { + "as": { + "number": 29518, + "organization": { + "name": "Bredband2 AB" + } + }, + "geo": { + "city_name": "Linköping", + "continent_name": "Europe", + "country_iso_code": "SE", + "country_name": "Sweden", + "location": { + "lat": 58.4167, + "lon": 15.6167 + }, + "region_iso_code": "SE-E", + "region_name": "Östergötland County" + }, + "ip": "89.160.20.112" + }, + "user": { + "name": "ISU_WD_Logs" + }, + "workday": { + "sign_on": { + "Authentication_Type": "OAuth 2.0", + "Device_is_Trusted": false, + "Prompt___Positive_Integer": "ISU_WD_Logs", + "Request_Originator": "Internal", + "Session_ID": "87ed78" + } + } + }, + { + "@timestamp": "2026-06-22T13:41:11.000Z", + "device": { + "type": "Desktop" + }, + "ecs": { + "version": "9.4.0" + }, + "event": { + "action": "user-signon", + "category": [ + "authentication", + "session" + ], + "created": "2026-06-22T13:41:11.320Z", + "kind": "event", + "original": "{\"Authentication_Failure_Message\":\"Invalid password\",\"Authentication_Type\":\"User Name Password\",\"Browser_Type\":\"Chrome\",\"Created_Moment\":\"2026-06-22T06:41:11.320-07:00\",\"Device_Type\":\"Desktop\",\"Device_is_Trusted\":\"0\",\"Operating_System\":\"Mac OS X\",\"Prompt_-_Positive_Integer\":\"chris.carnes / Chris Carnes\",\"Request_Originator\":\"UI\",\"Sign-on_Time\":\"2026-06-22T06:41:11-07:00\",\"Signon_IP_Address\":\"175.16.199.1\",\"Signon_Worker\":\"Chris Carnes (006423)\",\"User_Agent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36\",\"userName\":\"chris.carnes\"}", + "outcome": "failure", + "reason": "Invalid password", + "start": "2026-06-22T13:41:11.000Z", + "type": [ + "start" + ] + }, + "host": { + "entity": { + "lifecycle": { + "last_activity": "2026-06-22T13:41:11.000Z" + } + }, + "os": { + "name": "Mac OS X" + } + }, + "related": { + "ip": [ + "175.16.199.1" + ], + "user": [ + "chris.carnes", + "Chris Carnes (006423)" + ] + }, + "source": { + "geo": { + "city_name": "Changchun", + "continent_name": "Asia", + "country_iso_code": "CN", + "country_name": "China", + "location": { + "lat": 43.88, + "lon": 125.3228 + }, + "region_iso_code": "CN-22", + "region_name": "Jilin Sheng" + }, + "ip": "175.16.199.1" + }, + "user": { + "full_name": "Chris Carnes (006423)", + "name": "chris.carnes" + }, + "user_agent": { + "device": { + "name": "Mac" + }, + "name": "Chrome", + "original": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36", + "os": { + "full": "Mac OS X 10.15.7", + "name": "Mac OS X", + "version": "10.15.7" + }, + "version": "149.0.0.0" + }, + "workday": { + "sign_on": { + "Authentication_Type": "User Name Password", + "Browser_Type": "Chrome", + "Device_is_Trusted": false, + "Prompt___Positive_Integer": "chris.carnes / Chris Carnes", + "Request_Originator": "UI" + } + } + } + ] +} diff --git a/packages/workday/data_stream/sign_on/agent/stream/cel.yml.hbs b/packages/workday/data_stream/sign_on/agent/stream/cel.yml.hbs new file mode 100644 index 00000000000..0de45395879 --- /dev/null +++ b/packages/workday/data_stream/sign_on/agent/stream/cel.yml.hbs @@ -0,0 +1,65 @@ +interval: {{interval}} +resource.tracer: + enabled: {{enable_request_tracer}} + filename: "../../logs/cel/http-request-trace-*.ndjson" + maxbackups: 5 +{{#if proxy_url}} +resource.proxy_url: {{proxy_url}} +{{/if}} +{{#if ssl}} +resource.ssl: {{ssl}} +{{/if}} +{{#if http_client_timeout}} +resource.timeout: {{http_client_timeout}} +{{/if}} +resource.url: {{url}} +auth.basic.user: {{username}} +auth.basic.password: {{password}} +redact: + fields: + - auth.basic.user + - auth.basic.password +program: |- + state.with( + get(state.url).as(resp, + (resp.StatusCode == 200) ? + bytes(resp.Body).decode_json().as(body, + { + "events": (has(body.Report_Entry) && size(body.Report_Entry) > 0) ? + body.Report_Entry.map(e, {"message": e.encode_json()}) + : + [], + } + ) + : + { + "events": { + "error": { + "code": string(resp.StatusCode), + "id": resp.Status, + "message": "GET " + state.url + ": " + ( + (size(resp.Body) != 0) ? + string(resp.Body) + : + resp.Status + " (" + string(resp.StatusCode) + ")" + ), + }, + }, + "want_more": false, + } + ) + ) +tags: +{{#if preserve_original_event}} + - preserve_original_event +{{/if}} +{{#each tags as |tag|}} + - {{tag}} +{{/each}} +{{#contains "forwarded" tags}} +publisher_pipeline.disable_host: true +{{/contains}} +{{#if processors}} +processors: +{{processors}} +{{/if}} diff --git a/packages/workday/data_stream/sign_on/elasticsearch/ilm/default_policy.json b/packages/workday/data_stream/sign_on/elasticsearch/ilm/default_policy.json new file mode 100644 index 00000000000..a2258ec38f8 --- /dev/null +++ b/packages/workday/data_stream/sign_on/elasticsearch/ilm/default_policy.json @@ -0,0 +1,23 @@ +{ + "policy": { + "phases": { + "hot": { + "actions": { + "rollover": { + "max_age": "2d", + "max_size": "50gb" + }, + "set_priority": { + "priority": 100 + } + } + }, + "delete": { + "min_age": "30d", + "actions": { + "delete": {} + } + } + } + } +} diff --git a/packages/workday/data_stream/sign_on/elasticsearch/ingest_pipeline/default.yml b/packages/workday/data_stream/sign_on/elasticsearch/ingest_pipeline/default.yml new file mode 100644 index 00000000000..15efd2080a6 --- /dev/null +++ b/packages/workday/data_stream/sign_on/elasticsearch/ingest_pipeline/default.yml @@ -0,0 +1,466 @@ +--- +description: Pipeline for processing sign-on logs. +processors: + - set: + field: ecs.version + tag: set_ecs_version + value: 9.4.0 + - remove: + field: + - organization + - division + - team + tag: remove_agentless_tags + ignore_missing: true + if: ctx.organization instanceof String && ctx.division instanceof String && ctx.team instanceof String + description: Removes the fields added by Agentless as metadata, as they can collide with ECS fields. + - terminate: + tag: data_collection_error + description: error message set and no data to process. + if: ctx.error?.message != null && ctx.message == null && ctx.event?.original == null + - rename: + field: message + tag: rename_message_to_event_original + target_field: event.original + ignore_missing: true + description: Renames the original `message` field to `event.original` to store a copy of the original message. + if: ctx.event?.original == null + - remove: + field: + - message + tag: remove_message + ignore_missing: true + description: The `message` field is no longer required if the document has an `event.original` field. + if: ctx.event?.original != null + - json: + field: event.original + tag: json_event_original + target_field: workday.sign_on + if: ctx.event?.original != null + - fingerprint: + fields: + - event.original + tag: fingerprint_sign_on + target_field: _id + ignore_missing: true + - script: + tag: normalize_hyphenated_field_names + lang: painless + description: Rename any sign-on fields whose names contain a hyphen to use an underscore instead. + if: ctx.workday?.sign_on instanceof Map + source: |- + def signon = ctx.workday.sign_on; + for (def key : new ArrayList(signon.keySet())) { + if (key.contains('-')) { + signon.put(key.replace('-', '_'), signon.remove(key)); + } + } + - script: + tag: convert_signon_boolean_flags + lang: painless + description: Convert Workday 0/1 string flags to booleans. + if: ctx.workday?.sign_on != null + source: |- + def flags = [ + 'Account_Locked__Disabled_or_Expired', + 'Active_Session', + 'Device_is_Trusted', + 'Failed_Signon', + 'Forgotten_Password_Reset_Request', + 'Invalid_Credentials', + 'Invalid_Password', + 'Is_Device_Managed', + 'Password_Changed', + 'Signon', + 'Successful' + ]; + def signon = ctx.workday.sign_on; + for (def flag : flags) { + if (signon.containsKey(flag) && signon.get(flag) instanceof String) { + signon.put(flag, signon.get(flag) == '1'); + } + } + - date: + field: workday.sign_on.Sign_on_Time + tag: date_signon_time + target_field: workday.sign_on.Sign_on_Time + formats: + - ISO8601 + if: ctx.workday?.sign_on?.Sign_on_Time != null && ctx.workday.sign_on.Sign_on_Time != '' + on_failure: + - append: + field: error.message + value: 'Processor {{{_ingest.on_failure_processor_type}}} with tag {{{_ingest.on_failure_processor_tag}}} in pipeline {{{_ingest.on_failure_pipeline}}} failed with message: {{{_ingest.on_failure_message}}}' + - set: + field: '@timestamp' + tag: set_timestamp_from_signon_time + copy_from: workday.sign_on.Sign_on_Time + ignore_empty_value: true + - set: + field: event.start + tag: set_event_start_from_signon_time + copy_from: workday.sign_on.Sign_on_Time + ignore_empty_value: true + - date: + field: workday.sign_on.Session_Start + tag: date_session_start + target_field: workday.sign_on.Session_Start + formats: + - ISO8601 + if: ctx.workday?.sign_on?.Session_Start != null && ctx.workday.sign_on.Session_Start != '' + on_failure: + - append: + field: error.message + value: 'Processor {{{_ingest.on_failure_processor_type}}} with tag {{{_ingest.on_failure_processor_tag}}} in pipeline {{{_ingest.on_failure_pipeline}}} failed with message: {{{_ingest.on_failure_message}}}' + - set: + field: '@timestamp' + tag: set_timestamp_from_session_start + copy_from: workday.sign_on.Session_Start + ignore_empty_value: true + override: false + - set: + field: event.start + tag: set_event_start_from_session_start + copy_from: workday.sign_on.Session_Start + ignore_empty_value: true + override: false + - date: + field: workday.sign_on.Signon_DateTime + tag: date_signon_datetime + target_field: workday.sign_on.Signon_DateTime + formats: + - ISO8601 + if: ctx.workday?.sign_on?.Signon_DateTime != null && ctx.workday.sign_on.Signon_DateTime != '' + on_failure: + - append: + field: error.message + value: 'Processor {{{_ingest.on_failure_processor_type}}} with tag {{{_ingest.on_failure_processor_tag}}} in pipeline {{{_ingest.on_failure_pipeline}}} failed with message: {{{_ingest.on_failure_message}}}' + - set: + field: '@timestamp' + tag: set_timestamp_from_signon_datetime + copy_from: workday.sign_on.Signon_DateTime + ignore_empty_value: true + override: false + - set: + field: event.start + tag: set_event_start_from_signon_datetime + copy_from: workday.sign_on.Signon_DateTime + ignore_empty_value: true + override: false + - date: + field: workday.sign_on.Session_End + tag: date_session_end + target_field: workday.sign_on.Session_End + formats: + - ISO8601 + if: ctx.workday?.sign_on?.Session_End != null && ctx.workday.sign_on.Session_End != '' + on_failure: + - append: + field: error.message + value: 'Processor {{{_ingest.on_failure_processor_type}}} with tag {{{_ingest.on_failure_processor_tag}}} in pipeline {{{_ingest.on_failure_pipeline}}} failed with message: {{{_ingest.on_failure_message}}}' + - set: + field: event.end + tag: set_event_end_from_session_end + copy_from: workday.sign_on.Session_End + ignore_empty_value: true + override: false + - date: + field: workday.sign_on.Signoff_DateTime + tag: date_signoff_datetime + target_field: workday.sign_on.Signoff_DateTime + formats: + - ISO8601 + if: ctx.workday?.sign_on?.Signoff_DateTime != null && ctx.workday.sign_on.Signoff_DateTime != '' + on_failure: + - append: + field: error.message + value: 'Processor {{{_ingest.on_failure_processor_type}}} with tag {{{_ingest.on_failure_processor_tag}}} in pipeline {{{_ingest.on_failure_pipeline}}} failed with message: {{{_ingest.on_failure_message}}}' + - set: + field: event.end + tag: set_event_end_from_signoff_datetime + copy_from: workday.sign_on.Signoff_DateTime + ignore_empty_value: true + override: false + - date: + field: workday.sign_on.Signoff_Time + tag: date_signoff_time + target_field: workday.sign_on.Signoff_Time + formats: + - ISO8601 + if: ctx.workday?.sign_on?.Signoff_Time != null && ctx.workday.sign_on.Signoff_Time != '' + on_failure: + - append: + field: error.message + value: 'Processor {{{_ingest.on_failure_processor_type}}} with tag {{{_ingest.on_failure_processor_tag}}} in pipeline {{{_ingest.on_failure_pipeline}}} failed with message: {{{_ingest.on_failure_message}}}' + - set: + field: event.end + tag: set_event_end_from_signoff_time + copy_from: workday.sign_on.Signoff_Time + ignore_empty_value: true + - date: + field: workday.sign_on.Created_Moment + tag: date_created_moment + target_field: workday.sign_on.Created_Moment + formats: + - ISO8601 + if: ctx.workday?.sign_on?.Created_Moment != null && ctx.workday.sign_on.Created_Moment != '' + on_failure: + - append: + field: error.message + value: 'Processor {{{_ingest.on_failure_processor_type}}} with tag {{{_ingest.on_failure_processor_tag}}} in pipeline {{{_ingest.on_failure_pipeline}}} failed with message: {{{_ingest.on_failure_message}}}' + - set: + field: event.created + tag: set_event_created_from_created_moment + copy_from: workday.sign_on.Created_Moment + ignore_empty_value: true + - set: + field: user.name + tag: set_user_name_from_username + copy_from: workday.sign_on.userName + ignore_empty_value: true + - set: + field: user.full_name + tag: set_user_full_name_from_signon_worker + copy_from: workday.sign_on.Signon_Worker + ignore_empty_value: true + - set: + field: user_agent.original + tag: set_user_agent_original + copy_from: workday.sign_on.User_Agent + ignore_empty_value: true + - user_agent: + field: user_agent.original + tag: user_agent_parse + ignore_missing: true + - set: + field: host.os.name + tag: set_host_os_name_from_operating_system + copy_from: workday.sign_on.Operating_System + ignore_empty_value: true + - set: + field: device.type + tag: set_device_type_from_device_type + copy_from: workday.sign_on.Device_Type + ignore_empty_value: true + - convert: + field: workday.sign_on.Signon_IP_Address + tag: convert_signon_ip_address_to_source_ip + type: ip + ignore_missing: true + if: ctx.workday?.sign_on?.Signon_IP_Address != '' + on_failure: + - rename: + field: workday.sign_on.Signon_IP_Address + tag: rename_signon_ip_address_to_source_ip + target_field: workday.sign_on.signon_ip_address_string + ignore_missing: true + - set: + field: source.ip + tag: set_source_ip_from_signon_ip_address + copy_from: workday.sign_on.Signon_IP_Address + ignore_empty_value: true + - convert: + field: workday.sign_on.Session_IP_Address + tag: convert_session_ip_address_to_source_ip + type: ip + ignore_missing: true + if: ctx.workday?.sign_on?.Session_IP_Address != '' + on_failure: + - rename: + field: workday.sign_on.Session_IP_Address + tag: rename_session_ip_address_to_source_ip + target_field: workday.sign_on.session_ip_address_string + ignore_missing: true + - set: + field: source.ip + tag: set_source_ip_from_session_ip_address + copy_from: workday.sign_on.Session_IP_Address + ignore_empty_value: true + override: false + - geoip: + field: source.ip + tag: geoip_source_ip_to_source_geo + target_field: source.geo + ignore_missing: true + - geoip: + database_file: GeoLite2-ASN.mmdb + field: source.ip + tag: geoip_source_ip_to_source_as + target_field: source.as + properties: + - asn + - organization_name + ignore_missing: true + - rename: + field: source.as.asn + tag: rename_source_as_asn + target_field: source.as.number + ignore_missing: true + - rename: + field: source.as.organization_name + tag: rename_source_as_organization_name + target_field: source.as.organization.name + ignore_missing: true + - set: + field: event.reason + tag: set_event_reason_from_failure_message + copy_from: workday.sign_on.Authentication_Failure_Message + ignore_empty_value: true + - set: + field: organization.name + tag: set_organization_name_from_tenant_name + copy_from: workday.sign_on.tenant_name + ignore_empty_value: true + - append: + field: related.user + tag: append_related_user_name + value: '{{{user.name}}}' + allow_duplicates: false + if: ctx.user?.name != null + - append: + field: related.user + tag: append_related_user_full_name + value: '{{{user.full_name}}}' + allow_duplicates: false + if: ctx.user?.full_name != null + - append: + field: related.ip + tag: append_related_ip + value: '{{{source.ip}}}' + allow_duplicates: false + if: ctx.source?.ip != null + - set: + field: user_agent.name + tag: set_user_agent_name_from_browser_type + copy_from: workday.sign_on.Browser_Type + ignore_empty_value: true + override: false + - set: + field: event.kind + tag: set_event_kind + value: event + - append: + field: event.category + tag: append_authentication_into_event_category + value: authentication + allow_duplicates: false + - append: + field: event.category + tag: append_session_into_event_category + value: session + allow_duplicates: false + - append: + field: event.type + tag: append_start_into_event_type + value: start + allow_duplicates: false + - append: + field: event.type + tag: append_end_into_event_type + value: end + allow_duplicates: false + if: ctx.event?.end != null + - set: + field: event.action + tag: set_event_action + value: user-signon + - set: + field: event.outcome + tag: set_event_outcome_failure + value: failure + if: ctx.workday?.sign_on?.Failed_Signon == true || ctx.event?.reason != null + - set: + field: event.outcome + tag: set_event_outcome_success + value: success + if: ctx.event?.outcome == null + - set: + field: host.entity.attributes.managed + tag: set_host_entity_managed_from_is_device_managed + copy_from: workday.sign_on.Is_Device_Managed + ignore_empty_value: true + if: ctx.workday?.sign_on?.Is_Device_Managed instanceof Boolean + - set: + field: host.entity.lifecycle.last_activity + tag: set_host_entity_last_activity_from_event_end + copy_from: event.end + ignore_empty_value: true + override: false + - set: + field: host.entity.lifecycle.last_activity + tag: set_host_entity_last_activity_from_event_start + copy_from: event.start + ignore_empty_value: true + - remove: + field: + - workday.sign_on.Session_Start + - workday.sign_on.Session_End + - workday.sign_on.Sign_on_Time + - workday.sign_on.Created_Moment + - workday.sign_on.userName + - workday.sign_on.Signon_Worker + - workday.sign_on.User_Agent + - workday.sign_on.Operating_System + - workday.sign_on.Device_Type + - workday.sign_on.Signon_IP_Address + - workday.sign_on.Session_IP_Address + - workday.sign_on.Authentication_Failure_Message + - workday.sign_on.tenant_name + - workday.sign_on.Signon_DateTime + - workday.sign_on.Signoff_DateTime + - workday.sign_on.Signoff_Time + tag: remove_custom_fields_mapped_with_ecs_fields + ignore_missing: true + - script: + tag: remove_null_values + lang: painless + description: Remove null or empty values from the document. + source: |- + void handleMap(Map map) { + map.values().removeIf(v -> { + if (v instanceof Map) { + handleMap(v); + } else if (v instanceof List) { + handleList(v); + } + return v == null || v == '' || (v instanceof Map && v.size() == 0) || (v instanceof List && v.size() == 0) + }); + } + void handleList(List list) { + list.removeIf(v -> { + if (v instanceof Map) { + handleMap(v); + } else if (v instanceof List) { + handleList(v); + } + return v == null || v == '' || (v instanceof Map && v.size() == 0) || (v instanceof List && v.size() == 0) + }); + } + handleMap(ctx); + - set: + field: event.kind + tag: set_pipeline_error_into_event_kind + value: pipeline_error + if: ctx.error?.message != null + - append: + field: tags + tag: append_tags + value: preserve_original_event + allow_duplicates: false + if: ctx.error?.message != null +on_failure: + - append: + field: error.message + value: |- + Processor '{{{_ingest.on_failure_processor_type}}}' + {{{#_ingest.on_failure_processor_tag}}}with tag '{{{_ingest.on_failure_processor_tag}}}}' + {{{/_ingest.on_failure_processor_tag}}}failed with message '{{{_ingest.on_failure_message}}}' + - set: + field: event.kind + tag: set_pipeline_error_to_event_kind + value: pipeline_error + - append: + field: tags + tag: append_tags + value: preserve_original_event + allow_duplicates: false diff --git a/packages/workday/data_stream/sign_on/fields/base-fields.yml b/packages/workday/data_stream/sign_on/fields/base-fields.yml new file mode 100644 index 00000000000..c628adfdbbc --- /dev/null +++ b/packages/workday/data_stream/sign_on/fields/base-fields.yml @@ -0,0 +1,16 @@ +- name: data_stream.dataset + external: ecs +- name: data_stream.namespace + external: ecs +- name: data_stream.type + external: ecs +- name: event.dataset + type: constant_keyword + external: ecs + value: workday.sign_on +- name: event.module + type: constant_keyword + external: ecs + value: workday +- name: '@timestamp' + external: ecs diff --git a/packages/workday/data_stream/sign_on/fields/beats.yml b/packages/workday/data_stream/sign_on/fields/beats.yml new file mode 100644 index 00000000000..3c48f1f224f --- /dev/null +++ b/packages/workday/data_stream/sign_on/fields/beats.yml @@ -0,0 +1,3 @@ +- name: input.type + type: keyword + description: Type of Filebeat input. diff --git a/packages/workday/data_stream/sign_on/fields/ecs.yml b/packages/workday/data_stream/sign_on/fields/ecs.yml new file mode 100644 index 00000000000..8ef9acda203 --- /dev/null +++ b/packages/workday/data_stream/sign_on/fields/ecs.yml @@ -0,0 +1,5 @@ +# Define ECS constant fields as constant_keyword +- name: observer.vendor + external: ecs + type: constant_keyword + value: Workday diff --git a/packages/workday/data_stream/sign_on/fields/fields.yml b/packages/workday/data_stream/sign_on/fields/fields.yml new file mode 100644 index 00000000000..b055d1fe7c3 --- /dev/null +++ b/packages/workday/data_stream/sign_on/fields/fields.yml @@ -0,0 +1,87 @@ +- name: workday + type: group + fields: + - name: sign_on + type: group + fields: + - name: Account + type: keyword + description: The Workday account associated with the sign-on (for example, the account user name and worker display name). + - name: Account_Locked__Disabled_or_Expired + type: boolean + description: Whether the account was locked, disabled, or expired at the time of the sign-on. + - name: Active_Session + type: boolean + description: Whether the session was still active at the time the report was generated. + - name: Authentication_Channel + type: keyword + description: The channel through which the sign-on was performed (for example, Web, Mobile, API). + - name: Authentication_Type + type: keyword + description: The authentication method used for the sign-on (for example, SAML, OAuth 2.0, Trusted, User Name Password, ID Token). + - name: Authentication_Type_for_Signon + type: keyword + description: The authentication method used for the sign-on (for example, SAML, OAuth 2.0, Biometric, User Name Password). + - name: Browser_Type + type: keyword + description: The browser or client application used for the sign-on (for example, Chrome, Workday Phone App). + - name: Device_is_Trusted + type: boolean + description: Whether the device used for the sign-on is trusted. + - name: Failed_Signon + type: boolean + description: Whether the sign-on attempt failed. + - name: Forgotten_Password_Reset_Request + type: boolean + description: Whether the sign-on was associated with a forgotten password reset request. + - name: Invalid_Credentials + type: boolean + description: Whether the sign-on attempt was made with invalid credentials. + - name: Invalid_Password + type: boolean + description: Whether the sign-on attempt was made with an invalid password. + - name: Is_Device_Managed + type: boolean + description: Whether the device used for the sign-on is managed. + - name: Multi_Factor_Type + type: keyword + description: The type of multi-factor authentication used for the sign-on. + - name: Password_Changed + type: boolean + description: Whether the password was changed during the sign-on. + - name: Prompt___Positive_Integer + type: keyword + description: The sign-on prompt value as reported by Workday, typically the account name and worker display name. + - name: Request_Originator + type: keyword + description: The originator of the sign-on request (for example, UI, Internal, Web Services). + - name: Required_Multi_Factor + type: keyword + description: The type of multi-factor authentication required for the sign-on (for example, SMS, Email, Phone, Security Key). + - name: SAML_Identity_Provider + type: keyword + description: The SAML identity provider used for the sign-on. + - name: Session_ID + type: keyword + description: The Workday session identifier associated with the sign-on. + - name: session_ip_address_string + type: keyword + description: The originating IP address of the session (alternate report column name for Session_IP_Address). + - name: signon_ip_address_string + type: keyword + description: The originating IP address of the sign-on (alternate report column name for Signon_IP_Address). + - name: Signon + type: boolean + description: Whether the sign-on attempt was successful. + - name: Successful + type: boolean + description: Whether the sign-on attempt was successful. + - name: System_Account + type: keyword + description: The Workday system account associated with the sign-on (for example, the account user name and worker display name). + - name: UI_Client_Type + type: keyword + description: The type of UI client used for the sign-on (for example, iPhone Native, Android Native). + - name: Workday_Account + type: keyword + description: The Workday account associated with the sign-on (alternate report column name for System_Account). diff --git a/packages/workday/data_stream/sign_on/manifest.yml b/packages/workday/data_stream/sign_on/manifest.yml new file mode 100644 index 00000000000..8392d10bfec --- /dev/null +++ b/packages/workday/data_stream/sign_on/manifest.yml @@ -0,0 +1,83 @@ +title: Sign-on +type: logs +ilm_policy: logs-workday.sign_on-default_policy +streams: + - input: cel + title: Sign-on logs + description: Collect Sign-on logs from Workday. + template_path: cel.yml.hbs + vars: + - name: url + type: text + title: Report URL + description: 'Full URL of the Workday Custom Report (Reports as a Service / RaaS JSON endpoint). Example: `https://.workday.com/ccx/service/customreport2///?format=json`.' + multi: false + required: true + show_user: true + - name: username + type: text + title: Username + description: Username for basic authentication against the Workday Custom Report API (usually the Integration System User). + multi: false + required: true + show_user: true + - name: password + type: password + title: Password + description: Password for basic authentication against the Workday Custom Report API. + multi: false + required: true + show_user: true + secret: true + - name: interval + type: text + title: Interval + description: Duration between requests to the Workday Custom Report API. Supported units for this parameter are h/m/s. + default: 24h + multi: false + required: true + show_user: true + - name: http_client_timeout + type: text + title: HTTP Client Timeout + description: Duration before declaring that the HTTP client connection has timed out. Valid time units are ns, us, ms, s, m, h. + multi: false + required: true + show_user: false + default: 5m + - name: enable_request_tracer + type: bool + title: Enable request tracing + multi: false + required: false + show_user: false + default: false + description: >- + The request tracer logs requests and responses to the agent's local file-system for debugging configurations. Enabling this request tracing compromises security and should only be used for debugging. Disabling the request tracer will delete any stored traces. See [documentation](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-input-cel.html#_resource_tracer_enable) for details. + - name: tags + type: text + title: Tags + multi: true + required: true + show_user: false + default: + - forwarded + - workday-sign_on + - name: preserve_original_event + required: true + show_user: true + title: Preserve original event + description: Preserves a raw copy of the original event, added to the field event.original. + type: bool + multi: false + default: false + - name: processors + type: yaml + title: Processors + multi: false + required: false + show_user: false + description: |- + Processors are used to reduce the number of fields in the exported event or to enhance the event with metadata. + This executes in the agent before the logs are parsed. + See [Processors](https://www.elastic.co/guide/en/beats/filebeat/current/filtering-and-enhancing-data.html) for details. diff --git a/packages/workday/docs/README.md b/packages/workday/docs/README.md index b9ee8dd956a..c5f172ef527 100644 --- a/packages/workday/docs/README.md +++ b/packages/workday/docs/README.md @@ -4,35 +4,36 @@ [Workday](https://www.workday.com/en-in/homepage.html) is a cloud-based ERP system that manages business processes and allows organizations to use an integrated application. Workday is a coherent cloud ERP system for financial analysis, analytical solutions, HCM suites, and better business processes. -The Workday integration for Elastic collects `Activity Logs` via **API** and visualizes them in Kibana. +The Workday integration for Elastic collects `Activity` logs via the **Workday API** and `Sign-on` logs via the **Workday Custom Report API**, and visualizes them in Kibana. ### Compatibility -The Workday integration is compatible with API version **v1**. +- The **Activity** data stream is compatible with Workday API version **v1**. +- The **Sign-on** data stream is compatible with Workday Custom Reports exposed via the **Reports as a Service (RaaS)** JSON endpoint (`/ccx/service/customreport2/...?format=json`). ### How it works -This integration periodically queries the Workday API to retrieve logs. +- **Activity**: This integration periodically queries the Workday API to retrieve Activity logs. +- **Sign-on**: This integration periodically downloads a Workday Custom Report (for example, a Sign-on report that lists sign-on records along with their key attributes) and ingests each report row as a single event. ## What data does this integration collect? -This integration collects log messages of the following type: +This integration collects log messages of the following types: -- `Activity`: Collects [Activity Logs](https://community.workday.com/sites/default/files/file-hosting/restapi/#privacy/v1/get-/activityLogging) logs via Workday API (endpoint: `/activityLogging`). +- `Activity`: Collects [Activity Logs](https://community.workday.com/sites/default/files/file-hosting/restapi/#privacy/v1/get-/activityLogging) via the Workday API (endpoint: `/activityLogging`). +- `Sign-on`: Collects sign-on information from a Workday Custom Report via the Workday Reports as a Service (RaaS) JSON endpoint. ### Supported use cases -Integrating Workday with Elastic gives security and IT teams centralized visibility into **Workday activity logging**, so you can monitor configuration and usage changes, support audits, and investigate suspicious behavior from Kibana. +Integrating Workday with Elastic gives security and IT teams centralized visibility into **Workday activity logging** and **Workday sign-on data**, so you can monitor configuration and usage changes, track sign-on activity and access patterns, support audits, and investigate suspicious or unusual authentication behavior from Kibana. -The **Activity** dashboard summarizes key patterns such as **activity volume over time** and **top actors**, helping you spot unusual spikes and focus on the users and operations that matter. - -Built-in filters make it easier to narrow events by attributes such as **task**, **system account**, and **IP address**, which supports faster triage and a more consistent investigation workflow across your Workday telemetry. +The **Activity** dashboard summarizes key patterns such as **activity volume over time** and **top actors**, helping you spot unusual spikes and focus on the users and operations that matter. Built-in filters make it easier to narrow events by attributes such as **task**, **system account**, and **IP address**, which supports faster triage and a more consistent investigation workflow across your Workday telemetry. ## What do I need to use this integration? ### From Workday -#### Collect Workday API credentials +#### For the Activity data stream ##### Enable User Activity Logging @@ -43,7 +44,7 @@ Built-in filters make it easier to narrow events by attributes such as **task**, **Note:** Once enabled, Workday records all user activity in a secure tenant database. Activity logging must be enabled before any logs are available for export. -#### Create Integration System User (ISU) +##### Create Integration System User (ISU) 1. In the Workday search bar, search for Create Integration System User. 2. Enter a User Name (for example, ISU_SIEM_Export) and a strong Password. @@ -54,7 +55,7 @@ Built-in filters make it easier to narrow events by attributes such as **task**, 7. Search for View Domain and locate the User Activity Logging domain. Grant Get access to the ISU security group for this domain. 8. Search for Activate Pending Security Policy Changes and activate the changes. -#### Register API client for OAuth +##### Register API client for OAuth 1. In the Workday search bar, search for Register API Client for Integrations. 2. Enter a Client Name (for example, SIEM_OAuth_Client). @@ -69,7 +70,7 @@ Built-in filters make it easier to narrow events by attributes such as **task**, 9. Generate a new refresh token for the API client. 10. Copy and save the Refresh Token. -#### Determine tenant URL +##### Determine tenant URL The API endpoint is based on your Workday tenant. The format is: @@ -83,6 +84,43 @@ Activity Logging API | https://HOST/ccx/api/privacy/v1/TENANT/activityLogging **Note:** For additional Workday API security context, see [Generating API Keys for the Workday API](https://workday.my.site.com/customercenter/article?no=000013105&redirect=false). +#### For the Sign-on data stream + +##### Build the Sign-on custom report + +1. Sign in to your Workday tenant as a user with report-authoring privileges. +2. In the Workday search bar, search for **Create Custom Report**. +3. Create an Advanced report on a data source that exposes sign-on activity (for example, `Signons and Attempted Signons`). +4. Add the columns required for sign-on analytics (for example, `System Account`, `Session Start`, `Session End`, `Authentication Type for Signon`, `Failed Signon`, `Invalid Credentials`, `Account Locked, Disabled or Expired`, `Browser Type`, `Operating System`, `Device Type`, `Request Originator`, `SAML Identity Provider`). +5. On the **Advanced** tab, select **Enable As Web Service** so the report is exposed as Reports as a Service (RaaS). +6. Save the report and note the **Report Name** and the **Report Owner** (the Workday account that owns the report). + +##### Create the Integration System User (ISU) + +1. In the Workday search bar, search for **Create Integration System User**. +2. Enter a User Name (for example, `ISU_SIEM_Export`) and a strong Password. +3. Clear the **Require New Password at Next Sign In** checkbox. +4. Click **OK**. +5. Search for **Create Security Group** and create an Integration System Security Group (Unconstrained). +6. Add the ISU (`ISU_SIEM_Export`) to this security group. +7. Grant the ISU security group access to the domain protecting the custom report's data source (for example, the `System Auditing` domain). +8. Search for **Activate Pending Security Policy Changes** and activate the changes. + +##### Determine the report URL + +The Custom Report endpoint URL has the following format: + +``` +https://HOST/ccx/service/customreport2/TENANT/REPORT_OWNER/REPORT_NAME?format=json +``` + +Where: + +- `HOST` is your Workday hostname. +- `TENANT` is your Workday tenant name. +- `REPORT_OWNER` is the Workday account that owns the custom report. +- `REPORT_NAME` is the name of the custom report you created above. + ## How do I deploy this integration? This integration supports both Elastic Agentless-based and Agent-based installations. @@ -105,7 +143,7 @@ Elastic Agent must be installed. For more details, check the Elastic Agent [inst 4. Select **Add Workday** to add the integration. 5. Enable and configure only the collection methods which you will use. - * To **Collect Workday logs via API**, you'll need to: + * To **Collect Workday Activity logs via API**, you'll need to: - Configure **Hostname**. - Configure **Tenant**. @@ -114,6 +152,12 @@ Elastic Agent must be installed. For more details, check the Elastic Agent [inst - Configure **Refresh Token**. - Adjust the integration configuration parameters if required, including the **Interval**, **Initial Interval**, **Preserve original event** etc. to enable data collection. + * To **Collect Workday Sign-on logs via Custom Report API**, you'll need to: + + - Configure **Report URL** with the full Workday Custom Report (RaaS) URL noted above. + - Configure **Username** and **Password** for basic authentication against the Workday Custom Report API. + - Adjust the integration configuration parameters if required, including the **Interval** and **Preserve original event** etc. to enable data collection. + 6. Select **Save and continue** to save the integration. ### Validation @@ -160,6 +204,49 @@ For more information on architectures that can be used for scaling this integrat | workday.activity.user_activity_entry_count | Returns the User Activity Count for the inputted filter parameters. | long | +#### Sign-on + +**Exported fields** + +| Field | Description | Type | +|---|---|---| +| @timestamp | Date/time when the event originated. This is the date/time extracted from the event, typically representing when the event was generated by the source. If the event source has no original timestamp, this value is typically populated by the first time the event was received by the pipeline. Required field for all events. | date | +| data_stream.dataset | The field can contain anything that makes sense to signify the source of the data. Examples include `nginx.access`, `prometheus`, `endpoint` etc. For data streams that otherwise fit, but that do not have dataset set we use the value "generic" for the dataset value. `event.dataset` should have the same value as `data_stream.dataset`. Beyond the Elasticsearch data stream naming criteria noted above, the `dataset` value has additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.namespace | A user defined namespace. Namespaces are useful to allow grouping of data. Many users already organize their indices this way, and the data stream naming scheme now provides this best practice as a default. Many users will populate this field with `default`. If no value is used, it falls back to `default`. Beyond the Elasticsearch index naming criteria noted above, `namespace` value has the additional restrictions: \* Must not contain `-` \* No longer than 100 characters | constant_keyword | +| data_stream.type | An overarching type for the data stream. Currently allowed values are "logs" and "metrics". We expect to also add "traces" and "synthetics" in the near future. | constant_keyword | +| event.dataset | Name of the dataset. If an event source publishes more than one type of log or events (e.g. access log, error log), the dataset is used to specify which one the event comes from. It's recommended but not required to start the dataset name with the module name, followed by a dot, then the dataset name. | constant_keyword | +| event.module | Name of the module this data is coming from. If your monitoring agent supports the concept of modules or plugins to process events of a given source (e.g. Apache logs), `event.module` should contain the name of this module. | constant_keyword | +| input.type | Type of Filebeat input. | keyword | +| observer.vendor | Vendor name of the observer. | constant_keyword | +| workday.sign_on.Account | The Workday account associated with the sign-on (for example, the account user name and worker display name). | keyword | +| workday.sign_on.Account_Locked__Disabled_or_Expired | Whether the account was locked, disabled, or expired at the time of the sign-on. | boolean | +| workday.sign_on.Active_Session | Whether the session was still active at the time the report was generated. | boolean | +| workday.sign_on.Authentication_Channel | The channel through which the sign-on was performed (for example, Web, Mobile, API). | keyword | +| workday.sign_on.Authentication_Type | The authentication method used for the sign-on (for example, SAML, OAuth 2.0, Trusted, User Name Password, ID Token). | keyword | +| workday.sign_on.Authentication_Type_for_Signon | The authentication method used for the sign-on (for example, SAML, OAuth 2.0, Biometric, User Name Password). | keyword | +| workday.sign_on.Browser_Type | The browser or client application used for the sign-on (for example, Chrome, Workday Phone App). | keyword | +| workday.sign_on.Device_is_Trusted | Whether the device used for the sign-on is trusted. | boolean | +| workday.sign_on.Failed_Signon | Whether the sign-on attempt failed. | boolean | +| workday.sign_on.Forgotten_Password_Reset_Request | Whether the sign-on was associated with a forgotten password reset request. | boolean | +| workday.sign_on.Invalid_Credentials | Whether the sign-on attempt was made with invalid credentials. | boolean | +| workday.sign_on.Invalid_Password | Whether the sign-on attempt was made with an invalid password. | boolean | +| workday.sign_on.Is_Device_Managed | Whether the device used for the sign-on is managed. | boolean | +| workday.sign_on.Multi_Factor_Type | The type of multi-factor authentication used for the sign-on. | keyword | +| workday.sign_on.Password_Changed | Whether the password was changed during the sign-on. | boolean | +| workday.sign_on.Prompt___Positive_Integer | The sign-on prompt value as reported by Workday, typically the account name and worker display name. | keyword | +| workday.sign_on.Request_Originator | The originator of the sign-on request (for example, UI, Internal, Web Services). | keyword | +| workday.sign_on.Required_Multi_Factor | The type of multi-factor authentication required for the sign-on (for example, SMS, Email, Phone, Security Key). | keyword | +| workday.sign_on.SAML_Identity_Provider | The SAML identity provider used for the sign-on. | keyword | +| workday.sign_on.Session_ID | The Workday session identifier associated with the sign-on. | keyword | +| workday.sign_on.Signon | Whether the sign-on attempt was successful. | boolean | +| workday.sign_on.Successful | Whether the sign-on attempt was successful. | boolean | +| workday.sign_on.System_Account | The Workday system account associated with the sign-on (for example, the account user name and worker display name). | keyword | +| workday.sign_on.UI_Client_Type | The type of UI client used for the sign-on (for example, iPhone Native, Android Native). | keyword | +| workday.sign_on.Workday_Account | The Workday account associated with the sign-on (alternate report column name for System_Account). | keyword | +| workday.sign_on.session_ip_address_string | The originating IP address of the session (alternate report column name for Session_IP_Address). | keyword | +| workday.sign_on.signon_ip_address_string | The originating IP address of the sign-on (alternate report column name for Signon_IP_Address). | keyword | + + ### Example event #### Activity @@ -254,12 +341,17 @@ An example event for `activity` looks as following: ### Inputs used -These input is used in the integration: +These inputs are used in the integration: - [CEL](https://www.elastic.co/docs/reference/beats/filebeat/filebeat-input-cel) ### API usage -This integration uses the following Workday API: +This integration uses the following Workday APIs: + +- **Activity**: [Workday Activity API documentation](https://community.workday.com/sites/default/files/file-hosting/restapi/#privacy/v1/get-/activityLogging). +- **Sign-on**: The Workday **Reports as a Service (RaaS)** JSON endpoint is used to fetch a user-defined Sign-on custom report: -**Activity**: [Workday Activity API documentation](https://community.workday.com/sites/default/files/file-hosting/restapi/#privacy/v1/get-/activityLogging). +``` +GET https://HOST/ccx/service/customreport2/TENANT/REPORT_OWNER/REPORT_NAME?format=json +``` diff --git a/packages/workday/img/workday-signon-dashboard.png b/packages/workday/img/workday-signon-dashboard.png new file mode 100644 index 00000000000..6034edc1e44 Binary files /dev/null and b/packages/workday/img/workday-signon-dashboard.png differ diff --git a/packages/workday/kibana/dashboard/workday-36544d7d-809c-4306-a2b0-6276bad0a9b6.json b/packages/workday/kibana/dashboard/workday-36544d7d-809c-4306-a2b0-6276bad0a9b6.json new file mode 100644 index 00000000000..32d4640480a --- /dev/null +++ b/packages/workday/kibana/dashboard/workday-36544d7d-809c-4306-a2b0-6276bad0a9b6.json @@ -0,0 +1,1382 @@ +{ + "attributes": { + "controlGroupInput": { + "chainingSystem": "HIERARCHICAL", + "controlStyle": "oneLine", + "ignoreParentSettingsJSON": { + "ignoreFilters": false, + "ignoreQuery": false, + "ignoreTimerange": false, + "ignoreValidations": false + }, + "panelsJSON": { + "0c598211-5777-402f-89ae-2f05488a5f0d": { + "explicitInput": { + "dataViewId": "logs-*", + "fieldName": "workday.sign_on.Authentication_Type", + "searchTechnique": "prefix", + "selectedOptions": [], + "sort": { + "by": "_count", + "direction": "desc" + }, + "title": "Authentication Type" + }, + "grow": false, + "order": 0, + "type": "optionsListControl", + "width": "medium" + }, + "c2e0d9b7-f9cf-4fd8-aa16-8f6eda164975": { + "explicitInput": { + "dataViewId": "logs-*", + "fieldName": "workday.sign_on.Device_is_Trusted", + "searchTechnique": "prefix", + "selectedOptions": [], + "sort": { + "by": "_count", + "direction": "desc" + }, + "title": "Device Trusted" + }, + "grow": false, + "order": 1, + "type": "optionsListControl", + "width": "medium" + }, + "edec393f-95df-4e4e-ae38-c0497d1fe869": { + "explicitInput": { + "dataViewId": "logs-*", + "fieldName": "workday.sign_on.Request_Originator", + "searchTechnique": "prefix", + "selectedOptions": [], + "sort": { + "by": "_count", + "direction": "desc" + }, + "title": "Request Originator" + }, + "grow": false, + "order": 2, + "type": "optionsListControl", + "width": "medium" + } + }, + "showApplySelections": false + }, + "description": "Overview of Sign-on report from Workday in Elastic.", + "kibanaSavedObjectMeta": { + "searchSourceJSON": { + "filter": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "data_stream.dataset", + "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index", + "key": "data_stream.dataset", + "negate": false, + "params": { + "query": "workday.sign_on" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.sign_on" + } + } + } + ], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "optionsJSON": { + "hidePanelTitles": false, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false, + "useMargins": true + }, + "panelsJSON": [ + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "logs-*", + "name": "indexpattern-datasource-layer-ed94c77f-d603-4fbc-8185-e9fcdaf73c13", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "c7c491a9-307c-4f3b-9884-dd49c9aae83b", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "ed94c77f-d603-4fbc-8185-e9fcdaf73c13": { + "columnOrder": [ + "f12e75b9-e798-4f81-8baf-575f59df4ed8" + ], + "columns": { + "f12e75b9-e798-4f81-8baf-575f59df4ed8": { + "customLabel": true, + "dataType": "number", + "filter": { + "language": "kuery", + "query": "user.name: * " + }, + "isBucketed": false, + "label": "Total Users", + "operationType": "count", + "params": { + "emptyAsNull": false + }, + "scale": "ratio", + "sourceField": "___records___" + } + }, + "ignoreGlobalFilters": false, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "data_stream.dataset", + "index": "c7c491a9-307c-4f3b-9884-dd49c9aae83b", + "key": "data_stream.dataset", + "negate": false, + "params": { + "query": "workday.sign_on" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.sign_on" + } + } + } + ], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "color": "#6092C0", + "layerId": "ed94c77f-d603-4fbc-8185-e9fcdaf73c13", + "layerType": "data", + "metricAccessor": "f12e75b9-e798-4f81-8baf-575f59df4ed8" + } + }, + "title": "", + "type": "lens", + "visualizationType": "lnsMetric" + }, + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "data_stream.dataset", + "index": "logs-*", + "key": "data_stream.dataset", + "negate": false, + "params": { + "query": "workday.sign_on" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.sign_on" + } + } + } + ], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 8, + "i": "61edd668-677d-4a6d-bad5-1dd933ce7f91", + "w": 6, + "x": 10, + "y": 0 + }, + "panelIndex": "61edd668-677d-4a6d-bad5-1dd933ce7f91", + "type": "lens" + }, + { + "embeddableConfig": { + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "fontSize": 12, + "markdown": "### Overview\n\nThe Workday Sign-On dashboard provides security and IT teams visibility into authentication activity from the Workday Sign-On custom report, covering sign-on volume, authentication methods, and failure patterns.\n\nThe Total Users tile shows authenticated account scope, while Sign-ons by Authentication Type and Distribution of Authentication Types break down usage across SAML, OAuth 2.0, Trusted, Username/Password, and ID Token.\n\nTop Source IPs surfaces active originating addresses for investigation, Top SAML Identity Providers highlights federated sign-in sources, and the Failure Breakdown table helps teams quickly triage authentication failures.\n\n[**Integration Page**](https://127.0.0.1:5601/app/integrations/detail/workday/overview)\n", + "openLinksInNewTab": false + }, + "title": "", + "type": "markdown", + "uiState": {} + } + }, + "gridData": { + "h": 26, + "i": "818c4437-a43b-42fa-b984-cffc555904db", + "w": 10, + "x": 0, + "y": 0 + }, + "panelIndex": "818c4437-a43b-42fa-b984-cffc555904db", + "type": "visualization" + }, + { + "embeddableConfig": { + "attributes": { + "description": "", + "references": [ + { + "id": "logs-*", + "name": "indexpattern-datasource-layer-5cbeccd0-6531-4711-9804-e70d4fae58c3", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "4012a977-cb0d-4f6e-84d1-e0ef45527f65", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "5cbeccd0-6531-4711-9804-e70d4fae58c3": { + "columnOrder": [ + "4313cef6-1fe7-45d6-9301-bb491b6bc6b4", + "7a37c05a-b4b2-48ab-93cf-dda57c0ed2e9", + "16720ed3-c834-42e6-aecc-1441fcf1bab9" + ], + "columns": { + "16720ed3-c834-42e6-aecc-1441fcf1bab9": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Count", + "operationType": "count", + "params": { + "emptyAsNull": false + }, + "scale": "ratio", + "sourceField": "___records___" + }, + "4313cef6-1fe7-45d6-9301-bb491b6bc6b4": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Authentication Type", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "16720ed3-c834-42e6-aecc-1441fcf1bab9", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 5 + }, + "scale": "ordinal", + "sourceField": "workday.sign_on.Authentication_Type" + }, + "7a37c05a-b4b2-48ab-93cf-dda57c0ed2e9": { + "dataType": "date", + "isBucketed": true, + "label": "@timestamp", + "operationType": "date_histogram", + "params": { + "dropPartials": false, + "includeEmptyRows": true, + "interval": "auto" + }, + "scale": "interval", + "sourceField": "@timestamp" + } + }, + "ignoreGlobalFilters": false, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "data_stream.dataset", + "index": "4012a977-cb0d-4f6e-84d1-e0ef45527f65", + "key": "data_stream.dataset", + "negate": false, + "params": { + "query": "workday.sign_on" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.sign_on" + } + } + } + ], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "layers": [ + { + "accessors": [ + "16720ed3-c834-42e6-aecc-1441fcf1bab9" + ], + "colorMapping": { + "assignments": [], + "colorMode": { + "type": "categorical" + }, + "paletteId": "eui_amsterdam_color_blind", + "specialAssignments": [ + { + "color": { + "type": "loop" + }, + "rule": { + "type": "other" + }, + "touched": false + } + ] + }, + "layerId": "5cbeccd0-6531-4711-9804-e70d4fae58c3", + "layerType": "data", + "position": "top", + "seriesType": "line", + "showGridlines": false, + "splitAccessor": "4313cef6-1fe7-45d6-9301-bb491b6bc6b4", + "xAccessor": "7a37c05a-b4b2-48ab-93cf-dda57c0ed2e9" + } + ], + "legend": { + "isVisible": true, + "position": "right", + "shouldTruncate": false, + "showSingleSeries": true + }, + "preferredSeriesType": "line", + "title": "Empty XY chart", + "valueLabels": "hide" + } + }, + "title": "Sign-ons by Authentication Type over Time", + "visualizationType": "lnsXY" + }, + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "data_stream.dataset", + "index": "logs-*", + "key": "data_stream.dataset", + "negate": false, + "params": { + "query": "workday.sign_on" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.sign_on" + } + } + } + ], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 8, + "i": "c9279b48-fdf6-461c-a921-4bb4bb37014f", + "w": 32, + "x": 16, + "y": 0 + }, + "panelIndex": "c9279b48-fdf6-461c-a921-4bb4bb37014f", + "title": "Sign-ons by Authentication Type over Time", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "description": "", + "references": [ + { + "id": "logs-*", + "name": "indexpattern-datasource-layer-bf0d1fd4-4afd-45a6-9a0a-28973d1e8038", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "currentIndexPatternId": "logs-*", + "layers": { + "bf0d1fd4-4afd-45a6-9a0a-28973d1e8038": { + "columnOrder": [ + "f365c27f-6d06-4b4d-af88-7c019e5c9ef9", + "254ca83f-cfea-4386-b20e-a565d7a390cf" + ], + "columns": { + "254ca83f-cfea-4386-b20e-a565d7a390cf": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Count", + "operationType": "count", + "params": { + "emptyAsNull": false + }, + "scale": "ratio", + "sourceField": "___records___" + }, + "f365c27f-6d06-4b4d-af88-7c019e5c9ef9": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Authentication Type", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "254ca83f-cfea-4386-b20e-a565d7a390cf", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 5 + }, + "scale": "ordinal", + "sourceField": "workday.sign_on.Authentication_Type" + } + }, + "ignoreGlobalFilters": false, + "incompleteColumns": {}, + "indexPatternId": "logs-*", + "sampling": 1 + } + } + }, + "indexpattern": { + "currentIndexPatternId": "logs-*", + "layers": {} + }, + "textBased": { + "indexPatternRefs": [ + { + "id": "logs-*", + "timeField": "@timestamp", + "title": "logs-*" + } + ], + "layers": {} + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "data_stream.dataset", + "index": "logs-*", + "key": "data_stream.dataset", + "negate": false, + "params": { + "query": "workday.sign_on" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.sign_on" + } + } + } + ], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "layers": [ + { + "categoryDisplay": "default", + "colorMapping": { + "assignments": [], + "colorMode": { + "type": "categorical" + }, + "paletteId": "eui_amsterdam_color_blind", + "specialAssignments": [ + { + "color": { + "type": "loop" + }, + "rule": { + "type": "other" + }, + "touched": false + } + ] + }, + "layerId": "bf0d1fd4-4afd-45a6-9a0a-28973d1e8038", + "layerType": "data", + "legendDisplay": "show", + "metrics": [ + "254ca83f-cfea-4386-b20e-a565d7a390cf" + ], + "nestedLegend": false, + "numberDisplay": "percent", + "primaryGroups": [ + "f365c27f-6d06-4b4d-af88-7c019e5c9ef9" + ], + "truncateLegend": false + } + ], + "shape": "pie" + } + }, + "title": "Distribution of Authentication Types", + "visualizationType": "lnsPie" + }, + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "data_stream.dataset", + "index": "logs-*", + "key": "data_stream.dataset", + "negate": false, + "params": { + "query": "workday.sign_on" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.sign_on" + } + } + } + ], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 8, + "i": "4fe5b7d0-37b3-43da-8b4a-299283f333a8", + "w": 19, + "x": 10, + "y": 8 + }, + "panelIndex": "4fe5b7d0-37b3-43da-8b4a-299283f333a8", + "title": "Distribution of Authentication Types", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "description": "", + "references": [ + { + "id": "logs-*", + "name": "indexpattern-datasource-layer-c860a377-5c00-4d60-a715-60984b9dbdcf", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "8201a6d7-8b14-4c1d-b6e5-f9b2e1c8328c", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "c860a377-5c00-4d60-a715-60984b9dbdcf": { + "columnOrder": [ + "40565dd6-cde1-4ed8-840a-49953a79bca3", + "a256ead7-901c-4de6-9f16-39068cf2d509" + ], + "columns": { + "40565dd6-cde1-4ed8-840a-49953a79bca3": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "SAML Identity Provider", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "a256ead7-901c-4de6-9f16-39068cf2d509", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "secondaryFields": [], + "size": 10 + }, + "scale": "ordinal", + "sourceField": "workday.sign_on.SAML_Identity_Provider" + }, + "a256ead7-901c-4de6-9f16-39068cf2d509": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Count", + "operationType": "count", + "params": { + "emptyAsNull": false + }, + "scale": "ratio", + "sourceField": "___records___" + } + }, + "ignoreGlobalFilters": false, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "data_stream.dataset", + "index": "8201a6d7-8b14-4c1d-b6e5-f9b2e1c8328c", + "key": "data_stream.dataset", + "negate": false, + "params": { + "query": "workday.sign_on" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.sign_on" + } + } + } + ], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "layers": [ + { + "accessors": [ + "a256ead7-901c-4de6-9f16-39068cf2d509" + ], + "colorMapping": { + "assignments": [], + "colorMode": { + "type": "categorical" + }, + "paletteId": "eui_amsterdam_color_blind", + "specialAssignments": [ + { + "color": { + "type": "loop" + }, + "rule": { + "type": "other" + }, + "touched": false + } + ] + }, + "layerId": "c860a377-5c00-4d60-a715-60984b9dbdcf", + "layerType": "data", + "position": "top", + "seriesType": "bar_stacked", + "showGridlines": false, + "xAccessor": "40565dd6-cde1-4ed8-840a-49953a79bca3" + } + ], + "legend": { + "isVisible": true, + "position": "right" + }, + "preferredSeriesType": "bar_stacked", + "title": "Empty XY chart", + "valueLabels": "hide" + } + }, + "title": "Top SAML Identity Providers", + "visualizationType": "lnsXY" + }, + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "data_stream.dataset", + "index": "logs-*", + "key": "data_stream.dataset", + "negate": false, + "params": { + "query": "workday.sign_on" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.sign_on" + } + } + } + ], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 8, + "i": "8f464d7d-4e11-4797-9fce-6d8713d3cae3", + "w": 18, + "x": 29, + "y": 8 + }, + "panelIndex": "8f464d7d-4e11-4797-9fce-6d8713d3cae3", + "title": "Top SAML Identity Providers", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "description": "", + "references": [ + { + "id": "logs-*", + "name": "indexpattern-datasource-layer-5605db3e-28cb-4bc2-a001-d3b89dd54ba2", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "5605db3e-28cb-4bc2-a001-d3b89dd54ba2": { + "columnOrder": [ + "192badc3-4529-4512-bec5-5325ede95dcb", + "0593f0ea-189b-41a4-bf8e-da409a763be5" + ], + "columns": { + "0593f0ea-189b-41a4-bf8e-da409a763be5": { + "customLabel": true, + "dataType": "number", + "filter": { + "language": "kuery", + "query": "" + }, + "isBucketed": false, + "label": "Count", + "operationType": "count", + "params": { + "emptyAsNull": false + }, + "scale": "ratio", + "sourceField": "___records___" + }, + "192badc3-4529-4512-bec5-5325ede95dcb": { + "customLabel": true, + "dataType": "ip", + "isBucketed": true, + "label": "Source IP", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "0593f0ea-189b-41a4-bf8e-da409a763be5", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": false, + "parentFormat": { + "id": "terms" + }, + "size": 10 + }, + "scale": "ordinal", + "sourceField": "source.ip" + } + }, + "ignoreGlobalFilters": false, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "data_stream.dataset", + "index": "logs-*", + "key": "data_stream.dataset", + "negate": false, + "params": { + "query": "workday.sign_on" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.sign_on" + } + } + } + ], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "columns": [ + { + "columnId": "192badc3-4529-4512-bec5-5325ede95dcb", + "isMetric": false, + "isTransposed": false + }, + { + "columnId": "0593f0ea-189b-41a4-bf8e-da409a763be5", + "isMetric": true, + "isTransposed": false + } + ], + "layerId": "5605db3e-28cb-4bc2-a001-d3b89dd54ba2", + "layerType": "data" + } + }, + "title": "Top Source IPs", + "visualizationType": "lnsDatatable" + }, + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "data_stream.dataset", + "index": "logs-*", + "key": "data_stream.dataset", + "negate": false, + "params": { + "query": "workday.sign_on" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.sign_on" + } + } + } + ], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 9, + "i": "e3c11871-1b4b-45e6-ae14-3ce8f8c935f0", + "w": 19, + "x": 10, + "y": 16 + }, + "panelIndex": "e3c11871-1b4b-45e6-ae14-3ce8f8c935f0", + "title": "Top Source IPs", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "description": "", + "references": [ + { + "id": "logs-*", + "name": "indexpattern-datasource-layer-5749a443-ee17-4a72-b728-b44e73c7c30e", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "d57b06b9-2c09-4076-9e64-ace7dc90e07e", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "5749a443-ee17-4a72-b728-b44e73c7c30e": { + "columnOrder": [ + "d59fbc38-11f8-40ad-83b0-de3a72c9efa7", + "9feeb0d2-2a25-4c9d-96ef-e97477951955", + "dd930aa7-7490-44d9-94cf-19f8dec084c9" + ], + "columns": { + "9feeb0d2-2a25-4c9d-96ef-e97477951955": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Authentication Type", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "dd930aa7-7490-44d9-94cf-19f8dec084c9", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": false, + "parentFormat": { + "id": "terms" + }, + "size": 10 + }, + "scale": "ordinal", + "sourceField": "workday.sign_on.Authentication_Type" + }, + "d59fbc38-11f8-40ad-83b0-de3a72c9efa7": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Authentication Failure Message", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "dd930aa7-7490-44d9-94cf-19f8dec084c9", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": false, + "parentFormat": { + "id": "terms" + }, + "size": 10 + }, + "scale": "ordinal", + "sourceField": "event.reason" + }, + "dd930aa7-7490-44d9-94cf-19f8dec084c9": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Count", + "operationType": "count", + "params": { + "emptyAsNull": false + }, + "scale": "ratio", + "sourceField": "___records___" + } + }, + "ignoreGlobalFilters": false, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "data_stream.dataset", + "index": "d57b06b9-2c09-4076-9e64-ace7dc90e07e", + "key": "data_stream.dataset", + "negate": false, + "params": { + "query": "workday.sign_on" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.sign_on" + } + } + } + ], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "columns": [ + { + "columnId": "d59fbc38-11f8-40ad-83b0-de3a72c9efa7", + "isMetric": false, + "isTransposed": false + }, + { + "columnId": "9feeb0d2-2a25-4c9d-96ef-e97477951955", + "isMetric": false, + "isTransposed": false + }, + { + "columnId": "dd930aa7-7490-44d9-94cf-19f8dec084c9", + "isMetric": true, + "isTransposed": false + } + ], + "layerId": "5749a443-ee17-4a72-b728-b44e73c7c30e", + "layerType": "data" + } + }, + "title": "Failure Breakdown", + "visualizationType": "lnsDatatable" + }, + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "data_stream.dataset", + "index": "logs-*", + "key": "data_stream.dataset", + "negate": false, + "params": { + "query": "workday.sign_on" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.sign_on" + } + } + } + ], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 9, + "i": "70cba3c3-4d4c-4601-b79c-83f0d867aae6", + "w": 19, + "x": 29, + "y": 16 + }, + "panelIndex": "70cba3c3-4d4c-4601-b79c-83f0d867aae6", + "title": "Failure Breakdown", + "type": "lens" + } + ], + "timeRestore": false, + "title": "[Logs Workday] Sign On Report Overview", + "version": 3 + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-07-09T10:10:23.783Z", + "id": "workday-36544d7d-809c-4306-a2b0-6276bad0a9b6", + "references": [ + { + "id": "logs-*", + "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "61edd668-677d-4a6d-bad5-1dd933ce7f91:indexpattern-datasource-layer-ed94c77f-d603-4fbc-8185-e9fcdaf73c13", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "61edd668-677d-4a6d-bad5-1dd933ce7f91:c7c491a9-307c-4f3b-9884-dd49c9aae83b", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "c9279b48-fdf6-461c-a921-4bb4bb37014f:indexpattern-datasource-layer-5cbeccd0-6531-4711-9804-e70d4fae58c3", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "c9279b48-fdf6-461c-a921-4bb4bb37014f:4012a977-cb0d-4f6e-84d1-e0ef45527f65", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "4fe5b7d0-37b3-43da-8b4a-299283f333a8:indexpattern-datasource-layer-bf0d1fd4-4afd-45a6-9a0a-28973d1e8038", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "8f464d7d-4e11-4797-9fce-6d8713d3cae3:indexpattern-datasource-layer-c860a377-5c00-4d60-a715-60984b9dbdcf", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "8f464d7d-4e11-4797-9fce-6d8713d3cae3:8201a6d7-8b14-4c1d-b6e5-f9b2e1c8328c", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "e3c11871-1b4b-45e6-ae14-3ce8f8c935f0:indexpattern-datasource-layer-5605db3e-28cb-4bc2-a001-d3b89dd54ba2", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "70cba3c3-4d4c-4601-b79c-83f0d867aae6:indexpattern-datasource-layer-5749a443-ee17-4a72-b728-b44e73c7c30e", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "70cba3c3-4d4c-4601-b79c-83f0d867aae6:d57b06b9-2c09-4076-9e64-ace7dc90e07e", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "controlGroup_0c598211-5777-402f-89ae-2f05488a5f0d:optionsListDataView", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "controlGroup_c2e0d9b7-f9cf-4fd8-aa16-8f6eda164975:optionsListDataView", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "controlGroup_edec393f-95df-4e4e-ae38-c0497d1fe869:optionsListDataView", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index", + "type": "index-pattern" + } + ], + "type": "dashboard", + "typeMigrationVersion": "10.2.0", + "updated_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0" +} \ No newline at end of file diff --git a/packages/workday/manifest.yml b/packages/workday/manifest.yml index 8fc8dee9d51..e7a2918e77b 100644 --- a/packages/workday/manifest.yml +++ b/packages/workday/manifest.yml @@ -1,14 +1,14 @@ -format_version: 3.3.2 +format_version: 3.4.2 name: workday title: 'Workday' -version: 0.1.0 +version: 0.1.1 description: 'Collect logs from Workday with Elastic Agent.' type: integration categories: - security conditions: kibana: - version: '^8.18.0 || ^9.0.0' + version: '^8.18.0 || ^9.1.0' elastic: subscription: 'basic' screenshots: @@ -16,6 +16,10 @@ screenshots: title: Activity Dashboard size: 600x600 type: image/png + - src: /img/workday-signon-dashboard.png + title: Workday Sign On Dashboard + size: 600x600 + type: image/png icons: - src: /img/workday-logo.svg title: Workday logo @@ -38,41 +42,6 @@ policy_templates: title: Collect Workday logs via API description: Collecting logs from Workday via CEL input. vars: - - name: hostname - type: text - title: Hostname - description: 'Hostname of Workday instance. Example: .workday.com' - required: true - show_user: true - - name: tenant - type: text - title: Tenant - description: Tenant of Workday instance. - required: true - show_user: true - - name: client_id - type: text - title: Client ID - multi: false - required: true - show_user: true - description: Client ID. - - name: client_secret - type: password - title: Client Secret - multi: false - required: true - show_user: true - secret: true - description: Client Secret. - - name: refresh_token - type: text - title: Refresh Token - description: Refresh token for Workday instance. - multi: false - required: true - show_user: true - secret: true - name: proxy_url type: text title: Proxy URL