diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 0a6b9fbe905..b16a11c9a47 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -599,6 +599,7 @@ /packages/withsecure_elements @elastic/security-service-integrations @elastic/sit-crest-contractors /packages/wiz @elastic/security-service-integrations @elastic/sit-crest-contractors /packages/wmi @elastic/obs-infraobs-integrations +/packages/workday @elastic/security-service-integrations /packages/zeek @elastic/integration-experience /packages/zerofox @elastic/security-service-integrations @elastic/sit-crest-contractors /packages/zeronetworks @elastic/security-service-integrations @elastic/sit-crest-contractors diff --git a/packages/workday/_dev/build/build.yml b/packages/workday/_dev/build/build.yml new file mode 100644 index 00000000000..32921896292 --- /dev/null +++ b/packages/workday/_dev/build/build.yml @@ -0,0 +1,3 @@ +dependencies: + ecs: + reference: git@v9.3.0 diff --git a/packages/workday/_dev/build/docs/README.md b/packages/workday/_dev/build/docs/README.md new file mode 100644 index 00000000000..a259d6a13c5 --- /dev/null +++ b/packages/workday/_dev/build/docs/README.md @@ -0,0 +1,159 @@ +# Workday + +## Overview + +[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. + +### Compatibility + +The Workday integration is compatible with API version **v1**. + +### How it works + +This integration periodically queries the Workday API to retrieve logs. + +## What data does this integration collect? + +This integration collects log messages of the following type: + +- `Activity`: Collects [Activity Logs](https://community.workday.com/sites/default/files/file-hosting/restapi/#privacy/v1/get-/activityLogging) logs via Workday API (endpoint: `/activityLogging`). + +### 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. + +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 + +##### Enable User Activity Logging + +1. Sign in to your Workday tenant as a Security Administrator. +2. In the Workday search bar, search for and open the Edit Tenant Setup - System task. +3. In the Security section, select the Enable User Activity Logging checkbox. +4. Click OK to save the changes. + +**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) + +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. 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 + +1. In the Workday search bar, search for Register API Client for Integrations. +2. Enter a Client Name (for example, SIEM_OAuth_Client). +3. Select the Non-Expiring Refresh Tokens option. +4. Add the scope: System (or the scope required for User Activity Logging API). +5. Click OK. +6. Copy and save the following details in a secure location: + - Client ID: The API client identifier. + - Client Secret: The API client secret. +7. Search for Manage Refresh Tokens for Integrations. +8. Select the ISU account (ISU_SIEM_Export). +9. Generate a new refresh token for the API client. +10. Copy and save the Refresh Token. + +#### Determine tenant URL + +The API endpoint is based on your Workday tenant. The format is: + +Component | Value + +Token endpoint | https://HOST/ccx/oauth2/TENANT/token + +Activity Logging API | https://HOST/ccx/api/privacy/v1/TENANT/activityLogging + +**Note:** Replace HOST with your Workday hostname and TENANT with your tenant name. + +**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). + +## How do I deploy this integration? + +This integration supports both Elastic Agentless-based and Agent-based installations. + +### Agentless-based installation + +Agentless integrations allow you to collect data without having to manage Elastic Agent in your cloud. They make manual agent deployment unnecessary, so you can focus on your data instead of the agent that collects it. For more information, refer to [Agentless integrations](https://www.elastic.co/guide/en/serverless/current/security-agentless-integrations.html) and the [Agentless integrations FAQ](https://www.elastic.co/guide/en/serverless/current/agentless-integration-troubleshooting.html). + +Agentless deployments are only supported in Elastic Serverless and Elastic Cloud environments. This functionality is in beta and is subject to change. Beta features are not subject to the support SLA of official GA features. + +### Agent-based installation + +Elastic Agent must be installed. For more details, check the Elastic Agent [installation instructions](docs-content://reference/fleet/install-elastic-agents.md). You can install only one Elastic Agent per host. + +### Configure the integration + +1. In the top search bar in Kibana, search for **Integrations**. +2. In the search bar, type **Workday**. +3. Select the **Workday** integration from the search results. +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: + + - Configure **Hostname**. + - Configure **Tenant**. + - Configure **Client ID**. + - Configure **Client Secret**. + - Configure **Refresh Token**. + - Adjust the integration configuration parameters if required, including the **Interval**, **Initial Interval**, **Preserve original event** etc. to enable data collection. + +6. Select **Save and continue** to save the integration. + +### Validation + +#### Dashboard populated + +1. In the top search bar in Kibana, search for **Dashboards**. +2. In the search bar, type **Workday**. +3. Select a dashboard for the dataset you are collecting, and verify the dashboard information is populated. + +## Troubleshooting + +For help with Elastic ingest tools, check [Common problems](https://www.elastic.co/docs/troubleshoot/ingest/fleet/common-problems). + +## Performance and scaling + +For more information on architectures that can be used for scaling this integration, check the [Ingest Architectures](https://www.elastic.co/docs/manage-data/ingest/ingest-reference-architectures) documentation. + +## Reference + +### ECS field reference + +#### Activity + +{{fields "activity"}} + +### Example event + +#### Activity + +{{event "activity"}} + +### Inputs used + +These input is 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: + +**Activity**: [Workday Activity API documentation](https://community.workday.com/sites/default/files/file-hosting/restapi/#privacy/v1/get-/activityLogging). diff --git a/packages/workday/_dev/deploy/docker/docker-compose.yml b/packages/workday/_dev/deploy/docker/docker-compose.yml new file mode 100644 index 00000000000..93098cd82c0 --- /dev/null +++ b/packages/workday/_dev/deploy/docker/docker-compose.yml @@ -0,0 +1,17 @@ +version: '3.0' +services: + workday: + image: docker.elastic.co/observability/stream:v0.20.0 + hostname: workday + ports: + - 8090 + volumes: + - ./files:/files:ro + environment: + PORT: '8090' + command: + - http-server + - --addr=:8090 + - --config=/files/config.yml + - --tls-cert=/files/workday.crt + - --tls-key=/files/workday.key diff --git a/packages/workday/_dev/deploy/docker/files/config.yml b/packages/workday/_dev/deploy/docker/files/config.yml new file mode 100644 index 00000000000..d2c396f558c --- /dev/null +++ b/packages/workday/_dev/deploy/docker/files/config.yml @@ -0,0 +1,152 @@ +rules: + - path: /ccx/oauth2/tenant/token + methods: ['POST'] + query_params: + grant_type: ['refresh_token'] + refresh_token: ['refresh_token'] + client_id: ['client_id'] + client_secret: ['client_secret'] + responses: + - status_code: 200 + headers: + Content-Type: application/json + body: | + {{ minify_json ` + { + "access_token": "xxxx", + "token_type": "Bearer", + "refresh_token": "refresh_token" + } + `}} + - path: /ccx/api/privacy/v1/tenant/activityLogging + methods: ['GET'] + query_params: + offset: ['0'] + limit: ['2'] + from: ['{from:.*}'] + to: ['{to:.*}'] + request_headers: + Authorization: + - 'Bearer xxxx' + responses: + - status_code: 200 + headers: + Content-Type: + - application/json + body: | + {{ minify_json ` + { + "total": 5, + "data": [ + { + "activityAction": "READ", + "taskId": "e67b812850dc100047be196f396d745f", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36", + "requestTime": "2026-04-02T12:46:18.012Z", + "taskDisplayName": "privacy/activityLogging/userActivity (GET) (v1 - )", + "systemAccount": "wd-implementer", + "deviceType": "Desktop", + "ipAddress": "127.0.0.1", + "sessionId": "c7c6ff" + }, + { + "activityAction": "READ", + "systemAccount": "wd-implementer", + "requestTime": "2026-04-07T08:02:58.655Z", + "taskDisplayName": "Get OMS Session Data (Web Service)", + "sessionId": "c91278", + "target": { + "descriptor": "wd-implementer / Workday Implementer", + "id": "64700e15a04847f6ac13343b007478e3" + }, + "taskId": "dc1bea8c446c11de98360015c5e6daf6", + "ipAddress": "127.0.0.1", + "deviceType": "Desktop", + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36" + } + ] + } + `}} + - path: /ccx/api/privacy/v1/tenant/activityLogging + methods: ['GET'] + query_params: + offset: ['2'] + limit: ['2'] + from: ['{from:.*}'] + to: ['{to:.*}'] + request_headers: + Authorization: + - 'Bearer xxxx' + responses: + - status_code: 200 + headers: + Content-Type: + - application/json + body: | + {{ minify_json ` + { + "total": 5, + "data": [ + { + "activityAction": "OTHER", + "systemAccount": "wd-implementer", + "requestTime": "2026-04-07T10:29:14.163Z", + "taskDisplayName": "absenceManagement/balances/view (GET) (v1 - )", + "sessionId": "2b6938", + "taskId": "842800d7bb0210006a09e472785f010b", + "ipAddress": "127.0.0.1", + "deviceType": "Desktop", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36 Edg/146.0.0.0" + }, + { + "activityAction": "READ", + "systemAccount": "wd-implementer", + "requestTime": "2026-04-07T18:34:42.548Z", + "taskDisplayName": "Submit OAuth 2.0 Consent (Web Service)", + "sessionId": "a5097e", + "taskId": "8b086034c8ec49e79b0f13af87e911ea", + "ipAddress": "127.0.0.1", + "deviceType": "Desktop", + "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36" + } + ] + } + `}} + - path: /ccx/api/privacy/v1/tenant/activityLogging + methods: ['GET'] + query_params: + offset: ['4'] + limit: ['2'] + from: ['{from:.*}'] + to: ['{to:.*}'] + request_headers: + Authorization: + - 'Bearer xxxx' + responses: + - status_code: 200 + headers: + Content-Type: + - application/json + body: | + {{ minify_json ` + { + "total": 5, + "data": [ + { + "activityAction": "READ", + "systemAccount": "wd-implementer", + "requestTime": "2026-04-07T19:03:29.024Z", + "taskDisplayName": "Get OMS Session Data (Web Service)", + "sessionId": "6fe14f", + "target": { + "descriptor": "wd-implementer / Workday Implementer", + "id": "64700e15a04847f6ac13343b007478e3" + }, + "taskId": "dc1bea8c446c11de98360015c5e6daf6", + "ipAddress": "127.0.0.1", + "deviceType": "Desktop", + "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36" + } + ] + } + `}} diff --git a/packages/workday/_dev/deploy/docker/files/workday.crt b/packages/workday/_dev/deploy/docker/files/workday.crt new file mode 100644 index 00000000000..283d8b84c5b --- /dev/null +++ b/packages/workday/_dev/deploy/docker/files/workday.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDJTCCAg2gAwIBAgIUV+67DSMtT/+uSt4qDbY6IDwlJawwDQYJKoZIhvcNAQEL +BQAwFjEUMBIGA1UEAwwLc3ZjLXdvcmtkYXkwHhcNMjYwNjAxMTMwODIxWhcNMzYw +NTI5MTMwODIxWjAWMRQwEgYDVQQDDAtzdmMtd29ya2RheTCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBAKGf75wHU2B9niPdBS+QKuvQwWhtfPJxWtwpBtj6 +hqleBEAD1+fq02u0hflu9rEBxCcXYt8cQzVd0cW4zUvqk+78lwIcv3NelyHcwsEu +sfAhFXnL08axQVYc3oYzy2dQNnYH7lEGmY8/N31umXeTojPlDji9xTaExQ6Mj83y +QXQ1DajdHlirw8Qf8cnKPZtW50zyf7MGSTYiLgOvv9pFhwLL8eMKhJo23+c+B7GI +lGUOzQZV9VfzgQRpDpRnLeKghRwltverMkadxXlVAKlbXuhSDJluo2NCZ3+wBrj4 +IuMX0+IB6o6eZWnnJgPrQ5DN4WJdwjmmMQ7LTyUw3/hXjw0CAwEAAaNrMGkwHQYD +VR0OBBYEFDla3DE7Dm0f35w6PiMqslosh2HNMB8GA1UdIwQYMBaAFDla3DE7Dm0f +35w6PiMqslosh2HNMA8GA1UdEwEB/wQFMAMBAf8wFgYDVR0RBA8wDYILc3ZjLXdv +cmtkYXkwDQYJKoZIhvcNAQELBQADggEBAGb/wSyfnXpK9z7GqKnJ2JA3RkRdudHT +sy7j0Q0W0Cr6VeVj+paiRwQtMXriNOMzWvJ2cTMRp4l181XMnLvasQTqOASHpM1G +Ra0eEmITzhdJsiyW585fAL+hyvthzo8f4r/9rm3NwDQdFQt9akGw1nnuFzd2+K/b +c0GJiVBgNKp3Q1u7MeEQK/kKjzKP5qsB34aJNxWdzKF7rFaRQPtBcGh15zfxpcOJ +VrEdkgusmHeI8Q4yKPu2Vopaq29dg3iW/FLsXeTAOYeo9KfgSXt3cxMPrrwtJEwG +nWd6q0A8Ec8udGavtotazOi9g+F16fNTaUVk8bXkoTUezwSe/IfGRw4= +-----END CERTIFICATE----- diff --git a/packages/workday/_dev/deploy/docker/files/workday.key b/packages/workday/_dev/deploy/docker/files/workday.key new file mode 100644 index 00000000000..d85ef51d009 --- /dev/null +++ b/packages/workday/_dev/deploy/docker/files/workday.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQChn++cB1NgfZ4j +3QUvkCrr0MFobXzycVrcKQbY+oapXgRAA9fn6tNrtIX5bvaxAcQnF2LfHEM1XdHF +uM1L6pPu/JcCHL9zXpch3MLBLrHwIRV5y9PGsUFWHN6GM8tnUDZ2B+5RBpmPPzd9 +bpl3k6Iz5Q44vcU2hMUOjI/N8kF0NQ2o3R5Yq8PEH/HJyj2bVudM8n+zBkk2Ii4D +r7/aRYcCy/HjCoSaNt/nPgexiJRlDs0GVfVX84EEaQ6UZy3ioIUcJbb3qzJGncV5 +VQCpW17oUgyZbqNjQmd/sAa4+CLjF9PiAeqOnmVp5yYD60OQzeFiXcI5pjEOy08l +MN/4V48NAgMBAAECggEAH8gKXt0V6Rhqe1Tfyy2HMx22mmlFM4tUuYwbu5jv1+gT +396hmwoTDs/NtHG8cqwNPT6dA5BUKu9K651eSTpUYp8qtpCemPoVr+PwK/qZpMVs +qqmI+D4swdklbLBMpAEi5GzE0QwCMCfXKoQQC3JtZ9T3yfKPEBxlf2nmcTHc6xOf +jXoP91LVMQ7Orn6N23a8GJKnoEFGb9ngY9AxEqru7WmfdScj/xJ6ObnhmlHqHaUY +BaVfgMiWpKjmZitpH5n1m+SdwsazGEplsuWfNtKNzMcYjZMguKUO1OMOIZQz2SBp +ULw1gXVehk4hykVf6IZ8h5g3Z9EmVNWq/R0TMiA25QKBgQDUKsVpK3T3NXAVgFCg +o8caodHaQwgqHPeabiuQeB37xOFxziPFUCoAIu1z9IB+6/2iTMM6ueGbmo0y1n3a +9NJew0kLUy+0lRJmgArDZ2DSpzfIPZFVQewYU8GFGJ647Bqmez3Omwp/yki79DjJ +RVd+vH0U4oZzRRTSGC5rUhpmywKBgQDDBAzA2Xy2qxgJof0cwhLMQ9q8x9Zq4XVs +RwSsjjHr5eIjxgaHOd7rpF6no50uiAqEzEIdKh2/P3nc/fCl9tyv0NJ3fThUfmb1 +bODBCH56jEsrBIZFVaVh3Zs2Tj2dRP5cR6WmwTPet4sGMSqZAg2yIEprHB0tAyR8 +AJe8HpzOhwKBgGdCScHdvJd0EpDkWllUXFrB1vh7F0YnwvoOFHXDgBRAxdg1k4M8 +eLSISzjcDo23HUIYSgwS25J3rbDIY4hlDt2//ZTdb6JbyxDH0HU5ow3jBGsYS9tK +sjVEzjKQwO8POgk8geBD5OA8+xk+y0Rp0yODaPz5IqaHQJLf4fephd/xAoGATO7G +ETY7StzISNSMw9GUFN0X5612WwfCiQqjP2eBLiysP6yZWrNry842QS/8jCTC8Yya +8GJzBcWGz7WmP/LZMMrSnKzbkgmjmGJxb/Vn3/SEmt3YEnYtHiSMXKoVCHv1VHY3 +VUeWrN//ilvPEDmNKZ4vfX3DzMQWmoypT19MQPUCgYEAm/7B0ODsShmrwphl/g4c +szD4iuwhPc8KoR3HZn1eYsBTxW2nQtklunek155XioYKYCeKNEx4hreZZESAcTs6 +WZOskIskE/Ta0Kcu5QWxyrIhsBHnNx+R/AGXTK33u1E2LbAcvPuahWIso8eYKPj5 +VqdTHeOjkhC/JwjTCbQI82E= +-----END PRIVATE KEY----- diff --git a/packages/workday/changelog.yml b/packages/workday/changelog.yml new file mode 100644 index 00000000000..64f62bfd0f8 --- /dev/null +++ b/packages/workday/changelog.yml @@ -0,0 +1,6 @@ +# newer versions go on top +- version: '0.1.0' + changes: + - description: Add support for activity data stream. + type: enhancement + link: https://github.com/elastic/integrations/pull/19319 diff --git a/packages/workday/data_stream/activity/_dev/test/pipeline/test-activity.log b/packages/workday/data_stream/activity/_dev/test/pipeline/test-activity.log new file mode 100644 index 00000000000..534577afa94 --- /dev/null +++ b/packages/workday/data_stream/activity/_dev/test/pipeline/test-activity.log @@ -0,0 +1,5 @@ +{"activityAction":"READ","taskId":"e67b812850dc100047be196f396d745f","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36","requestTime":"2026-04-02T12:46:18.012Z","taskDisplayName":"privacy/activityLogging/userActivity (GET) (v1 -  )","systemAccount":"wd-implementer","deviceType":"Desktop","ipAddress":"127.0.0.1","sessionId":"c7c6ff"} +{"activityAction":"READ","systemAccount":"wd-implementer","requestTime":"2026-04-07T08:02:58.655Z","taskDisplayName":"Get OMS Session Data (Web Service)","sessionId":"c91278","target":{"descriptor":"wd-implementer / Workday Implementer","id":"64700e15a04847f6ac13343b007478e3"},"taskId":"dc1bea8c446c11de98360015c5e6daf6","ipAddress":"127.0.0.1","deviceType":"Desktop","userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"} +{"activityAction":"OTHER","systemAccount":"wd-implementer","requestTime":"2026-04-07T10:29:14.163Z","taskDisplayName":"absenceManagement/balances/view (GET) (v1 -  )","sessionId":"2b6938","taskId":"842800d7bb0210006a09e472785f010b","ipAddress":"127.0.0.1","deviceType":"Desktop","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36 Edg/146.0.0.0"} +{"activityAction":"READ","systemAccount":"wd-implementer","requestTime":"2026-04-07T18:34:42.548Z","taskDisplayName":"Submit OAuth 2.0 Consent (Web Service)","sessionId":"a5097e","taskId":"8b086034c8ec49e79b0f13af87e911ea","ipAddress":"127.0.0.1","deviceType":"Desktop","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36"} +{"activityAction":"READ","systemAccount":"wd-implementer","requestTime":"2026-04-07T19:03:29.024Z","taskDisplayName":"Get OMS Session Data (Web Service)","sessionId":"6fe14f","target":{"descriptor":"wd-implementer / Workday Implementer","id":"64700e15a04847f6ac13343b007478e3"},"taskId":"dc1bea8c446c11de98360015c5e6daf6","ipAddress":"127.0.0.1","deviceType":"Desktop","userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36"} diff --git a/packages/workday/data_stream/activity/_dev/test/pipeline/test-activity.log-expected.json b/packages/workday/data_stream/activity/_dev/test/pipeline/test-activity.log-expected.json new file mode 100644 index 00000000000..7a61504246e --- /dev/null +++ b/packages/workday/data_stream/activity/_dev/test/pipeline/test-activity.log-expected.json @@ -0,0 +1,287 @@ +{ + "expected": [ + { + "@timestamp": "2026-04-02T12:46:18.012Z", + "device": { + "type": "desktop" + }, + "ecs": { + "version": "9.3.0" + }, + "event": { + "action": "read", + "category": [ + "iam" + ], + "kind": "event", + "original": "{\"activityAction\":\"READ\",\"taskId\":\"e67b812850dc100047be196f396d745f\",\"userAgent\":\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36\",\"requestTime\":\"2026-04-02T12:46:18.012Z\",\"taskDisplayName\":\"privacy/activityLogging/userActivity (GET) (v1 -  )\",\"systemAccount\":\"wd-implementer\",\"deviceType\":\"Desktop\",\"ipAddress\":\"127.0.0.1\",\"sessionId\":\"c7c6ff\"}", + "type": [ + "info" + ] + }, + "related": { + "ip": [ + "127.0.0.1" + ], + "user": [ + "wd-implementer" + ] + }, + "source": { + "ip": "127.0.0.1" + }, + "user": { + "name": "wd-implementer" + }, + "user_agent": { + "device": { + "name": "Other" + }, + "name": "Chrome", + "original": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36", + "os": { + "full": "Windows 10", + "name": "Windows", + "version": "10" + }, + "version": "146.0.0.0" + }, + "workday": { + "activity": { + "activity_action": "READ", + "session_id": "c7c6ff", + "task_display_name": "privacy/activityLogging/userActivity (GET) (v1 -  )", + "task_id": "e67b812850dc100047be196f396d745f" + } + } + }, + { + "@timestamp": "2026-04-07T08:02:58.655Z", + "device": { + "type": "desktop" + }, + "ecs": { + "version": "9.3.0" + }, + "event": { + "action": "read", + "category": [ + "iam" + ], + "kind": "event", + "original": "{\"activityAction\":\"READ\",\"systemAccount\":\"wd-implementer\",\"requestTime\":\"2026-04-07T08:02:58.655Z\",\"taskDisplayName\":\"Get OMS Session Data (Web Service)\",\"sessionId\":\"c91278\",\"target\":{\"descriptor\":\"wd-implementer / Workday Implementer\",\"id\":\"64700e15a04847f6ac13343b007478e3\"},\"taskId\":\"dc1bea8c446c11de98360015c5e6daf6\",\"ipAddress\":\"127.0.0.1\",\"deviceType\":\"Desktop\",\"userAgent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36\"}", + "type": [ + "info" + ] + }, + "related": { + "ip": [ + "127.0.0.1" + ], + "user": [ + "wd-implementer" + ] + }, + "source": { + "ip": "127.0.0.1" + }, + "user": { + "name": "wd-implementer" + }, + "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/146.0.0.0 Safari/537.36", + "os": { + "full": "Mac OS X 10.15.7", + "name": "Mac OS X", + "version": "10.15.7" + }, + "version": "146.0.0.0" + }, + "workday": { + "activity": { + "activity_action": "READ", + "session_id": "c91278", + "target": { + "descriptor": "wd-implementer / Workday Implementer", + "id": "64700e15a04847f6ac13343b007478e3" + }, + "task_display_name": "Get OMS Session Data (Web Service)", + "task_id": "dc1bea8c446c11de98360015c5e6daf6" + } + } + }, + { + "@timestamp": "2026-04-07T10:29:14.163Z", + "device": { + "type": "desktop" + }, + "ecs": { + "version": "9.3.0" + }, + "event": { + "action": "other", + "category": [ + "iam" + ], + "kind": "event", + "original": "{\"activityAction\":\"OTHER\",\"systemAccount\":\"wd-implementer\",\"requestTime\":\"2026-04-07T10:29:14.163Z\",\"taskDisplayName\":\"absenceManagement/balances/view (GET) (v1 -  )\",\"sessionId\":\"2b6938\",\"taskId\":\"842800d7bb0210006a09e472785f010b\",\"ipAddress\":\"127.0.0.1\",\"deviceType\":\"Desktop\",\"userAgent\":\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36 Edg/146.0.0.0\"}", + "type": [ + "info" + ] + }, + "related": { + "ip": [ + "127.0.0.1" + ], + "user": [ + "wd-implementer" + ] + }, + "source": { + "ip": "127.0.0.1" + }, + "user": { + "name": "wd-implementer" + }, + "user_agent": { + "device": { + "name": "Other" + }, + "name": "Edge", + "original": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36 Edg/146.0.0.0", + "os": { + "full": "Windows 10", + "name": "Windows", + "version": "10" + }, + "version": "146.0.0.0" + }, + "workday": { + "activity": { + "activity_action": "OTHER", + "session_id": "2b6938", + "task_display_name": "absenceManagement/balances/view (GET) (v1 -  )", + "task_id": "842800d7bb0210006a09e472785f010b" + } + } + }, + { + "@timestamp": "2026-04-07T18:34:42.548Z", + "device": { + "type": "desktop" + }, + "ecs": { + "version": "9.3.0" + }, + "event": { + "action": "read", + "category": [ + "iam" + ], + "kind": "event", + "original": "{\"activityAction\":\"READ\",\"systemAccount\":\"wd-implementer\",\"requestTime\":\"2026-04-07T18:34:42.548Z\",\"taskDisplayName\":\"Submit OAuth 2.0 Consent (Web Service)\",\"sessionId\":\"a5097e\",\"taskId\":\"8b086034c8ec49e79b0f13af87e911ea\",\"ipAddress\":\"127.0.0.1\",\"deviceType\":\"Desktop\",\"userAgent\":\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36\"}", + "type": [ + "info" + ] + }, + "related": { + "ip": [ + "127.0.0.1" + ], + "user": [ + "wd-implementer" + ] + }, + "source": { + "ip": "127.0.0.1" + }, + "user": { + "name": "wd-implementer" + }, + "user_agent": { + "device": { + "name": "Other" + }, + "name": "Chrome", + "original": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36", + "os": { + "full": "Windows 10", + "name": "Windows", + "version": "10" + }, + "version": "147.0.0.0" + }, + "workday": { + "activity": { + "activity_action": "READ", + "session_id": "a5097e", + "task_display_name": "Submit OAuth 2.0 Consent (Web Service)", + "task_id": "8b086034c8ec49e79b0f13af87e911ea" + } + } + }, + { + "@timestamp": "2026-04-07T19:03:29.024Z", + "device": { + "type": "desktop" + }, + "ecs": { + "version": "9.3.0" + }, + "event": { + "action": "read", + "category": [ + "iam" + ], + "kind": "event", + "original": "{\"activityAction\":\"READ\",\"systemAccount\":\"wd-implementer\",\"requestTime\":\"2026-04-07T19:03:29.024Z\",\"taskDisplayName\":\"Get OMS Session Data (Web Service)\",\"sessionId\":\"6fe14f\",\"target\":{\"descriptor\":\"wd-implementer / Workday Implementer\",\"id\":\"64700e15a04847f6ac13343b007478e3\"},\"taskId\":\"dc1bea8c446c11de98360015c5e6daf6\",\"ipAddress\":\"127.0.0.1\",\"deviceType\":\"Desktop\",\"userAgent\":\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36\"}", + "type": [ + "info" + ] + }, + "related": { + "ip": [ + "127.0.0.1" + ], + "user": [ + "wd-implementer" + ] + }, + "source": { + "ip": "127.0.0.1" + }, + "user": { + "name": "wd-implementer" + }, + "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/146.0.0.0 Safari/537.36", + "os": { + "full": "Mac OS X 10.15.7", + "name": "Mac OS X", + "version": "10.15.7" + }, + "version": "146.0.0.0" + }, + "workday": { + "activity": { + "activity_action": "READ", + "session_id": "6fe14f", + "target": { + "descriptor": "wd-implementer / Workday Implementer", + "id": "64700e15a04847f6ac13343b007478e3" + }, + "task_display_name": "Get OMS Session Data (Web Service)", + "task_id": "dc1bea8c446c11de98360015c5e6daf6" + } + } + } + ] +} 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 new file mode 100644 index 00000000000..d6481a8aa12 --- /dev/null +++ b/packages/workday/data_stream/activity/_dev/test/system/test-common-config.yml @@ -0,0 +1,36 @@ +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: + - | + -----BEGIN CERTIFICATE----- + MIIDJTCCAg2gAwIBAgIUV+67DSMtT/+uSt4qDbY6IDwlJawwDQYJKoZIhvcNAQEL + BQAwFjEUMBIGA1UEAwwLc3ZjLXdvcmtkYXkwHhcNMjYwNjAxMTMwODIxWhcNMzYw + NTI5MTMwODIxWjAWMRQwEgYDVQQDDAtzdmMtd29ya2RheTCCASIwDQYJKoZIhvcN + AQEBBQADggEPADCCAQoCggEBAKGf75wHU2B9niPdBS+QKuvQwWhtfPJxWtwpBtj6 + hqleBEAD1+fq02u0hflu9rEBxCcXYt8cQzVd0cW4zUvqk+78lwIcv3NelyHcwsEu + sfAhFXnL08axQVYc3oYzy2dQNnYH7lEGmY8/N31umXeTojPlDji9xTaExQ6Mj83y + QXQ1DajdHlirw8Qf8cnKPZtW50zyf7MGSTYiLgOvv9pFhwLL8eMKhJo23+c+B7GI + lGUOzQZV9VfzgQRpDpRnLeKghRwltverMkadxXlVAKlbXuhSDJluo2NCZ3+wBrj4 + IuMX0+IB6o6eZWnnJgPrQ5DN4WJdwjmmMQ7LTyUw3/hXjw0CAwEAAaNrMGkwHQYD + VR0OBBYEFDla3DE7Dm0f35w6PiMqslosh2HNMB8GA1UdIwQYMBaAFDla3DE7Dm0f + 35w6PiMqslosh2HNMA8GA1UdEwEB/wQFMAMBAf8wFgYDVR0RBA8wDYILc3ZjLXdv + cmtkYXkwDQYJKoZIhvcNAQELBQADggEBAGb/wSyfnXpK9z7GqKnJ2JA3RkRdudHT + sy7j0Q0W0Cr6VeVj+paiRwQtMXriNOMzWvJ2cTMRp4l181XMnLvasQTqOASHpM1G + Ra0eEmITzhdJsiyW585fAL+hyvthzo8f4r/9rm3NwDQdFQt9akGw1nnuFzd2+K/b + c0GJiVBgNKp3Q1u7MeEQK/kKjzKP5qsB34aJNxWdzKF7rFaRQPtBcGh15zfxpcOJ + VrEdkgusmHeI8Q4yKPu2Vopaq29dg3iW/FLsXeTAOYeo9KfgSXt3cxMPrrwtJEwG + nWd6q0A8Ec8udGavtotazOi9g+F16fNTaUVk8bXkoTUezwSe/IfGRw4= + -----END CERTIFICATE----- +data_stream: + vars: + preserve_original_event: true + batch_size: 2 +assert: + hit_count: 5 diff --git a/packages/workday/data_stream/activity/agent/stream/cel.yml.hbs b/packages/workday/data_stream/activity/agent/stream/cel.yml.hbs new file mode 100644 index 00000000000..7f4e634ee3b --- /dev/null +++ b/packages/workday/data_stream/activity/agent/stream/cel.yml.hbs @@ -0,0 +1,197 @@ +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: https://{{hostname}}/ccx/api/privacy/v1/{{tenant}} +state: + client_id: {{client_id}} + client_secret: {{client_secret}} + refresh_token: {{refresh_token}} + token_url: https://{{hostname}}/ccx/oauth2/{{tenant}}/token + initial_interval: {{initial_interval}} + batch_size : {{batch_size}} + offset: 0 +redact: + fields: + - client_id + - client_secret + - refresh_token + - cursor.access_token +program: |- + ( + state.?want_more.orValue(false) ? + state + : + state.with( + { + "start_time": state.?cursor.last_timestamp.orValue((now - duration(state.initial_interval)).format(time_layout.RFC3339)), + "end_time": now.format(time_layout.RFC3339), + } + ) + ).as(state, + state.url.trim_right("/").as(base_url, + state.with( + ( + (state.?cursor.access_token.orValue("") == "") ? + post_request( + state.token_url, + "application/x-www-form-urlencoded", + { + "grant_type": ["refresh_token"], + "refresh_token": [state.refresh_token], + "client_id": [state.client_id], + "client_secret": [state.client_secret], + }.format_query() + ).do_request().as(authResp, + (authResp.StatusCode == 200) ? + authResp.Body.decode_json().as(ao, + { + "ok": true, + "access_token": ao.access_token, + } + ) + : + { + "ok": false, + "err_code": string(authResp.StatusCode), + "err_status": authResp.Status, + "err_body": (size(authResp.Body) != 0) ? string(authResp.Body) : authResp.Status, + } + ) + : + { + "ok": true, + "access_token": state.cursor.access_token, + } + ).as(tok, + !tok.ok ? + { + "events": { + "error": { + "code": tok.err_code, + "id": tok.err_status, + "message": "POST " + state.token_url + ": " + tok.err_body, + }, + }, + "want_more": false, + "offset": 0, + } + : + request( + "GET", + base_url + "/activityLogging?" + { + "offset": [string(state.offset)], + "limit": [string(state.batch_size)], + "from": [string(state.start_time)], + "to": [string(state.end_time)], + }.format_query() + ).with( + { + "Header": { + "Authorization": ["Bearer " + tok.access_token], + "Accept": ["application/json"], + }, + } + ).do_request().as(resp, + (resp.StatusCode == 200) ? + resp.Body.decode_json().as(body, + (int(state.offset) + body.data.size()).as(new_offset, + ( + body.data.size() > 0 && has(body.total) && new_offset < int(body.total) + ).as(has_more, + { + "events": body.data.map(e, {"message": e.encode_json()}), + "batch_size": state.batch_size, + "offset": has_more ? new_offset : 0, + "want_more": has_more, + "cursor": { + "access_token": tok.access_token, + ?"max_ingested_time": has_more ? + ( + has(state.?cursor.max_ingested_time) ? + optional.of(max(state.cursor.max_ingested_time, body.data.map(e, e.requestTime).max())) + : + optional.of(body.data.map(e, e.requestTime).max()) + ) + : + optional.none(), + ?"last_timestamp": !has_more ? + ( + (body.data.size() > 0) ? + ( + has(state.?cursor.max_ingested_time) ? + optional.of(max(state.cursor.max_ingested_time, body.data.map(e, e.requestTime).max())) + : + optional.of(body.data.map(e, e.requestTime).max()) + ) + : has(state.?cursor.max_ingested_time) ? + optional.of(state.cursor.max_ingested_time) + : + state.?cursor.last_timestamp + ) + : + state.?cursor.last_timestamp, + }, + } + ) + ) + ) + : (resp.StatusCode == 401) ? + { + "events": { + "error": { + "code": string(resp.StatusCode), + "id": resp.Status, + "message": "GET " + base_url + "/activityLogging: token expired, retrying", + }, + }, + "want_more": true, + "offset": state.offset, + } + : + { + "events": { + "error": { + "code": string(resp.StatusCode), + "id": resp.Status, + "message": "GET " + base_url + "/activityLogging: " + ( + (size(resp.Body) != 0) ? + string(resp.Body) + : + resp.Status + " (" + string(resp.StatusCode) + ")" + ), + }, + }, + "want_more": false, + "offset": 0, + } + ) + ) + ) + ) + ) + +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/activity/elasticsearch/ingest_pipeline/default.yml b/packages/workday/data_stream/activity/elasticsearch/ingest_pipeline/default.yml new file mode 100644 index 00000000000..ebff3150fa0 --- /dev/null +++ b/packages/workday/data_stream/activity/elasticsearch/ingest_pipeline/default.yml @@ -0,0 +1,315 @@ +--- +description: Pipeline for processing activity logs. +processors: + - set: + field: ecs.version + tag: set_ecs_version + value: 9.3.0 + - remove: + field: + - cloud.account.id + - cloud.availability_zone + - cloud.image.id + - cloud.instance.id + - cloud.instance.name + - cloud.machine.type + - cloud.provider + - cloud.region + - cloud.service.name + - host + tag: remove_agentless_fields + ignore_missing: true + if: ctx.input?.type == 'cel' + - 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: json + - fingerprint: + fields: + - json.requestTime + - json.sessionId + - json.taskId + tag: fingerprint_activity + target_field: _id + ignore_missing: true + - set: + field: event.kind + tag: set_event_kind + value: event + - append: + field: event.type + tag: append_info_into_event_type + value: info + - append: + field: event.category + tag: append_iam_into_event_category + value: iam + - rename: + field: json.activityAction + tag: rename_activityAction + target_field: workday.activity.activity_action + ignore_missing: true + - set: + field: event.action + tag: set_event_action_from_activity_activity_action + copy_from: workday.activity.activity_action + ignore_empty_value: true + - lowercase: + field: event.action + tag: lowercase_event_action + ignore_missing: true + - split: + field: event.action + tag: split_event_action + separator: \s+ + ignore_missing: true + if: ctx.event?.action != '' + 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}}}' + - join: + field: event.action + tag: join_event_action + separator: '-' + if: ctx.event?.action != '' + 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}}}' + - rename: + field: json.deviceType + tag: rename_deviceType + target_field: workday.activity.device_type + ignore_missing: true + - set: + field: device.type + tag: set_device_type_from_activity_device_type + copy_from: workday.activity.device_type + ignore_empty_value: true + - lowercase: + field: device.type + tag: lowercase_device_type + ignore_missing: true + - convert: + field: json.ipAddress + tag: convert_ipAddress_to_ip + target_field: workday.activity.ip_address + type: ip + ignore_missing: true + if: ctx.json?.ipAddress != '' + 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: source.ip + tag: set_source_ip_from_activity_ip_address + copy_from: workday.activity.ip_address + ignore_empty_value: true + - geoip: + field: source.ip + tag: geoip_source_ip_to_source_geo + target_field: source.geo + ignore_missing: true + - geoip: + database_file: GeoLite2-ASN.mmdb + tag: geoip_source_ip_to_source_as + field: source.ip + 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 + - append: + field: related.ip + tag: append_activity_ip_address_into_related_ip + value: '{{{workday.activity.ip_address}}}' + allow_duplicates: false + if: ctx.workday?.activity?.ip_address != null + - date: + field: json.requestTime + tag: date_requestTime + target_field: workday.activity.request_time + formats: + - ISO8601 + if: ctx.json?.requestTime != null && ctx.json.requestTime != '' + 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_activity_request_time + copy_from: workday.activity.request_time + ignore_empty_value: true + - rename: + field: json.sessionId + tag: rename_sessionId + target_field: workday.activity.session_id + ignore_missing: true + - rename: + field: json.systemAccount + tag: rename_systemAccount + target_field: workday.activity.system_account + ignore_missing: true + - set: + field: user.name + tag: set_user_name_from_activity_system_account + copy_from: workday.activity.system_account + ignore_empty_value: true + - append: + field: related.user + tag: append_activity_system_account_into_related_user + value: '{{{workday.activity.system_account}}}' + allow_duplicates: false + if: ctx.workday?.activity?.system_account != null + - rename: + field: json.target.descriptor + tag: rename_target_descriptor + target_field: workday.activity.target.descriptor + ignore_missing: true + - rename: + field: json.target.href + tag: rename_target_href + target_field: workday.activity.target.href + ignore_missing: true + - rename: + field: json.target.id + tag: rename_target_id + target_field: workday.activity.target.id + ignore_missing: true + - rename: + field: json.taskDisplayName + tag: rename_taskDisplayName + target_field: workday.activity.task_display_name + ignore_missing: true + - rename: + field: json.taskId + tag: rename_taskId + target_field: workday.activity.task_id + ignore_missing: true + - convert: + field: json.userActivityEntryCount + tag: convert_userActivityEntryCount_to_long + target_field: workday.activity.user_activity_entry_count + type: long + ignore_missing: true + 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}}}' + - rename: + field: json.userAgent + tag: rename_userAgent + target_field: workday.activity.user_agent + ignore_missing: true + - set: + field: user_agent.original + tag: set_user_agent_original_from_activity_user_agent + copy_from: workday.activity.user_agent + ignore_empty_value: true + - user_agent: + field: user_agent.original + tag: user_agent_original + if: ctx.user_agent?.original != '' + ignore_missing: true + 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}}}' + - remove: + field: + - workday.activity.ip_address + - workday.activity.request_time + - workday.activity.user_agent + - workday.activity.device_type + - workday.activity.system_account + tag: remove_activity_fields_mapped_with_ecs + ignore_missing: true + - remove: + field: + - json + tag: remove_json + 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/activity/fields/base-fields.yml b/packages/workday/data_stream/activity/fields/base-fields.yml new file mode 100644 index 00000000000..9d5eb50b33d --- /dev/null +++ b/packages/workday/data_stream/activity/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.activity +- name: event.module + type: constant_keyword + external: ecs + value: workday +- name: '@timestamp' + external: ecs diff --git a/packages/workday/data_stream/activity/fields/beats.yml b/packages/workday/data_stream/activity/fields/beats.yml new file mode 100644 index 00000000000..3c48f1f224f --- /dev/null +++ b/packages/workday/data_stream/activity/fields/beats.yml @@ -0,0 +1,3 @@ +- name: input.type + type: keyword + description: Type of Filebeat input. diff --git a/packages/workday/data_stream/activity/fields/ecs.yml b/packages/workday/data_stream/activity/fields/ecs.yml new file mode 100644 index 00000000000..8ef9acda203 --- /dev/null +++ b/packages/workday/data_stream/activity/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/activity/fields/fields.yml b/packages/workday/data_stream/activity/fields/fields.yml new file mode 100644 index 00000000000..a25c36dd231 --- /dev/null +++ b/packages/workday/data_stream/activity/fields/fields.yml @@ -0,0 +1,33 @@ +- name: workday + type: group + fields: + - name: activity + type: group + fields: + - name: activity_action + type: keyword + description: The type of action that was executed. + - name: session_id + type: keyword + description: The system ID for tracking signons from the user signon used to make the request. + - name: target + type: group + fields: + - name: descriptor + type: keyword + description: The display name of the instance. + - name: href + type: keyword + description: A link to the instance. + - name: id + type: keyword + description: Workday Id or Reference Id of the instance. + - name: task_display_name + type: keyword + description: The action executed in the transaction. + - name: task_id + type: keyword + description: The Workday ID of the task executed in the transaction. + - name: user_activity_entry_count + type: long + description: Returns the User Activity Count for the inputted filter parameters. diff --git a/packages/workday/data_stream/activity/manifest.yml b/packages/workday/data_stream/activity/manifest.yml new file mode 100644 index 00000000000..5ee7d2ba5ea --- /dev/null +++ b/packages/workday/data_stream/activity/manifest.yml @@ -0,0 +1,76 @@ +title: Activity +type: logs +streams: + - input: cel + title: Activity logs + description: Collect Activity logs from Workday. + template_path: cel.yml.hbs + vars: + - name: initial_interval + type: text + title: Initial Interval + description: How far back to pull the Activity logs from Workday API. Supported units for this parameter are h/m/s. + default: 24h + multi: false + required: true + show_user: true + - name: interval + type: text + title: Interval + description: Duration between requests to the Workday API. Supported units for this parameter are h/m/s. + default: 5m + multi: false + required: true + show_user: true + - name: batch_size + type: integer + title: Batch Size + description: Batch size for the response of the Workday API. The batch size can range from a minimum of 1 to a maximum of 1000. + default: 1000 + 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: 30s + - 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-activity + - 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/data_stream/activity/sample_event.json b/packages/workday/data_stream/activity/sample_event.json new file mode 100644 index 00000000000..93385c0a417 --- /dev/null +++ b/packages/workday/data_stream/activity/sample_event.json @@ -0,0 +1,83 @@ +{ + "@timestamp": "2026-04-02T12:46:18.012Z", + "agent": { + "ephemeral_id": "56b15ab2-aac3-4167-a87e-300667f9c510", + "id": "49c06832-6dd8-4eea-8c9d-702a4bcee941", + "name": "elastic-agent-15161", + "type": "filebeat", + "version": "8.18.0" + }, + "data_stream": { + "dataset": "workday.activity", + "namespace": "58781", + "type": "logs" + }, + "device": { + "type": "desktop" + }, + "ecs": { + "version": "9.3.0" + }, + "elastic_agent": { + "id": "49c06832-6dd8-4eea-8c9d-702a4bcee941", + "snapshot": false, + "version": "8.18.0" + }, + "event": { + "action": "read", + "agent_id_status": "verified", + "category": [ + "iam" + ], + "dataset": "workday.activity", + "ingested": "2026-06-05T11:40:39Z", + "kind": "event", + "original": "{\"activityAction\":\"READ\",\"deviceType\":\"Desktop\",\"ipAddress\":\"127.0.0.1\",\"requestTime\":\"2026-04-02T12:46:18.012Z\",\"sessionId\":\"c7c6ff\",\"systemAccount\":\"wd-implementer\",\"taskDisplayName\":\"privacy/activityLogging/userActivity (GET) (v1 - )\",\"taskId\":\"e67b812850dc100047be196f396d745f\",\"userAgent\":\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36\"}", + "type": [ + "info" + ] + }, + "input": { + "type": "cel" + }, + "related": { + "ip": [ + "127.0.0.1" + ], + "user": [ + "wd-implementer" + ] + }, + "source": { + "ip": "127.0.0.1" + }, + "tags": [ + "preserve_original_event", + "forwarded", + "workday-activity" + ], + "user": { + "name": "wd-implementer" + }, + "user_agent": { + "device": { + "name": "Other" + }, + "name": "Chrome", + "original": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36", + "os": { + "full": "Windows 10", + "name": "Windows", + "version": "10" + }, + "version": "146.0.0.0" + }, + "workday": { + "activity": { + "activity_action": "READ", + "session_id": "c7c6ff", + "task_display_name": "privacy/activityLogging/userActivity (GET) (v1 - )", + "task_id": "e67b812850dc100047be196f396d745f" + } + } +} diff --git a/packages/workday/docs/README.md b/packages/workday/docs/README.md new file mode 100644 index 00000000000..b9ee8dd956a --- /dev/null +++ b/packages/workday/docs/README.md @@ -0,0 +1,265 @@ +# Workday + +## Overview + +[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. + +### Compatibility + +The Workday integration is compatible with API version **v1**. + +### How it works + +This integration periodically queries the Workday API to retrieve logs. + +## What data does this integration collect? + +This integration collects log messages of the following type: + +- `Activity`: Collects [Activity Logs](https://community.workday.com/sites/default/files/file-hosting/restapi/#privacy/v1/get-/activityLogging) logs via Workday API (endpoint: `/activityLogging`). + +### 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. + +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 + +##### Enable User Activity Logging + +1. Sign in to your Workday tenant as a Security Administrator. +2. In the Workday search bar, search for and open the Edit Tenant Setup - System task. +3. In the Security section, select the Enable User Activity Logging checkbox. +4. Click OK to save the changes. + +**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) + +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. 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 + +1. In the Workday search bar, search for Register API Client for Integrations. +2. Enter a Client Name (for example, SIEM_OAuth_Client). +3. Select the Non-Expiring Refresh Tokens option. +4. Add the scope: System (or the scope required for User Activity Logging API). +5. Click OK. +6. Copy and save the following details in a secure location: + - Client ID: The API client identifier. + - Client Secret: The API client secret. +7. Search for Manage Refresh Tokens for Integrations. +8. Select the ISU account (ISU_SIEM_Export). +9. Generate a new refresh token for the API client. +10. Copy and save the Refresh Token. + +#### Determine tenant URL + +The API endpoint is based on your Workday tenant. The format is: + +Component | Value + +Token endpoint | https://HOST/ccx/oauth2/TENANT/token + +Activity Logging API | https://HOST/ccx/api/privacy/v1/TENANT/activityLogging + +**Note:** Replace HOST with your Workday hostname and TENANT with your tenant name. + +**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). + +## How do I deploy this integration? + +This integration supports both Elastic Agentless-based and Agent-based installations. + +### Agentless-based installation + +Agentless integrations allow you to collect data without having to manage Elastic Agent in your cloud. They make manual agent deployment unnecessary, so you can focus on your data instead of the agent that collects it. For more information, refer to [Agentless integrations](https://www.elastic.co/guide/en/serverless/current/security-agentless-integrations.html) and the [Agentless integrations FAQ](https://www.elastic.co/guide/en/serverless/current/agentless-integration-troubleshooting.html). + +Agentless deployments are only supported in Elastic Serverless and Elastic Cloud environments. This functionality is in beta and is subject to change. Beta features are not subject to the support SLA of official GA features. + +### Agent-based installation + +Elastic Agent must be installed. For more details, check the Elastic Agent [installation instructions](docs-content://reference/fleet/install-elastic-agents.md). You can install only one Elastic Agent per host. + +### Configure the integration + +1. In the top search bar in Kibana, search for **Integrations**. +2. In the search bar, type **Workday**. +3. Select the **Workday** integration from the search results. +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: + + - Configure **Hostname**. + - Configure **Tenant**. + - Configure **Client ID**. + - Configure **Client Secret**. + - Configure **Refresh Token**. + - Adjust the integration configuration parameters if required, including the **Interval**, **Initial Interval**, **Preserve original event** etc. to enable data collection. + +6. Select **Save and continue** to save the integration. + +### Validation + +#### Dashboard populated + +1. In the top search bar in Kibana, search for **Dashboards**. +2. In the search bar, type **Workday**. +3. Select a dashboard for the dataset you are collecting, and verify the dashboard information is populated. + +## Troubleshooting + +For help with Elastic ingest tools, check [Common problems](https://www.elastic.co/docs/troubleshoot/ingest/fleet/common-problems). + +## Performance and scaling + +For more information on architectures that can be used for scaling this integration, check the [Ingest Architectures](https://www.elastic.co/docs/manage-data/ingest/ingest-reference-architectures) documentation. + +## Reference + +### ECS field reference + +#### Activity + +**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.activity.activity_action | The type of action that was executed. | keyword | +| workday.activity.session_id | The system ID for tracking signons from the user signon used to make the request. | keyword | +| workday.activity.target.descriptor | The display name of the instance. | keyword | +| workday.activity.target.href | A link to the instance. | keyword | +| workday.activity.target.id | Workday Id or Reference Id of the instance. | keyword | +| workday.activity.task_display_name | The action executed in the transaction. | keyword | +| workday.activity.task_id | The Workday ID of the task executed in the transaction. | keyword | +| workday.activity.user_activity_entry_count | Returns the User Activity Count for the inputted filter parameters. | long | + + +### Example event + +#### Activity + +An example event for `activity` looks as following: + +```json +{ + "@timestamp": "2026-04-02T12:46:18.012Z", + "agent": { + "ephemeral_id": "56b15ab2-aac3-4167-a87e-300667f9c510", + "id": "49c06832-6dd8-4eea-8c9d-702a4bcee941", + "name": "elastic-agent-15161", + "type": "filebeat", + "version": "8.18.0" + }, + "data_stream": { + "dataset": "workday.activity", + "namespace": "58781", + "type": "logs" + }, + "device": { + "type": "desktop" + }, + "ecs": { + "version": "9.3.0" + }, + "elastic_agent": { + "id": "49c06832-6dd8-4eea-8c9d-702a4bcee941", + "snapshot": false, + "version": "8.18.0" + }, + "event": { + "action": "read", + "agent_id_status": "verified", + "category": [ + "iam" + ], + "dataset": "workday.activity", + "ingested": "2026-06-05T11:40:39Z", + "kind": "event", + "original": "{\"activityAction\":\"READ\",\"deviceType\":\"Desktop\",\"ipAddress\":\"127.0.0.1\",\"requestTime\":\"2026-04-02T12:46:18.012Z\",\"sessionId\":\"c7c6ff\",\"systemAccount\":\"wd-implementer\",\"taskDisplayName\":\"privacy/activityLogging/userActivity (GET) (v1 - )\",\"taskId\":\"e67b812850dc100047be196f396d745f\",\"userAgent\":\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36\"}", + "type": [ + "info" + ] + }, + "input": { + "type": "cel" + }, + "related": { + "ip": [ + "127.0.0.1" + ], + "user": [ + "wd-implementer" + ] + }, + "source": { + "ip": "127.0.0.1" + }, + "tags": [ + "preserve_original_event", + "forwarded", + "workday-activity" + ], + "user": { + "name": "wd-implementer" + }, + "user_agent": { + "device": { + "name": "Other" + }, + "name": "Chrome", + "original": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36", + "os": { + "full": "Windows 10", + "name": "Windows", + "version": "10" + }, + "version": "146.0.0.0" + }, + "workday": { + "activity": { + "activity_action": "READ", + "session_id": "c7c6ff", + "task_display_name": "privacy/activityLogging/userActivity (GET) (v1 - )", + "task_id": "e67b812850dc100047be196f396d745f" + } + } +} +``` + +### Inputs used + +These input is 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: + +**Activity**: [Workday Activity API documentation](https://community.workday.com/sites/default/files/file-hosting/restapi/#privacy/v1/get-/activityLogging). diff --git a/packages/workday/img/workday-activity-dashboard.png b/packages/workday/img/workday-activity-dashboard.png new file mode 100644 index 00000000000..b39c97b324b Binary files /dev/null and b/packages/workday/img/workday-activity-dashboard.png differ diff --git a/packages/workday/img/workday-logo.svg b/packages/workday/img/workday-logo.svg new file mode 100644 index 00000000000..b5e12d4aec1 --- /dev/null +++ b/packages/workday/img/workday-logo.svg @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/packages/workday/kibana/dashboard/workday-972e856e-47c4-4c27-966e-b9dfcd380d72.json b/packages/workday/kibana/dashboard/workday-972e856e-47c4-4c27-966e-b9dfcd380d72.json new file mode 100644 index 00000000000..30b6407df4d --- /dev/null +++ b/packages/workday/kibana/dashboard/workday-972e856e-47c4-4c27-966e-b9dfcd380d72.json @@ -0,0 +1,1517 @@ +{ + "attributes": { + "controlGroupInput": { + "chainingSystem": "HIERARCHICAL", + "controlStyle": "oneLine", + "ignoreParentSettingsJSON": { + "ignoreFilters": false, + "ignoreQuery": false, + "ignoreTimerange": false, + "ignoreValidations": false + }, + "panelsJSON": { + "87cad3b1-43f0-441b-a3ba-8d266336557a": { + "explicitInput": { + "dataViewId": "logs-*", + "exclude": null, + "existsSelected": null, + "fieldName": "event.action", + "hideActionBar": null, + "hideExclude": null, + "hideExists": null, + "hideSort": null, + "placeholder": null, + "runPastTimeout": null, + "searchTechnique": "prefix", + "selectedOptions": [], + "singleSelect": null, + "sort": { + "by": "_count", + "direction": "desc" + }, + "title": "Action" + }, + "grow": true, + "order": 0, + "type": "optionsListControl", + "width": "medium" + }, + "d352c978-a644-4ace-914f-b928f5c0add2": { + "explicitInput": { + "dataViewId": "logs-*", + "exclude": null, + "existsSelected": null, + "fieldName": "workday.activity.task_display_name", + "hideActionBar": null, + "hideExclude": null, + "hideExists": null, + "hideSort": null, + "placeholder": null, + "runPastTimeout": null, + "searchTechnique": "prefix", + "selectedOptions": [], + "singleSelect": null, + "sort": { + "by": "_count", + "direction": "desc" + }, + "title": "Task" + }, + "grow": true, + "order": 2, + "type": "optionsListControl", + "width": "medium" + }, + "f0d05b20-49d6-492c-9bb8-456920a302ca": { + "explicitInput": { + "dataViewId": "logs-*", + "exclude": null, + "existsSelected": null, + "fieldName": "device.type", + "hideActionBar": null, + "hideExclude": null, + "hideExists": null, + "hideSort": null, + "placeholder": null, + "runPastTimeout": null, + "searchTechnique": "prefix", + "selectedOptions": [], + "singleSelect": null, + "sort": { + "by": "_count", + "direction": "desc" + }, + "title": "Device Type" + }, + "grow": true, + "order": 1, + "type": "optionsListControl", + "width": "medium" + } + }, + "showApplySelections": false + }, + "description": "", + "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.activity" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.activity" + } + } + } + ], + "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-b8dea39e-0b66-4ad0-a7aa-54685762be20", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "594c9e9f-63f0-4016-a6b0-c6121c89cc7a", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "b8dea39e-0b66-4ad0-a7aa-54685762be20": { + "columnOrder": [ + "f0c74495-58f5-437d-b088-040bec5ca2dc", + "bc5eeda1-6c51-49f3-a11a-b35a63f07570" + ], + "columns": { + "bc5eeda1-6c51-49f3-a11a-b35a63f07570": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Count", + "operationType": "count", + "params": { + "emptyAsNull": false, + "format": { + "id": "number", + "params": { + "decimals": 0 + } + } + }, + "scale": "ratio", + "sourceField": "___records___" + }, + "f0c74495-58f5-437d-b088-040bec5ca2dc": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Action", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "bc5eeda1-6c51-49f3-a11a-b35a63f07570", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 5 + }, + "scale": "ordinal", + "sourceField": "event.action" + } + }, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "data_stream.dataset", + "index": "594c9e9f-63f0-4016-a6b0-c6121c89cc7a", + "key": "data_stream.dataset", + "negate": false, + "params": { + "query": "workday.activity" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.activity" + } + } + } + ], + "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": "b8dea39e-0b66-4ad0-a7aa-54685762be20", + "layerType": "data", + "legendDisplay": "show", + "metrics": [ + "bc5eeda1-6c51-49f3-a11a-b35a63f07570" + ], + "nestedLegend": false, + "numberDisplay": "percent", + "primaryGroups": [ + "f0c74495-58f5-437d-b088-040bec5ca2dc" + ], + "truncateLegend": false + } + ], + "shape": "pie" + } + }, + "title": "", + "type": "lens", + "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.activity" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.activity" + } + } + } + ], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 15, + "i": "3f9b13fc-ef22-4523-8b76-2f6a6dbbd5a4", + "w": 24, + "x": 24, + "y": 18 + }, + "panelIndex": "3f9b13fc-ef22-4523-8b76-2f6a6dbbd5a4", + "title": "Activity by Action", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "logs-*", + "name": "indexpattern-datasource-layer-b8dea39e-0b66-4ad0-a7aa-54685762be20", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "241ba901-4a5b-45a3-a505-fd54a5f62031", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "b8dea39e-0b66-4ad0-a7aa-54685762be20": { + "columnOrder": [ + "f0c74495-58f5-437d-b088-040bec5ca2dc", + "bc5eeda1-6c51-49f3-a11a-b35a63f07570" + ], + "columns": { + "bc5eeda1-6c51-49f3-a11a-b35a63f07570": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Count", + "operationType": "count", + "params": { + "emptyAsNull": false, + "format": { + "id": "number", + "params": { + "decimals": 0 + } + } + }, + "scale": "ratio", + "sourceField": "___records___" + }, + "f0c74495-58f5-437d-b088-040bec5ca2dc": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Device Type", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "bc5eeda1-6c51-49f3-a11a-b35a63f07570", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "secondaryFields": [], + "size": 5 + }, + "scale": "ordinal", + "sourceField": "device.type" + } + }, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "data_stream.dataset", + "index": "241ba901-4a5b-45a3-a505-fd54a5f62031", + "key": "data_stream.dataset", + "negate": false, + "params": { + "query": "workday.activity" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.activity" + } + } + } + ], + "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": "b8dea39e-0b66-4ad0-a7aa-54685762be20", + "layerType": "data", + "legendDisplay": "show", + "metrics": [ + "bc5eeda1-6c51-49f3-a11a-b35a63f07570" + ], + "nestedLegend": false, + "numberDisplay": "percent", + "primaryGroups": [ + "f0c74495-58f5-437d-b088-040bec5ca2dc" + ], + "truncateLegend": false + } + ], + "shape": "pie" + } + }, + "title": "", + "type": "lens", + "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.activity" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.activity" + } + } + } + ], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 15, + "i": "04bd84b5-05c0-42e1-af53-3a915d944478", + "w": 24, + "x": 0, + "y": 18 + }, + "panelIndex": "04bd84b5-05c0-42e1-af53-3a915d944478", + "title": "Activity by Device Type", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "logs-*", + "name": "indexpattern-datasource-layer-c97022de-40c0-42cd-8f3e-e78632555e93", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "a0d4d60a-fc9e-41a4-89cb-7c8740b26ad5", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "c97022de-40c0-42cd-8f3e-e78632555e93": { + "columnOrder": [ + "86928a3d-13f0-43f8-883b-440e62debcf2", + "11ae25c3-d3fd-4df0-8da9-35256a66146d" + ], + "columns": { + "11ae25c3-d3fd-4df0-8da9-35256a66146d": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Count", + "operationType": "count", + "params": { + "emptyAsNull": false, + "format": { + "id": "number", + "params": { + "decimals": 0 + } + } + }, + "scale": "ratio", + "sourceField": "___records___" + }, + "86928a3d-13f0-43f8-883b-440e62debcf2": { + "customLabel": true, + "dataType": "ip", + "isBucketed": true, + "label": "Source IP", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "11ae25c3-d3fd-4df0-8da9-35256a66146d", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 10 + }, + "scale": "ordinal", + "sourceField": "source.ip" + } + }, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "data_stream.dataset", + "index": "a0d4d60a-fc9e-41a4-89cb-7c8740b26ad5", + "key": "data_stream.dataset", + "negate": false, + "params": { + "query": "workday.activity" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.activity" + } + } + } + ], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "columns": [ + { + "columnId": "86928a3d-13f0-43f8-883b-440e62debcf2" + }, + { + "columnId": "11ae25c3-d3fd-4df0-8da9-35256a66146d" + } + ], + "layerId": "c97022de-40c0-42cd-8f3e-e78632555e93", + "layerType": "data" + } + }, + "title": "", + "type": "lens", + "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.activity" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.activity" + } + } + } + ], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 15, + "i": "6b4baa90-3304-4072-a453-bf89456257ff", + "w": 24, + "x": 24, + "y": 33 + }, + "panelIndex": "6b4baa90-3304-4072-a453-bf89456257ff", + "title": "Top Source IP", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "logs-*", + "name": "indexpattern-datasource-layer-c97022de-40c0-42cd-8f3e-e78632555e93", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "f460aaaf-0800-45bf-b9d7-9c7ef809e5bb", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "c97022de-40c0-42cd-8f3e-e78632555e93": { + "columnOrder": [ + "86928a3d-13f0-43f8-883b-440e62debcf2", + "11ae25c3-d3fd-4df0-8da9-35256a66146d" + ], + "columns": { + "11ae25c3-d3fd-4df0-8da9-35256a66146d": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Count", + "operationType": "count", + "params": { + "emptyAsNull": false, + "format": { + "id": "number", + "params": { + "decimals": 0 + } + } + }, + "scale": "ratio", + "sourceField": "___records___" + }, + "86928a3d-13f0-43f8-883b-440e62debcf2": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "User Agent", + "operationType": "terms", + "params": { + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "11ae25c3-d3fd-4df0-8da9-35256a66146d", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "secondaryFields": [], + "size": 10 + }, + "scale": "ordinal", + "sourceField": "user_agent.original" + } + }, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "data_stream.dataset", + "index": "f460aaaf-0800-45bf-b9d7-9c7ef809e5bb", + "key": "data_stream.dataset", + "negate": false, + "params": { + "query": "workday.activity" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.activity" + } + } + } + ], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "columns": [ + { + "columnId": "86928a3d-13f0-43f8-883b-440e62debcf2" + }, + { + "columnId": "11ae25c3-d3fd-4df0-8da9-35256a66146d" + } + ], + "layerId": "c97022de-40c0-42cd-8f3e-e78632555e93", + "layerType": "data" + } + }, + "title": "", + "type": "lens", + "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.activity" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.activity" + } + } + } + ], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 15, + "i": "5fdf6541-036a-4775-a483-655f8f49039e", + "w": 24, + "x": 0, + "y": 33 + }, + "panelIndex": "5fdf6541-036a-4775-a483-655f8f49039e", + "title": "Top User Agents", + "type": "lens" + }, + { + "embeddableConfig": { + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "savedVis": { + "data": { + "aggs": [], + "searchSource": { + "filter": [], + "query": { + "language": "kuery", + "query": "" + } + } + }, + "description": "", + "id": "", + "params": { + "fontSize": 12, + "markdown": "**Workday**\n\n**Overview**\n\nThis dashboard provides a concise overview of Workday Activity Logs, highlighting key trends and user interactions. It includes activity over time, along with breakdowns by action and device type to understand usage patterns.\n\nThe dashboard also displays top source IPs, user agents, and most executed tasks, helping identify common behaviors and potential anomalies. An essential details section allows quick access to detailed activity records for further analysis.\n\n[**Integrations Page**](/app/integrations/detail/workday/overview)", + "openLinksInNewTab": false + }, + "title": "", + "type": "markdown", + "uiState": {} + } + }, + "gridData": { + "h": 18, + "i": "5baf84a9-ba0d-4047-b405-45cf97856d53", + "w": 13, + "x": 0, + "y": 0 + }, + "panelIndex": "5baf84a9-ba0d-4047-b405-45cf97856d53", + "type": "visualization" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "logs-*", + "name": "indexpattern-datasource-layer-de5fbb0f-d57a-4fbb-8bfd-e1631521ded8", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "82ba8dc8-a207-4a85-a523-60014911e219", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "de5fbb0f-d57a-4fbb-8bfd-e1631521ded8": { + "columnOrder": [ + "4cf9667e-b08b-43b1-b40b-7adaa7b92892", + "8c9ebb9f-9695-46e9-9f56-ee823e34a429" + ], + "columns": { + "4cf9667e-b08b-43b1-b40b-7adaa7b92892": { + "dataType": "date", + "isBucketed": true, + "label": "@timestamp", + "operationType": "date_histogram", + "params": { + "dropPartials": false, + "includeEmptyRows": true, + "interval": "auto" + }, + "scale": "interval", + "sourceField": "@timestamp" + }, + "8c9ebb9f-9695-46e9-9f56-ee823e34a429": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Activity", + "operationType": "count", + "params": { + "emptyAsNull": false, + "format": { + "id": "number", + "params": { + "decimals": 0 + } + } + }, + "scale": "ratio", + "sourceField": "___records___" + } + }, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "data_stream.dataset", + "index": "82ba8dc8-a207-4a85-a523-60014911e219", + "key": "data_stream.dataset", + "negate": false, + "params": { + "query": "workday.activity" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.activity" + } + } + } + ], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "fittingFunction": "Linear", + "gridlinesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "labelsOrientation": { + "x": 0, + "yLeft": 0, + "yRight": 0 + }, + "layers": [ + { + "accessors": [ + "8c9ebb9f-9695-46e9-9f56-ee823e34a429" + ], + "colorMapping": { + "assignments": [], + "colorMode": { + "type": "categorical" + }, + "paletteId": "eui_amsterdam_color_blind", + "specialAssignments": [ + { + "color": { + "type": "loop" + }, + "rule": { + "type": "other" + }, + "touched": false + } + ] + }, + "layerId": "de5fbb0f-d57a-4fbb-8bfd-e1631521ded8", + "layerType": "data", + "position": "top", + "seriesType": "line", + "showGridlines": false, + "xAccessor": "4cf9667e-b08b-43b1-b40b-7adaa7b92892" + } + ], + "legend": { + "isVisible": true, + "position": "right" + }, + "preferredSeriesType": "line", + "tickLabelsVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "valueLabels": "hide" + } + }, + "title": "", + "type": "lens", + "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.activity" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.activity" + } + } + } + ], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 18, + "i": "4d46c40f-2ae6-4dcb-b44f-528ebb32e964", + "w": 35, + "x": 13, + "y": 0 + }, + "panelIndex": "4d46c40f-2ae6-4dcb-b44f-528ebb32e964", + "title": "Activity Over Time", + "type": "lens" + }, + { + "embeddableConfig": { + "attributes": { + "references": [ + { + "id": "logs-*", + "name": "indexpattern-datasource-layer-fa079e28-a6a1-4905-8a54-8ea96d366522", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "1c7fed27-4972-44aa-99d6-50acd50ebf77", + "type": "index-pattern" + } + ], + "state": { + "adHocDataViews": {}, + "datasourceStates": { + "formBased": { + "layers": { + "fa079e28-a6a1-4905-8a54-8ea96d366522": { + "columnOrder": [ + "bbc5e3b5-bd2e-429a-99d7-4b6c298f347e", + "36af1c7c-1c80-429f-8d91-23f30dd15de2" + ], + "columns": { + "36af1c7c-1c80-429f-8d91-23f30dd15de2": { + "customLabel": true, + "dataType": "number", + "isBucketed": false, + "label": "Count", + "operationType": "count", + "params": { + "emptyAsNull": false, + "format": { + "id": "number", + "params": { + "decimals": 0 + } + } + }, + "scale": "ratio", + "sourceField": "___records___" + }, + "bbc5e3b5-bd2e-429a-99d7-4b6c298f347e": { + "customLabel": true, + "dataType": "string", + "isBucketed": true, + "label": "Task", + "operationType": "terms", + "params": { + "accuracyMode": true, + "exclude": [], + "excludeIsRegex": false, + "include": [], + "includeIsRegex": false, + "missingBucket": false, + "orderBy": { + "columnId": "36af1c7c-1c80-429f-8d91-23f30dd15de2", + "type": "column" + }, + "orderDirection": "desc", + "otherBucket": true, + "parentFormat": { + "id": "terms" + }, + "size": 10 + }, + "scale": "ordinal", + "sourceField": "workday.activity.task_display_name" + } + }, + "incompleteColumns": {}, + "sampling": 1 + } + } + }, + "indexpattern": { + "layers": {} + }, + "textBased": { + "layers": {} + } + }, + "filters": [ + { + "$state": { + "store": "appState" + }, + "meta": { + "alias": null, + "disabled": false, + "field": "data_stream.dataset", + "index": "1c7fed27-4972-44aa-99d6-50acd50ebf77", + "key": "data_stream.dataset", + "negate": false, + "params": { + "query": "workday.activity" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.activity" + } + } + } + ], + "internalReferences": [], + "query": { + "language": "kuery", + "query": "" + }, + "visualization": { + "axisTitlesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "fittingFunction": "Linear", + "gridlinesVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "labelsOrientation": { + "x": 0, + "yLeft": 0, + "yRight": 0 + }, + "layers": [ + { + "accessors": [ + "36af1c7c-1c80-429f-8d91-23f30dd15de2" + ], + "colorMapping": { + "assignments": [], + "colorMode": { + "type": "categorical" + }, + "paletteId": "eui_amsterdam_color_blind", + "specialAssignments": [ + { + "color": { + "type": "loop" + }, + "rule": { + "type": "other" + }, + "touched": false + } + ] + }, + "layerId": "fa079e28-a6a1-4905-8a54-8ea96d366522", + "layerType": "data", + "position": "top", + "seriesType": "bar_horizontal_stacked", + "showGridlines": false, + "xAccessor": "bbc5e3b5-bd2e-429a-99d7-4b6c298f347e" + } + ], + "legend": { + "isInside": false, + "isVisible": true, + "position": "right", + "shouldTruncate": false, + "showSingleSeries": false + }, + "preferredSeriesType": "bar_stacked", + "tickLabelsVisibilitySettings": { + "x": true, + "yLeft": true, + "yRight": true + }, + "valueLabels": "show" + } + }, + "title": "", + "type": "lens", + "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.activity" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.activity" + } + } + } + ], + "query": { + "language": "kuery", + "query": "" + }, + "syncColors": false, + "syncCursor": true, + "syncTooltips": false + }, + "gridData": { + "h": 14, + "i": "d97d5edd-bfd7-4fcb-ba7a-bc53137c63cf", + "w": 48, + "x": 0, + "y": 48 + }, + "panelIndex": "d97d5edd-bfd7-4fcb-ba7a-bc53137c63cf", + "title": "Top Tasks", + "type": "lens" + }, + { + "embeddableConfig": { + "columns": [ + "workday.activity.task_id", + "workday.activity.task_display_name", + "event.action", + "workday.activity.target.descriptor", + "workday.activity.target.id" + ], + "description": "", + "enhancements": { + "dynamicActions": { + "events": [] + } + }, + "grid": {}, + "sort": [ + [ + "@timestamp", + "desc" + ] + ] + }, + "gridData": { + "h": 16, + "i": "eac3b323-5a36-4a0f-ac1e-86fd4302ca2a", + "w": 48, + "x": 0, + "y": 62 + }, + "panelIndex": "eac3b323-5a36-4a0f-ac1e-86fd4302ca2a", + "panelRefName": "panel_eac3b323-5a36-4a0f-ac1e-86fd4302ca2a", + "title": "Activity Essential Details", + "type": "search" + } + ], + "timeRestore": false, + "title": "[Logs Workday] Activity Overview", + "version": 3 + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-04-07T21:59:04.297Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "workday-972e856e-47c4-4c27-966e-b9dfcd380d72", + "references": [ + { + "id": "logs-*", + "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index", + "type": "index-pattern" + }, + { + "id": "workday-b1b11266-913a-4ae4-9565-8c836b79ad2f", + "name": "eac3b323-5a36-4a0f-ac1e-86fd4302ca2a:panel_eac3b323-5a36-4a0f-ac1e-86fd4302ca2a", + "type": "search" + }, + { + "id": "logs-*", + "name": "3f9b13fc-ef22-4523-8b76-2f6a6dbbd5a4:indexpattern-datasource-layer-b8dea39e-0b66-4ad0-a7aa-54685762be20", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "3f9b13fc-ef22-4523-8b76-2f6a6dbbd5a4:594c9e9f-63f0-4016-a6b0-c6121c89cc7a", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "04bd84b5-05c0-42e1-af53-3a915d944478:indexpattern-datasource-layer-b8dea39e-0b66-4ad0-a7aa-54685762be20", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "04bd84b5-05c0-42e1-af53-3a915d944478:241ba901-4a5b-45a3-a505-fd54a5f62031", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "6b4baa90-3304-4072-a453-bf89456257ff:indexpattern-datasource-layer-c97022de-40c0-42cd-8f3e-e78632555e93", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "6b4baa90-3304-4072-a453-bf89456257ff:a0d4d60a-fc9e-41a4-89cb-7c8740b26ad5", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "5fdf6541-036a-4775-a483-655f8f49039e:indexpattern-datasource-layer-c97022de-40c0-42cd-8f3e-e78632555e93", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "5fdf6541-036a-4775-a483-655f8f49039e:f460aaaf-0800-45bf-b9d7-9c7ef809e5bb", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "4d46c40f-2ae6-4dcb-b44f-528ebb32e964:indexpattern-datasource-layer-de5fbb0f-d57a-4fbb-8bfd-e1631521ded8", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "4d46c40f-2ae6-4dcb-b44f-528ebb32e964:82ba8dc8-a207-4a85-a523-60014911e219", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "d97d5edd-bfd7-4fcb-ba7a-bc53137c63cf:indexpattern-datasource-layer-fa079e28-a6a1-4905-8a54-8ea96d366522", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "d97d5edd-bfd7-4fcb-ba7a-bc53137c63cf:1c7fed27-4972-44aa-99d6-50acd50ebf77", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "controlGroup_87cad3b1-43f0-441b-a3ba-8d266336557a:optionsListDataView", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "controlGroup_f0d05b20-49d6-492c-9bb8-456920a302ca:optionsListDataView", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "controlGroup_d352c978-a644-4ace-914f-b928f5c0add2: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/kibana/search/workday-b1b11266-913a-4ae4-9565-8c836b79ad2f.json b/packages/workday/kibana/search/workday-b1b11266-913a-4ae4-9565-8c836b79ad2f.json new file mode 100644 index 00000000000..5b701d8aa01 --- /dev/null +++ b/packages/workday/kibana/search/workday-b1b11266-913a-4ae4-9565-8c836b79ad2f.json @@ -0,0 +1,75 @@ +{ + "attributes": { + "columns": [ + "workday.activity.task_id", + "workday.activity.task_display_name", + "event.action", + "workday.activity.target.descriptor", + "workday.activity.target.id" + ], + "description": "", + "grid": {}, + "hideChart": false, + "isTextBasedQuery": false, + "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.activity" + }, + "type": "phrase" + }, + "query": { + "match_phrase": { + "data_stream.dataset": "workday.activity" + } + } + } + ], + "indexRefName": "kibanaSavedObjectMeta.searchSourceJSON.index", + "query": { + "language": "kuery", + "query": "" + } + } + }, + "sort": [ + [ + "@timestamp", + "desc" + ] + ], + "timeRestore": false, + "title": "Activity Essential Details [Logs Workday]" + }, + "coreMigrationVersion": "8.8.0", + "created_at": "2026-04-07T21:38:48.680Z", + "created_by": "u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0", + "id": "workday-b1b11266-913a-4ae4-9565-8c836b79ad2f", + "references": [ + { + "id": "logs-*", + "name": "kibanaSavedObjectMeta.searchSourceJSON.index", + "type": "index-pattern" + }, + { + "id": "logs-*", + "name": "kibanaSavedObjectMeta.searchSourceJSON.filter[0].meta.index", + "type": "index-pattern" + } + ], + "type": "search", + "typeMigrationVersion": "10.5.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 new file mode 100644 index 00000000000..8fc8dee9d51 --- /dev/null +++ b/packages/workday/manifest.yml @@ -0,0 +1,114 @@ +format_version: 3.3.2 +name: workday +title: 'Workday' +version: 0.1.0 +description: 'Collect logs from Workday with Elastic Agent.' +type: integration +categories: + - security +conditions: + kibana: + version: '^8.18.0 || ^9.0.0' + elastic: + subscription: 'basic' +screenshots: + - src: /img/workday-activity-dashboard.png + title: Activity Dashboard + size: 600x600 + type: image/png +icons: + - src: /img/workday-logo.svg + title: Workday logo + size: 32x32 + type: image/svg+xml +policy_templates: + - name: workday + title: Workday logs + description: Collect Workday logs. + deployment_modes: + default: + enabled: true + agentless: + enabled: true + organization: security + division: engineering + team: security-service-integrations + inputs: + - type: cel + 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 + description: proxy configuration in the form of https://:@:. + multi: false + required: false + show_user: false + - name: ssl + type: yaml + title: SSL Configuration + description: SSL configuration options. See [documentation](https://www.elastic.co/guide/en/beats/filebeat/current/configuration-ssl.html#ssl-common-config) for details. + multi: false + required: false + show_user: false + default: | + #certificate_authorities: + # - | + # -----BEGIN CERTIFICATE----- + # MIIDCjCCAfKgAwIBAgITJ706Mu2wJlKckpIvkWxEHvEyijANBgkqhkiG9w0BAQsF + # ADAUMRIwEAYDVQQDDAlsb2NhbGhvc3QwIBcNMTkwNzIyMTkyOTA0WhgPMjExOTA2 + # MjgxOTI5MDRaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEB + # BQADggEPADCCAQoCggEBANce58Y/JykI58iyOXpxGfw0/gMvF0hUQAcUrSMxEO6n + # fZRA49b4OV4SwWmA3395uL2eB2NB8y8qdQ9muXUdPBWE4l9rMZ6gmfu90N5B5uEl + # 94NcfBfYOKi1fJQ9i7WKhTjlRkMCgBkWPkUokvBZFRt8RtF7zI77BSEorHGQCk9t + # /D7BS0GJyfVEhftbWcFEAG3VRcoMhF7kUzYwp+qESoriFRYLeDWv68ZOvG7eoWnP + # PsvZStEVEimjvK5NSESEQa9xWyJOmlOKXhkdymtcUd/nXnx6UTCFgnkgzSdTWV41 + # CI6B6aJ9svCTI2QuoIq2HxX/ix7OvW1huVmcyHVxyUECAwEAAaNTMFEwHQYDVR0O + # BBYEFPwN1OceFGm9v6ux8G+DZ3TUDYxqMB8GA1UdIwQYMBaAFPwN1OceFGm9v6ux + # 8G+DZ3TUDYxqMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAG5D + # 874A4YI7YUwOVsVAdbWtgp1d0zKcPRR+r2OdSbTAV5/gcS3jgBJ3i1BN34JuDVFw + # 3DeJSYT3nxy2Y56lLnxDeF8CUTUtVQx3CuGkRg1ouGAHpO/6OqOhwLLorEmxi7tA + # H2O8mtT0poX5AnOAhzVy7QW0D/k4WaoLyckM5hUa6RtvgvLxOwA0U+VGurCDoctu + # 8F4QOgTAWyh8EZIwaKCliFRSynDpv3JTUwtfZkxo6K6nce1RhCWFAsMvDZL8Dgc0 + # yvgJ38BRsFOtkRuAGSf6ZUwTO8JJRRIFnpUzXflAnGivK9M13D5GEQMmIl6U9Pvk + # sxSmbIUfc2SGJGCJD4I= + # -----END CERTIFICATE----- +owner: + github: elastic/security-service-integrations + type: elastic diff --git a/packages/workday/validation.yml b/packages/workday/validation.yml new file mode 100644 index 00000000000..0d5da503363 --- /dev/null +++ b/packages/workday/validation.yml @@ -0,0 +1,4 @@ +errors: + exclude_checks: + - SVR00004 # References in dashboards. + - SVR00005 # Kibana version for saved tags.