diff --git a/packages/entityanalytics_ad/changelog.yml b/packages/entityanalytics_ad/changelog.yml index f6f4cb1e9c6..c4b98c14a15 100644 --- a/packages/entityanalytics_ad/changelog.yml +++ b/packages/entityanalytics_ad/changelog.yml @@ -1,4 +1,9 @@ # newer versions go on top +- version: "0.17.0" + changes: + - description: Improve field mappings for device entities. + type: enhancement + link: https://github.com/elastic/integrations/pull/15642 - version: "0.16.0" changes: - description: Add support for collection device entities. diff --git a/packages/entityanalytics_ad/data_stream/entity/_dev/test/pipeline/test-device.json b/packages/entityanalytics_ad/data_stream/entity/_dev/test/pipeline/test-device.json new file mode 100644 index 00000000000..105b49885ab --- /dev/null +++ b/packages/entityanalytics_ad/data_stream/entity/_dev/test/pipeline/test-device.json @@ -0,0 +1,138 @@ +{ + "events": [ + { + "@timestamp": "2025-10-09T21:34:29.084Z", + "activedirectory": { + "device": { + "account_expires": "9223372036854775807", + "account_never_expires": true, + "bad_password_time": "133251039041149826", + "bad_pwd_count": "0", + "cn": "TEST12009", + "dNSHostName": "TEST12009.org.test.local", + "description": "Kretts, Topsy", + "distinguished_name": "CN=TEST12009,OU=Policy Exception 3,OU=Computers,OU=Information Technology Services,OU=Executive,OU=Users and Computers,DC=org,DC=test,DC=local", + "instance_type": "4", + "is_critical_system_object": false, + "last_logon": "2025-10-07T13:39:18.7867226Z", + "last_logon_timestamp": "2025-09-30T14:42:35.7840088Z", + "logon_count": "2275", + "member_of": [ + "CN=GPOD Office Updates,OU=User Groups,DC=org,DC=test,DC=local", + "CN=GPOD Test Defender for Endpoint,OU=User Groups,DC=org,DC=test,DC=local", + "CN=GPOD Windows 11,OU=User Groups,DC=org,DC=test,DC=local", + "CN=GPOD Applocker Enforce,OU=User Groups,DC=org,DC=test,DC=local", + "CN=GPOD Office 365 & OneDrive,OU=User Groups,DC=org,DC=test,DC=local", + "CN=GPOD Remote Desktop,OU=User Groups,DC=org,DC=test,DC=local" + ], + "name": "TEST12009", + "object_class": [ + "top", + "person", + "organizationalPerson", + "user", + "computer" + ], + "object_guid": "5d02cebc-ffd5-4903-ad8e-d9ef36cd6cbb", + "object_sid": "S-1-5-21-1133191089-1850170202-1535859923-274531", + "operatingSystem": "Windows 11 Enterprise", + "operatingSystemVersion": "10.0 (26100)", + "privileged_group_member": false, + "pwd_last_set": "2025-09-10T13:45:36.9983472Z", + "sam_account_name": "TEST12009$", + "service_principal_name": [ + "WSMAN/TEST12009", + "WSMAN/TEST12009.org.test.local", + "TERMSRV/TEST12009", + "TERMSRV/TEST12009.org.test.local", + "RestrictedKrbHost/TEST12009", + "HOST/TEST12009", + "RestrictedKrbHost/TEST12009.org.test.local", + "HOST/TEST12009.org.test.local" + ], + "when_changed": "2025-09-30T14:42:41Z", + "when_created": "2022-03-02T21:14:42Z" + }, + "groups": [ + { + "distinguished_name": "CN=GPOD Office Updates,OU=User Groups,DC=org,DC=test,DC=local", + "name": "GPOD Office Updates", + "object_class": [ + "top", + "group" + ], + "object_guid": "36ef7eb9-0dac-4c83-8e7d-990dd25b1369", + "sam_account_name": "GPOD Office Updates", + "when_changed": "2025-10-09T14:02:02Z" + }, + { + "distinguished_name": "CN=GPOD Test Defender for Endpoint,OU=User Groups,DC=org,DC=test,DC=local", + "name": "GPOD Test Defender for Endpoint", + "object_class": [ + "top", + "group" + ], + "object_guid": "894d8230-aa33-4344-9d96-da049c82e9cf", + "sam_account_name": "GPOD Test Defender for Endpoint", + "when_changed": "2022-09-14T02:04:25Z" + }, + { + "distinguished_name": "CN=GPOD Windows 11,OU=User Groups,DC=org,DC=test,DC=local", + "name": "GPOD Windows 11", + "object_class": [ + "top", + "group" + ], + "object_guid": "f6533b99-a816-4408-a5a5-493ef2a22381", + "sam_account_name": "GPOD Windows 11", + "when_changed": "2025-10-09T21:11:28Z" + }, + { + "distinguished_name": "CN=GPOD Applocker Enforce,OU=User Groups,DC=org,DC=test,DC=local", + "name": "GPOD Applocker Enforce", + "object_class": [ + "top", + "group" + ], + "object_guid": "d4ae2b30-7032-4fc2-b9c1-a369ff12f6d9", + "sam_account_name": "GPOD Applocker Enforce", + "when_changed": "2025-07-14T15:14:38Z" + }, + { + "distinguished_name": "CN=GPOD Office 365 & OneDrive,OU=User Groups,DC=org,DC=test,DC=local", + "name": "GPOD Office 365 & OneDrive", + "object_class": [ + "top", + "group" + ], + "object_guid": "2c526d70-2f92-41bb-bbd9-67a614ca09a6", + "sam_account_name": "GPOD Office 365 & OneDrive", + "when_changed": "2025-10-09T21:11:28Z" + }, + { + "distinguished_name": "CN=GPOD Remote Desktop,OU=User Groups,DC=org,DC=test,DC=local", + "name": "GPOD Remote Desktop", + "object_class": [ + "top", + "group" + ], + "object_guid": "d7798c2b-9b53-498a-b65e-57f0653fc669", + "sam_account_name": "GPOD Remote Desktop", + "when_changed": "2025-10-09T18:45:27Z" + } + ], + "id": "CN=TEST12009,OU=Policy Exception 3,OU=Computers,OU=Information Technology Services,OU=Executive,OU=Users and Computers,DC=org,DC=test,DC=local", + "when_changed": "2025-10-09T21:11:28Z" + }, + "event": { + "action": "device-discovered" + }, + "labels": { + "identity_source": "entity-analytics-entityanalytics_ad.device-8c3c1f67-428d-4a95-a6de-69a2b8f952c3" + }, + "device": { + "id": "CN=TEST12009,OU=Policy Exception 3,OU=Computers,OU=Information Technology Services,OU=Executive,OU=Users and Computers,DC=org,DC=test,DC=local" + } + } + ] +} diff --git a/packages/entityanalytics_ad/data_stream/entity/_dev/test/pipeline/test-device.json-expected.json b/packages/entityanalytics_ad/data_stream/entity/_dev/test/pipeline/test-device.json-expected.json new file mode 100644 index 00000000000..272a463b709 --- /dev/null +++ b/packages/entityanalytics_ad/data_stream/entity/_dev/test/pipeline/test-device.json-expected.json @@ -0,0 +1,198 @@ +{ + "expected": [ + { + "@timestamp": "2025-10-09T21:34:29.084Z", + "asset": { + "category": "entity", + "create_date": "2022-03-02T21:14:42.000Z", + "id": "S-1-5-21-1133191089-1850170202-1535859923-274531", + "last_updated": "2025-09-30T14:42:41.000Z", + "name": "test12009.org.test.local", + "type": "activedirectory_user" + }, + "data_stream": { + "dataset": "entityanalytics_ad.device", + "namespace": "default", + "type": "logs" + }, + "device": { + "id": "S-1-5-21-1133191089-1850170202-1535859923-274531" + }, + "ecs": { + "version": "8.11.0" + }, + "entityanalytics_ad": { + "device": { + "account_expires": "9223372036854775807", + "account_never_expires": true, + "bad_password_time": "133251039041149826", + "bad_pwd_count": "0", + "cn": "TEST12009", + "description": "Kretts, Topsy", + "distinguished_name": "CN=TEST12009,OU=Policy Exception 3,OU=Computers,OU=Information Technology Services,OU=Executive,OU=Users and Computers,DC=org,DC=test,DC=local", + "dns_host_name": "TEST12009.org.test.local", + "instance_type": "4", + "is_critical_system_object": false, + "last_logon": "2025-10-07T13:39:18.7867226Z", + "last_logon_timestamp": "2025-09-30T14:42:35.7840088Z", + "logon_count": "2275", + "member_of": [ + "CN=GPOD Office Updates,OU=User Groups,DC=org,DC=test,DC=local", + "CN=GPOD Test Defender for Endpoint,OU=User Groups,DC=org,DC=test,DC=local", + "CN=GPOD Windows 11,OU=User Groups,DC=org,DC=test,DC=local", + "CN=GPOD Applocker Enforce,OU=User Groups,DC=org,DC=test,DC=local", + "CN=GPOD Office 365 & OneDrive,OU=User Groups,DC=org,DC=test,DC=local", + "CN=GPOD Remote Desktop,OU=User Groups,DC=org,DC=test,DC=local" + ], + "name": "TEST12009", + "object_class": [ + "top", + "person", + "organizationalPerson", + "user", + "computer" + ], + "object_dn": "CN=TEST12009,OU=Policy Exception 3,OU=Computers,OU=Information Technology Services,OU=Executive,OU=Users and Computers,DC=org,DC=test,DC=local", + "object_guid": "5d02cebc-ffd5-4903-ad8e-d9ef36cd6cbb", + "object_sid": "S-1-5-21-1133191089-1850170202-1535859923-274531", + "operating_system": "Windows 11 Enterprise", + "operating_system_version": "10.0 (26100)", + "privileged_group_member": false, + "pwd_last_set": "2025-09-10T13:45:36.9983472Z", + "sam_account_name": "TEST12009$", + "service_principal_name": [ + "WSMAN/TEST12009", + "WSMAN/TEST12009.org.test.local", + "TERMSRV/TEST12009", + "TERMSRV/TEST12009.org.test.local", + "RestrictedKrbHost/TEST12009", + "HOST/TEST12009", + "RestrictedKrbHost/TEST12009.org.test.local", + "HOST/TEST12009.org.test.local" + ], + "when_changed": "2025-09-30T14:42:41Z", + "when_created": "2022-03-02T21:14:42Z" + }, + "groups": [ + { + "distinguished_name": "CN=GPOD Office Updates,OU=User Groups,DC=org,DC=test,DC=local", + "name": "GPOD Office Updates", + "object_class": [ + "top", + "group" + ], + "object_guid": "36ef7eb9-0dac-4c83-8e7d-990dd25b1369", + "sam_account_name": "GPOD Office Updates", + "when_changed": "2025-10-09T14:02:02Z" + }, + { + "distinguished_name": "CN=GPOD Test Defender for Endpoint,OU=User Groups,DC=org,DC=test,DC=local", + "name": "GPOD Test Defender for Endpoint", + "object_class": [ + "top", + "group" + ], + "object_guid": "894d8230-aa33-4344-9d96-da049c82e9cf", + "sam_account_name": "GPOD Test Defender for Endpoint", + "when_changed": "2022-09-14T02:04:25Z" + }, + { + "distinguished_name": "CN=GPOD Windows 11,OU=User Groups,DC=org,DC=test,DC=local", + "name": "GPOD Windows 11", + "object_class": [ + "top", + "group" + ], + "object_guid": "f6533b99-a816-4408-a5a5-493ef2a22381", + "sam_account_name": "GPOD Windows 11", + "when_changed": "2025-10-09T21:11:28Z" + }, + { + "distinguished_name": "CN=GPOD Applocker Enforce,OU=User Groups,DC=org,DC=test,DC=local", + "name": "GPOD Applocker Enforce", + "object_class": [ + "top", + "group" + ], + "object_guid": "d4ae2b30-7032-4fc2-b9c1-a369ff12f6d9", + "sam_account_name": "GPOD Applocker Enforce", + "when_changed": "2025-07-14T15:14:38Z" + }, + { + "distinguished_name": "CN=GPOD Office 365 & OneDrive,OU=User Groups,DC=org,DC=test,DC=local", + "name": "GPOD Office 365 & OneDrive", + "object_class": [ + "top", + "group" + ], + "object_guid": "2c526d70-2f92-41bb-bbd9-67a614ca09a6", + "sam_account_name": "GPOD Office 365 & OneDrive", + "when_changed": "2025-10-09T21:11:28Z" + }, + { + "distinguished_name": "CN=GPOD Remote Desktop,OU=User Groups,DC=org,DC=test,DC=local", + "name": "GPOD Remote Desktop", + "object_class": [ + "top", + "group" + ], + "object_guid": "d7798c2b-9b53-498a-b65e-57f0653fc669", + "sam_account_name": "GPOD Remote Desktop", + "when_changed": "2025-10-09T18:45:27Z" + } + ], + "when_changed": "2025-10-09T21:11:28Z" + }, + "event": { + "category": [ + "iam" + ], + "kind": "asset", + "type": [ + "info" + ] + }, + "host": { + "domain": "org.test.local", + "hostname": "TEST12009", + "name": "test12009.org.test.local", + "os": { + "full": "Windows 11 Enterprise", + "version": "10.0 (26100)" + } + }, + "labels": { + "identity_source": "entity-analytics-entityanalytics_ad.device-8c3c1f67-428d-4a95-a6de-69a2b8f952c3" + }, + "related": { + "hosts": [ + "test12009.org.test.local", + "CN=TEST12009,OU=Policy Exception 3,OU=Computers,OU=Information Technology Services,OU=Executive,OU=Users and Computers,DC=org,DC=test,DC=local", + "5d02cebc-ffd5-4903-ad8e-d9ef36cd6cbb" + ], + "user": [ + "TEST12009$" + ] + }, + "tags": [ + "preserve_duplicate_custom_fields" + ], + "user": { + "account": { + "password_change_date": "2025-09-10T13:45:36.998Z" + }, + "group": { + "name": [ + "GPOD Applocker Enforce", + "GPOD Office 365 & OneDrive", + "GPOD Test Defender for Endpoint", + "GPOD Remote Desktop", + "GPOD Office Updates", + "GPOD Windows 11" + ] + }, + "name": "TEST12009$" + } + } + ] +} diff --git a/packages/entityanalytics_ad/data_stream/entity/_dev/test/pipeline/test-user.json b/packages/entityanalytics_ad/data_stream/entity/_dev/test/pipeline/test-user.json index 63fc5ab8c4e..99bb3ee7f2d 100644 --- a/packages/entityanalytics_ad/data_stream/entity/_dev/test/pipeline/test-user.json +++ b/packages/entityanalytics_ad/data_stream/entity/_dev/test/pipeline/test-user.json @@ -365,4 +365,4 @@ } } ] -} \ No newline at end of file +} diff --git a/packages/entityanalytics_ad/data_stream/entity/elasticsearch/ingest_pipeline/common.yml b/packages/entityanalytics_ad/data_stream/entity/elasticsearch/ingest_pipeline/common.yml index c5708eab7c4..57992ccd261 100644 --- a/packages/entityanalytics_ad/data_stream/entity/elasticsearch/ingest_pipeline/common.yml +++ b/packages/entityanalytics_ad/data_stream/entity/elasticsearch/ingest_pipeline/common.yml @@ -14,6 +14,7 @@ processors: "countryCode": "country_code" "description": "description" "distinguishedName": "distinguished_name" + "dNSHostName": "dns_host_name" "dSCorePropagationData": "ds_core_propagation_data" "groups": "groups" "groupType": "group_type" @@ -31,6 +32,8 @@ processors: "objectClass": "object_class" "objectGUID": "object_guid" "objectSid": "object_sid" + "operatingSystem": "operating_system" + "operatingSystemVersion": "operating_system_version" "primaryGroupID": "primary_group_id" "pwdLastSet": "pwd_last_set" "sAMAccountName": "sam_account_name" @@ -139,172 +142,6 @@ processors: ctx.activedirectory = renameKeys(ctx.activedirectory, params) - - script: - lang: painless - ignore_failure: false - tag: Set User Account Control - description: Set User Account Control - # USER_ACCOUNT Codes - # https://learn.microsoft.com/en-us/windows/win32/adschema/a-useraccountcontrol - # https://learn.microsoft.com/en-us/windows/win32/api/iads/ne-iads-ads_user_flag_enum - params: - "0x00000001": SCRIPT - "0x00000002": ACCOUNTDISABLE - "0x00000008": HOMEDIR_REQUIRED - "0x00000010": LOCKOUT - "0x00000020": PASSWD_NOTREQD - "0x00000040": PASSWD_CANT_CHANGE - "0x00000080": ENCRYPTED_TEXT_PWD_ALLOWED - "0x00000100": TEMP_DUPLICATE_ACCOUNT - "0x00000200": NORMAL_ACCOUNT - "0x00000800": INTERDOMAIN_TRUST_ACCOUNT - "0x00001000": WORKSTATION_TRUST_ACCOUNT - "0x00002000": SERVER_TRUST_ACCOUNT - "0x00010000": DONT_EXPIRE_PASSWORD - "0x00020000": MNS_LOGON_ACCOUNT - "0x00040000": SMARTCARD_REQUIRED - "0x00080000": TRUSTED_FOR_DELEGATION - "0x00100000": NOT_DELEGATED - "0x00200000": USE_DES_KEY_ONLY - "0x00400000": DONT_REQUIRE_PREAUTH - "0x00800000": PASSWORD_EXPIRED - "0x01000000": TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION - "0x04000000": PARTIAL_SECRETS_ACCOUNT - source: |- - Long newUacValue = Long.decode(ctx.activedirectory.user.user_account_control); - ArrayList uacResult = new ArrayList(); - for (entry in params.entrySet()) { - Long flag = Long.decode(entry.getKey()); - if ((newUacValue.longValue() & flag.longValue()) != 0) { - uacResult.add(entry.getValue()); - } - } - if (uacResult.length != 0) { - ctx.activedirectory.user.uac_list = uacResult; - } - if: ctx.activedirectory?.user?.user_account_control != null && ctx.activedirectory.user.user_account_control != 0 - - - date: - field: activedirectory.user.when_created - target_field: asset.create_date - tag: date_user_created - formats: - - ISO8601 - if: ctx.activedirectory?.user?.when_created != null && ctx.activedirectory.user.when_created != '' - on_failure: - - remove: - field: activedirectory.user.when_created - - append: - field: error.message - value: 'Processor {{{_ingest.on_failure_processor_type}}} with tag {{{_ingest.on_failure_processor_tag}}} in pipeline {{{_ingest.pipeline}}} failed with message: {{{_ingest.on_failure_message}}}' - - date: - field: activedirectory.user.when_changed - target_field: asset.last_updated - tag: date_user_changed - formats: - - ISO8601 - if: ctx.activedirectory?.user?.when_changed != null && ctx.activedirectory.user.when_changed != '' - on_failure: - - remove: - field: activedirectory.user.when_changed - - append: - field: error.message - value: 'Processor {{{_ingest.on_failure_processor_type}}} with tag {{{_ingest.on_failure_processor_tag}}} in pipeline {{{_ingest.pipeline}}} failed with message: {{{_ingest.on_failure_message}}}' - - date: - field: activedirectory.user.pwd_last_set - target_field: user.account.password_change_date - tag: date_user_password_changed - formats: - - ISO8601 - if: ctx.activedirectory?.user?.pwd_last_set != null && ctx.activedirectory.user.pwd_last_set != '' - on_failure: - - remove: - field: activedirectory.user.pwd_last_set - - append: - field: error.message - value: 'Processor {{{_ingest.on_failure_processor_type}}} with tag {{{_ingest.on_failure_processor_tag}}} in pipeline {{{_ingest.pipeline}}} failed with message: {{{_ingest.on_failure_message}}}' - - - set: - field: asset.name - copy_from: activedirectory.user.sam_account_name - ignore_empty_value: true - - set: - field: user.name - copy_from: activedirectory.user.sam_account_name - ignore_empty_value: true - - gsub: - tag: gsub_user_dn - field: activedirectory.user.distinguished_name - pattern: '^.*?DC=' - replacement: '' - target_field: user.domain - if: ctx.activedirectory?.user?.distinguished_name != null - - gsub: - tag: gsub_user_domain - field: user.domain - pattern: ',DC=' - replacement: '.' - if: ctx.user?.domain != null - - set: - field: asset.id - copy_from: activedirectory.user.object_sid - - set: - field: user.id - copy_from: activedirectory.user.object_sid - - - set: - field: activedirectory.user.logon_script_enabled - value: true - if: ctx.activedirectory?.user?.uac_list?.contains('SCRIPT') == true - - set: - field: activedirectory.user.enabled - value: true - if: ctx.activedirectory?.user?.uac_list?.contains('ACCOUNTDISABLE') == false - - set: - field: activedirectory.user.enabled - value: false - if: ctx.activedirectory?.user?.uac_list?.contains('ACCOUNTDISABLE') == true - - - set: - field: activedirectory.user.locked - value: true - if: ctx.activedirectory?.user?.uac_list?.contains('LOCKOUT') == true - - - set: - field: activedirectory.user.password_not_required - value: true - if: ctx.activedirectory?.user?.uac_list?.contains('PASSWD_NOTREQD') == true - - - set: - field: activedirectory.user.reversible_encryption_password - value: true - if: ctx.activedirectory?.user?.uac_list?.contains('ENCRYPTED_TEXT_PWD_ALLOWED') == true - - - set: - field: activedirectory.user.unconstrained_delegation - value: true - if: ctx.activedirectory?.user?.uac_list?.contains('TRUSTED_FOR_DELEGATION') == true - - - set: - field: activedirectory.user.sensitive_object - value: true - if: ctx.activedirectory?.user?.uac_list?.contains('NOT_DELEGATED') == true - - - set: - field: activedirectory.user.use_des_key_only - value: true - if: ctx.activedirectory?.user?.uac_list?.contains('USE_DES_KEY_ONLY') == true - - - set: - field: activedirectory.user.dont_require_preauth - value: true - if: ctx.activedirectory?.user?.uac_list?.contains('DONT_REQUIRE_PREAUTH') == true - - - set: - field: activedirectory.user.constrained_delegation - value: true - if: ctx.activedirectory?.user?.uac_list?.contains('TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION') == true - - foreach: tag: foreach_group field: activedirectory.groups @@ -317,63 +154,6 @@ processors: field: _ingest._value.member ignore_missing: true - - script: - lang: painless - ignore_failure: true - tag: handle_user_group_details - description: Collect user's group details and set privileged_group_member flag based on group membership. - if: ctx.activedirectory?.groups instanceof List - # Well-known SIDs - Name to SID mapping - # https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/understand-security-identifiers#well-known-sids - params: - '512': true - '516': true - '518': true - '519': true - '520': true - '525': true - '526': true - '527': true - '544': true - '548': true - '549': true - '551': true - source: |- - ctx.user = ctx.user ?: [:]; - ctx.user.group = ctx.user.group ?: [:]; - - for (def group : ctx.activedirectory.groups) { - if (group.name != null) { - ctx.user.group.name = ctx.user.group.name ?: new HashSet(); - ctx.user.group.name.add(group.name); - } - - if (group?.object_sid == null) { - continue; - } - - group.id = group.object_sid; - ctx.user.group.id = ctx.user.group.id ?: new HashSet(); - ctx.user.group.id.add(group.id); - - int idx = group.object_sid.lastIndexOf('-'); - if (idx < 0) { - continue; - } - def priv = params.get(group.object_sid.substring(idx+1)); - if (priv != null && ctx.activedirectory.user.privileged_group_member == null) { - ctx.activedirectory.user.privileged_group_member = priv; - } - } - if (ctx.activedirectory.user.privileged_group_member == null) { - ctx.activedirectory.user.privileged_group_member = false; - } - - - set: - field: activedirectory.user.account_never_expires - value: true - if: ctx.activedirectory?.user?.account_expires == "0" || ctx.activedirectory?.user?.account_expires == "9223372036854775807" - on_failure: - append: field: error.message diff --git a/packages/entityanalytics_ad/data_stream/entity/elasticsearch/ingest_pipeline/device.yml b/packages/entityanalytics_ad/data_stream/entity/elasticsearch/ingest_pipeline/device.yml index 1fa815eee18..990c813b605 100644 --- a/packages/entityanalytics_ad/data_stream/entity/elasticsearch/ingest_pipeline/device.yml +++ b/packages/entityanalytics_ad/data_stream/entity/elasticsearch/ingest_pipeline/device.yml @@ -27,32 +27,270 @@ processors: tag: pipeline_entity ignore_missing_pipeline: true + - script: + lang: painless + ignore_failure: false + tag: Set User Account Control + description: script_set_user_account_control + # USER_ACCOUNT Codes + # https://learn.microsoft.com/en-us/windows/win32/adschema/a-useraccountcontrol + # https://learn.microsoft.com/en-us/windows/win32/api/iads/ne-iads-ads_user_flag_enum + params: + "0x00000001": SCRIPT + "0x00000002": ACCOUNTDISABLE + "0x00000008": HOMEDIR_REQUIRED + "0x00000010": LOCKOUT + "0x00000020": PASSWD_NOTREQD + "0x00000040": PASSWD_CANT_CHANGE + "0x00000080": ENCRYPTED_TEXT_PWD_ALLOWED + "0x00000100": TEMP_DUPLICATE_ACCOUNT + "0x00000200": NORMAL_ACCOUNT + "0x00000800": INTERDOMAIN_TRUST_ACCOUNT + "0x00001000": WORKSTATION_TRUST_ACCOUNT + "0x00002000": SERVER_TRUST_ACCOUNT + "0x00010000": DONT_EXPIRE_PASSWORD + "0x00020000": MNS_LOGON_ACCOUNT + "0x00040000": SMARTCARD_REQUIRED + "0x00080000": TRUSTED_FOR_DELEGATION + "0x00100000": NOT_DELEGATED + "0x00200000": USE_DES_KEY_ONLY + "0x00400000": DONT_REQUIRE_PREAUTH + "0x00800000": PASSWORD_EXPIRED + "0x01000000": TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION + "0x04000000": PARTIAL_SECRETS_ACCOUNT + source: |- + Long newUacValue = Long.decode(ctx.activedirectory.device.user_account_control); + ArrayList uacResult = new ArrayList(); + for (entry in params.entrySet()) { + Long flag = Long.decode(entry.getKey()); + if ((newUacValue.longValue() & flag.longValue()) != 0) { + uacResult.add(entry.getValue()); + } + } + if (uacResult.length != 0) { + ctx.activedirectory.device.uac_list = uacResult; + } + if: ctx.activedirectory?.device?.user_account_control != null && ctx.activedirectory.device.user_account_control != 0 + + - date: + field: activedirectory.device.when_created + target_field: asset.create_date + tag: date_device_created + formats: + - ISO8601 + if: ctx.activedirectory?.device?.when_created != null && ctx.activedirectory.device.when_created != '' + on_failure: + - remove: + field: activedirectory.device.when_created + - append: + field: error.message + value: 'Processor {{{_ingest.on_failure_processor_type}}} with tag {{{_ingest.on_failure_processor_tag}}} in pipeline {{{_ingest.pipeline}}} failed with message: {{{_ingest.on_failure_message}}}' + - date: + field: activedirectory.device.when_changed + target_field: asset.last_updated + tag: date_device_changed + formats: + - ISO8601 + if: ctx.activedirectory?.device?.when_changed != null && ctx.activedirectory.device.when_changed != '' + on_failure: + - remove: + field: activedirectory.device.when_changed + - append: + field: error.message + value: 'Processor {{{_ingest.on_failure_processor_type}}} with tag {{{_ingest.on_failure_processor_tag}}} in pipeline {{{_ingest.pipeline}}} failed with message: {{{_ingest.on_failure_message}}}' + - date: + field: activedirectory.device.pwd_last_set + target_field: user.account.password_change_date + tag: date_user_password_changed + formats: + - ISO8601 + if: ctx.activedirectory?.device?.pwd_last_set != null && ctx.activedirectory.device.pwd_last_set != '' + on_failure: + - remove: + field: activedirectory.device.pwd_last_set + - append: + field: error.message + value: 'Processor {{{_ingest.on_failure_processor_type}}} with tag {{{_ingest.on_failure_processor_tag}}} in pipeline {{{_ingest.pipeline}}} failed with message: {{{_ingest.on_failure_message}}}' + + - lowercase: + field: activedirectory.device.dns_host_name + target_field: asset.name + ignore_missing: true + - set: + field: user.name + copy_from: activedirectory.device.sam_account_name + ignore_empty_value: true + - set: + field: asset.id + copy_from: activedirectory.device.object_sid + - set: + field: device.id + copy_from: activedirectory.device.object_sid + + - set: + field: activedirectory.device.logon_script_enabled + value: true + if: ctx.activedirectory?.device?.uac_list?.contains('SCRIPT') == true + - set: + field: activedirectory.device.enabled + value: true + if: ctx.activedirectory?.device?.uac_list?.contains('ACCOUNTDISABLE') == false + - set: + field: activedirectory.device.enabled + value: false + if: ctx.activedirectory?.device?.uac_list?.contains('ACCOUNTDISABLE') == true + + - set: + field: activedirectory.device.locked + value: true + if: ctx.activedirectory?.device?.uac_list?.contains('LOCKOUT') == true + + - set: + field: activedirectory.device.password_not_required + value: true + if: ctx.activedirectory?.device?.uac_list?.contains('PASSWD_NOTREQD') == true + + - set: + field: activedirectory.device.reversible_encryption_password + value: true + if: ctx.activedirectory?.device?.uac_list?.contains('ENCRYPTED_TEXT_PWD_ALLOWED') == true + + - set: + field: activedirectory.device.unconstrained_delegation + value: true + if: ctx.activedirectory?.device?.uac_list?.contains('TRUSTED_FOR_DELEGATION') == true + + - set: + field: activedirectory.device.sensitive_object + value: true + if: ctx.activedirectory?.device?.uac_list?.contains('NOT_DELEGATED') == true + + - set: + field: activedirectory.device.use_des_key_only + value: true + if: ctx.activedirectory?.device?.uac_list?.contains('USE_DES_KEY_ONLY') == true + + - set: + field: activedirectory.device.dont_require_preauth + value: true + if: ctx.activedirectory?.device?.uac_list?.contains('DONT_REQUIRE_PREAUTH') == true + + - set: + field: activedirectory.device.constrained_delegation + value: true + if: ctx.activedirectory?.device?.uac_list?.contains('TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION') == true + + - script: + lang: painless + ignore_failure: true + tag: handle_user_group_details + description: Collect user's group details and set privileged_group_member flag based on group membership. + if: ctx.activedirectory?.groups instanceof List + # Well-known SIDs - Name to SID mapping + # https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/understand-security-identifiers#well-known-sids + params: + '512': true + '516': true + '518': true + '519': true + '520': true + '525': true + '526': true + '527': true + '544': true + '548': true + '549': true + '551': true + source: |- + ctx.user = ctx.user ?: [:]; + ctx.user.group = ctx.user.group ?: [:]; + + for (def group : ctx.activedirectory.groups) { + if (group.name != null) { + ctx.user.group.name = ctx.user.group.name ?: new HashSet(); + ctx.user.group.name.add(group.name); + } + + if (group?.object_sid == null) { + continue; + } + + group.id = group.object_sid; + ctx.user.group.id = ctx.user.group.id ?: new HashSet(); + ctx.user.group.id.add(group.id); + + int idx = group.object_sid.lastIndexOf('-'); + if (idx < 0) { + continue; + } + def priv = params.get(group.object_sid.substring(idx+1)); + if (priv != null && ctx.activedirectory.device.privileged_group_member == null) { + ctx.activedirectory.device.privileged_group_member = priv; + } + } + if (ctx.activedirectory.device.privileged_group_member == null) { + ctx.activedirectory.device.privileged_group_member = false; + } + + - set: + field: activedirectory.device.account_never_expires + value: true + if: ctx.activedirectory?.device?.account_expires == "0" || ctx.activedirectory?.device?.account_expires == "9223372036854775807" + + - set: + field: host.hostname + copy_from: activedirectory.device.cn + ignore_empty_value: true + - lowercase: + field: activedirectory.device.dns_host_name + target_field: host.name + ignore_missing: true + - dissect: + field: host.name + pattern: '%{}.%{host.domain}' + if: >- + ctx.host?.name instanceof String && + ctx.host?.hostname instanceof String && + ctx.host.name.contains('.') && + ctx.host.name.startsWith(ctx.host.hostname.toLowerCase()+'.') + + - set: + field: host.os.full + copy_from: activedirectory.device.operating_system + ignore_empty_value: true + - set: + field: host.os.version + copy_from: activedirectory.device.operating_system_version + ignore_empty_value: true + - append: field: related.user - value: "{{{activedirectory.user.sam_account_name}}}" + value: "{{{activedirectory.device.sam_account_name}}}" tag: append_name_into_related_user allow_duplicates: false - if: ctx.activedirectory?.user?.sam_account_name != null + if: ctx.activedirectory?.device?.sam_account_name != null - append: - field: related.user + field: related.hosts + value: "{{{host.name}}}" + tag: append_host_name_into_related_hosts + allow_duplicates: false + if: ctx.host?.name != null + - append: + field: related.hosts value: "{{{activedirectory.id}}}" - tag: append_id_into_related_user + tag: append_id_into_related_hosts allow_duplicates: false if: ctx.activedirectory?.id != null - append: - field: related.user - value: "{{{activedirectory.user.object_guid}}}" - tag: append_object_guid_into_related_user + field: related.hosts + value: "{{{activedirectory.device.object_guid}}}" + tag: append_object_guid_into_related_hosts allow_duplicates: false - if: ctx.activedirectory?.user?.object_guid != null + if: ctx.activedirectory?.device?.object_guid != null - rename: field: activedirectory.id - target_field: activedirectory.user.object_dn - - - rename: - field: activedirectory.user - target_field: activedirectory.device + target_field: activedirectory.device.object_dn - rename: field: activedirectory diff --git a/packages/entityanalytics_ad/data_stream/entity/elasticsearch/ingest_pipeline/user.yml b/packages/entityanalytics_ad/data_stream/entity/elasticsearch/ingest_pipeline/user.yml index 153f95d9665..769dd7fb3a0 100644 --- a/packages/entityanalytics_ad/data_stream/entity/elasticsearch/ingest_pipeline/user.yml +++ b/packages/entityanalytics_ad/data_stream/entity/elasticsearch/ingest_pipeline/user.yml @@ -27,6 +27,229 @@ processors: tag: pipeline_entity ignore_missing_pipeline: true + - script: + lang: painless + ignore_failure: false + tag: Set User Account Control + description: script_set_user_account_control + # USER_ACCOUNT Codes + # https://learn.microsoft.com/en-us/windows/win32/adschema/a-useraccountcontrol + # https://learn.microsoft.com/en-us/windows/win32/api/iads/ne-iads-ads_user_flag_enum + params: + "0x00000001": SCRIPT + "0x00000002": ACCOUNTDISABLE + "0x00000008": HOMEDIR_REQUIRED + "0x00000010": LOCKOUT + "0x00000020": PASSWD_NOTREQD + "0x00000040": PASSWD_CANT_CHANGE + "0x00000080": ENCRYPTED_TEXT_PWD_ALLOWED + "0x00000100": TEMP_DUPLICATE_ACCOUNT + "0x00000200": NORMAL_ACCOUNT + "0x00000800": INTERDOMAIN_TRUST_ACCOUNT + "0x00001000": WORKSTATION_TRUST_ACCOUNT + "0x00002000": SERVER_TRUST_ACCOUNT + "0x00010000": DONT_EXPIRE_PASSWORD + "0x00020000": MNS_LOGON_ACCOUNT + "0x00040000": SMARTCARD_REQUIRED + "0x00080000": TRUSTED_FOR_DELEGATION + "0x00100000": NOT_DELEGATED + "0x00200000": USE_DES_KEY_ONLY + "0x00400000": DONT_REQUIRE_PREAUTH + "0x00800000": PASSWORD_EXPIRED + "0x01000000": TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION + "0x04000000": PARTIAL_SECRETS_ACCOUNT + source: |- + Long newUacValue = Long.decode(ctx.activedirectory.user.user_account_control); + ArrayList uacResult = new ArrayList(); + for (entry in params.entrySet()) { + Long flag = Long.decode(entry.getKey()); + if ((newUacValue.longValue() & flag.longValue()) != 0) { + uacResult.add(entry.getValue()); + } + } + if (uacResult.length != 0) { + ctx.activedirectory.user.uac_list = uacResult; + } + if: ctx.activedirectory?.user?.user_account_control != null && ctx.activedirectory.user.user_account_control != 0 + + - date: + field: activedirectory.user.when_created + target_field: asset.create_date + tag: date_user_created + formats: + - ISO8601 + if: ctx.activedirectory?.user?.when_created != null && ctx.activedirectory.user.when_created != '' + on_failure: + - remove: + field: activedirectory.user.when_created + - append: + field: error.message + value: 'Processor {{{_ingest.on_failure_processor_type}}} with tag {{{_ingest.on_failure_processor_tag}}} in pipeline {{{_ingest.pipeline}}} failed with message: {{{_ingest.on_failure_message}}}' + - date: + field: activedirectory.user.when_changed + target_field: asset.last_updated + tag: date_user_changed + formats: + - ISO8601 + if: ctx.activedirectory?.user?.when_changed != null && ctx.activedirectory.user.when_changed != '' + on_failure: + - remove: + field: activedirectory.user.when_changed + - append: + field: error.message + value: 'Processor {{{_ingest.on_failure_processor_type}}} with tag {{{_ingest.on_failure_processor_tag}}} in pipeline {{{_ingest.pipeline}}} failed with message: {{{_ingest.on_failure_message}}}' + - date: + field: activedirectory.user.pwd_last_set + target_field: user.account.password_change_date + tag: date_user_password_changed + formats: + - ISO8601 + if: ctx.activedirectory?.user?.pwd_last_set != null && ctx.activedirectory.user.pwd_last_set != '' + on_failure: + - remove: + field: activedirectory.user.pwd_last_set + - append: + field: error.message + value: 'Processor {{{_ingest.on_failure_processor_type}}} with tag {{{_ingest.on_failure_processor_tag}}} in pipeline {{{_ingest.pipeline}}} failed with message: {{{_ingest.on_failure_message}}}' + + - set: + field: asset.name + copy_from: activedirectory.user.sam_account_name + ignore_empty_value: true + - set: + field: user.name + copy_from: activedirectory.user.sam_account_name + ignore_empty_value: true + - gsub: + tag: gsub_user_dn + field: activedirectory.user.distinguished_name + pattern: '^.*?DC=' + replacement: '' + target_field: user.domain + if: ctx.activedirectory?.user?.distinguished_name != null + - gsub: + tag: gsub_user_domain + field: user.domain + pattern: ',DC=' + replacement: '.' + if: ctx.user?.domain != null + - set: + field: asset.id + copy_from: activedirectory.user.object_sid + - set: + field: user.id + copy_from: activedirectory.user.object_sid + + - set: + field: activedirectory.user.logon_script_enabled + value: true + if: ctx.activedirectory?.user?.uac_list?.contains('SCRIPT') == true + - set: + field: activedirectory.user.enabled + value: true + if: ctx.activedirectory?.user?.uac_list?.contains('ACCOUNTDISABLE') == false + - set: + field: activedirectory.user.enabled + value: false + if: ctx.activedirectory?.user?.uac_list?.contains('ACCOUNTDISABLE') == true + + - set: + field: activedirectory.user.locked + value: true + if: ctx.activedirectory?.user?.uac_list?.contains('LOCKOUT') == true + + - set: + field: activedirectory.user.password_not_required + value: true + if: ctx.activedirectory?.user?.uac_list?.contains('PASSWD_NOTREQD') == true + + - set: + field: activedirectory.user.reversible_encryption_password + value: true + if: ctx.activedirectory?.user?.uac_list?.contains('ENCRYPTED_TEXT_PWD_ALLOWED') == true + + - set: + field: activedirectory.user.unconstrained_delegation + value: true + if: ctx.activedirectory?.user?.uac_list?.contains('TRUSTED_FOR_DELEGATION') == true + + - set: + field: activedirectory.user.sensitive_object + value: true + if: ctx.activedirectory?.user?.uac_list?.contains('NOT_DELEGATED') == true + + - set: + field: activedirectory.user.use_des_key_only + value: true + if: ctx.activedirectory?.user?.uac_list?.contains('USE_DES_KEY_ONLY') == true + + - set: + field: activedirectory.user.dont_require_preauth + value: true + if: ctx.activedirectory?.user?.uac_list?.contains('DONT_REQUIRE_PREAUTH') == true + + - set: + field: activedirectory.user.constrained_delegation + value: true + if: ctx.activedirectory?.user?.uac_list?.contains('TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION') == true + + - script: + lang: painless + ignore_failure: true + tag: handle_user_group_details + description: Collect user's group details and set privileged_group_member flag based on group membership. + if: ctx.activedirectory?.groups instanceof List + # Well-known SIDs - Name to SID mapping + # https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/understand-security-identifiers#well-known-sids + params: + '512': true + '516': true + '518': true + '519': true + '520': true + '525': true + '526': true + '527': true + '544': true + '548': true + '549': true + '551': true + source: |- + ctx.user = ctx.user ?: [:]; + ctx.user.group = ctx.user.group ?: [:]; + + for (def group : ctx.activedirectory.groups) { + if (group.name != null) { + ctx.user.group.name = ctx.user.group.name ?: new HashSet(); + ctx.user.group.name.add(group.name); + } + + if (group?.object_sid == null) { + continue; + } + + group.id = group.object_sid; + ctx.user.group.id = ctx.user.group.id ?: new HashSet(); + ctx.user.group.id.add(group.id); + + int idx = group.object_sid.lastIndexOf('-'); + if (idx < 0) { + continue; + } + def priv = params.get(group.object_sid.substring(idx+1)); + if (priv != null && ctx.activedirectory.user.privileged_group_member == null) { + ctx.activedirectory.user.privileged_group_member = priv; + } + } + if (ctx.activedirectory.user.privileged_group_member == null) { + ctx.activedirectory.user.privileged_group_member = false; + } + + - set: + field: activedirectory.user.account_never_expires + value: true + if: ctx.activedirectory?.user?.account_expires == "0" || ctx.activedirectory?.user?.account_expires == "9223372036854775807" + - append: field: related.user value: "{{{activedirectory.user.sam_account_name}}}" diff --git a/packages/entityanalytics_ad/data_stream/entity/fields/fields.yml b/packages/entityanalytics_ad/data_stream/entity/fields/fields.yml index 8ec2038997e..a345477ed99 100644 --- a/packages/entityanalytics_ad/data_stream/entity/fields/fields.yml +++ b/packages/entityanalytics_ad/data_stream/entity/fields/fields.yml @@ -141,6 +141,8 @@ type: keyword - name: distinguished_name type: keyword + - name: dns_host_name + type: keyword - name: dont_require_preauth type: boolean description: True if the account does not require Kerberos pre-authentication. @@ -183,6 +185,10 @@ type: keyword - name: object_sid type: keyword + - name: operating_system + type: keyword + - name: operating_system_version + type: keyword - name: password_not_required type: boolean description: True if the account does not require a password. diff --git a/packages/entityanalytics_ad/manifest.yml b/packages/entityanalytics_ad/manifest.yml index 85b8c2a4956..73e4c883ac1 100644 --- a/packages/entityanalytics_ad/manifest.yml +++ b/packages/entityanalytics_ad/manifest.yml @@ -1,7 +1,7 @@ format_version: "3.0.2" name: entityanalytics_ad title: Active Directory Entity Analytics -version: "0.16.0" +version: "0.17.0" description: "Collect User Identities from Active Directory Entity with Elastic Agent." type: integration categories: