From 0239143f79be8fa96ddf845ed04acc02e52f5533 Mon Sep 17 00:00:00 2001 From: Brandon Qiao Date: Fri, 23 Oct 2026 10:58:18 -0400 Subject: [PATCH 1/6] fix --- .../CHANGELOG/ASimUserManagementAWSCloudTrail.md | 4 ++++ .../CHANGELOG/vimUserManagementAWSCloudTrail.md | 4 ++++ .../Parsers/ASimUserManagementAWSCloudTrail.yaml | 5 ++--- .../Parsers/vimUserManagementAWSCloudTrail.yaml | 6 ++---- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Parsers/ASimUserManagement/CHANGELOG/ASimUserManagementAWSCloudTrail.md b/Parsers/ASimUserManagement/CHANGELOG/ASimUserManagementAWSCloudTrail.md index 762b4339ee4..3195dcce8f4 100644 --- a/Parsers/ASimUserManagement/CHANGELOG/ASimUserManagementAWSCloudTrail.md +++ b/Parsers/ASimUserManagement/CHANGELOG/ASimUserManagementAWSCloudTrail.md @@ -1,5 +1,9 @@ # Changelog for ASimUserManagementAWSCloudTrail.yaml +## Version 0.1.1 + +- (2026-10-23) Remove the duplicate IAM lookup entry for UntagUser so each matching event produces one UserModified output row. + ## Version 0.1.0 - (2026-01-26) [ASIM] UserManagement - AWSCloudTrail (New Parser) - [PR #13503](https://github.com/Azure/Azure-Sentinel/pull/13503) - Create parser for AWSCloudTrail diff --git a/Parsers/ASimUserManagement/CHANGELOG/vimUserManagementAWSCloudTrail.md b/Parsers/ASimUserManagement/CHANGELOG/vimUserManagementAWSCloudTrail.md index e9e2c1eb334..c6e9e0ea153 100644 --- a/Parsers/ASimUserManagement/CHANGELOG/vimUserManagementAWSCloudTrail.md +++ b/Parsers/ASimUserManagement/CHANGELOG/vimUserManagementAWSCloudTrail.md @@ -1,5 +1,9 @@ # Changelog for vimUserManagementAWSCloudTrail.yaml +## Version 0.1.1 + +- (2026-10-23) Remove the duplicate IAM lookup entry for UntagUser so each matching event produces one UserModified output row. + ## Version 0.1.0 - (2026-01-26) [ASIM] UserManagement - AWSCloudTrail (New Parser) - [PR #13503](https://github.com/Azure/Azure-Sentinel/pull/13503) - Create parser for AWSCloudTrail diff --git a/Parsers/ASimUserManagement/Parsers/ASimUserManagementAWSCloudTrail.yaml b/Parsers/ASimUserManagement/Parsers/ASimUserManagementAWSCloudTrail.yaml index ac75a937c04..bac84bf6850 100644 --- a/Parsers/ASimUserManagement/Parsers/ASimUserManagementAWSCloudTrail.yaml +++ b/Parsers/ASimUserManagement/Parsers/ASimUserManagementAWSCloudTrail.yaml @@ -1,7 +1,7 @@ Parser: Title: User Management ASIM parser for AWS Cloud Trail - Version: '0.1.0' - LastUpdated: Jan 26, 2026 + Version: '0.1.1' + LastUpdated: Oct 23, 2026 Product: Name: AWS Cloud Trail Normalization: @@ -67,7 +67,6 @@ ParserQuery: | "TagRole", "UserModified", "TagUser", "UserModified", "UntagUser", "UserModified", - "UntagUser", "UserModified", "UpdateGroup", "GroupModified", "UpdateLoginProfile", "PasswordChanged", "UpdateRole", "UserModified", diff --git a/Parsers/ASimUserManagement/Parsers/vimUserManagementAWSCloudTrail.yaml b/Parsers/ASimUserManagement/Parsers/vimUserManagementAWSCloudTrail.yaml index 0b8e90fb2ce..9d6dda45c11 100644 --- a/Parsers/ASimUserManagement/Parsers/vimUserManagementAWSCloudTrail.yaml +++ b/Parsers/ASimUserManagement/Parsers/vimUserManagementAWSCloudTrail.yaml @@ -1,7 +1,7 @@ Parser: Title: User Management ASIM filtering parser for AWS Cloud Trail - Version: '0.1.0' - LastUpdated: Jan 26, 2026 + Version: '0.1.1' + LastUpdated: Oct 23, 2026 Product: Name: AWS Cloud Trail Normalization: @@ -85,7 +85,6 @@ ParserQuery: | "TagRole", "UserModified", "TagUser", "UserModified", "UntagUser", "UserModified", - "UntagUser", "UserModified", "UpdateGroup", "GroupModified", "UpdateLoginProfile", "PasswordChanged", "UpdateRole", "UserModified", @@ -321,4 +320,3 @@ ParserQuery: | disabled = disabled, pack = pack ) - From 88df5dd7a64a10e0a01cc5880fa85ce7f20b524f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <> Date: Fri, 23 Oct 2026 15:04:35 +0000 Subject: [PATCH 2/6] [ASIM Parsers] Generate deployable ARM templates from KQL function YAML files. --- .../ASimUserManagementAWSCloudTrail.json | 2 +- .../vimUserManagementAWSCloudTrail.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Parsers/ASimUserManagement/ARM/ASimUserManagementAWSCloudTrail/ASimUserManagementAWSCloudTrail.json b/Parsers/ASimUserManagement/ARM/ASimUserManagementAWSCloudTrail/ASimUserManagementAWSCloudTrail.json index 60ca3aa4e06..1a11b84676f 100644 --- a/Parsers/ASimUserManagement/ARM/ASimUserManagementAWSCloudTrail/ASimUserManagementAWSCloudTrail.json +++ b/Parsers/ASimUserManagement/ARM/ASimUserManagementAWSCloudTrail/ASimUserManagementAWSCloudTrail.json @@ -27,7 +27,7 @@ "displayName": "User Management ASIM parser for AWS Cloud Trail", "category": "ASIM", "FunctionAlias": "ASimUserManagementAWSCloudTrail", - "query": "let ParseIAMEvents = (T: (EventSource: string, EventName: string, RequestParameters: dynamic, ResponseElements: dynamic)) {\n let IAMEventNameLookup = datatable(EventName: string, EventType: string)\n [\n \"AddUserToGroup\", \"UserAddedToGroup\",\n \"AttachGroupPolicy\", \"GroupModified\",\n \"AttachUserPolicy\", \"UserModified\",\n \"ChangePassword\", \"PasswordChanged\",\n \"CreateGroup\", \"GroupCreated\",\n \"CreateLoginProfile\", \"UserModified\",\n \"CreateUser\", \"UserCreated\",\n \"DeleteGroup\", \"GroupDeleted\",\n \"DeleteGroupPolicy\", \"GroupModified\",\n \"DeleteLoginProfile\", \"UserModified\",\n \"DeleteRole\", \"UserDeleted\",\n \"DeleteUser\", \"UserDeleted\",\n \"DeleteUserPolicy\", \"UserModified\",\n \"DetachGroupPolicy\", \"GroupModified\",\n \"DetachRolePolicy\", \"UserModified\",\n \"DetachUserPolicy\", \"UserModified\",\n \"EnableMFADevice\", \"UserModified\",\n \"GetGroup\", \"GroupRead\",\n \"GetGroupPolicy\", \"GroupRead\",\n \"GetLoginProfile\", \"UserRead\",\n \"GetMFADevice\", \"UserRead\",\n \"GetRole\", \"UserRead\",\n \"GetUser\", \"UserRead\",\n \"ListAttachedGroupPolicies\", \"GroupRead\",\n \"ListAttachedRolePolicies\", \"UserRead\",\n \"ListAttachedUserPolicies\", \"UserRead\",\n \"ListGroups\", \"GroupEnumerated\",\n \"ListGroupsForUser\", \"UserRead\",\n \"ListMFADevices\", \"UserRead\",\n \"ListRoles\", \"UserRead\",\n \"ListUsers\", \"UserRead\",\n \"PutGroupPolicy\", \"GroupModified\",\n \"PutRolePolicy\", \"UserModified\",\n \"PutUserPolicy\", \"UserModified\",\n \"RemoveUserFromGroup\", \"UserRemovedFromGroup\",\n \"TagRole\", \"UserModified\",\n \"TagUser\", \"UserModified\",\n \"UntagUser\", \"UserModified\",\n \"UntagUser\", \"UserModified\",\n \"UpdateGroup\", \"GroupModified\",\n \"UpdateLoginProfile\", \"PasswordChanged\",\n \"UpdateRole\", \"UserModified\",\n \"UpdateRoleDescription\", \"UserModified\",\n \"UpdateSigningCertificate\", \"PasswordChanged\",\n \"UpdateSSHPublicKey\", \"PasswordChanged\",\n \"UpdateUser\", \"UserModified\",\n \"UploadSigningCertificate\", \"UserModified\",\n \"UploadSSHPublicKey\", \"UserModified\"\n ];\n T\n | where EventSource == \"iam.amazonaws.com\"\n | lookup IAMEventNameLookup on EventName\n | where isnotempty(EventType)\n | extend\n TargetUserId = coalesce(tostring(ResponseElements.user.userId), tostring(ResponseElements.role.roleId)),\n TargetUsername = coalesce(tostring(RequestParameters.userName), tostring(RequestParameters.roleName)),\n GroupId = tostring(ResponseElements.group.groupName),\n GroupName = tostring(RequestParameters.groupName)\n | extend \n TargetUserIdType = case(\n TargetUserId startswith \"AROA\", \"AWSIAMRoleId\",\n TargetUserId startswith \"AIDA\", \"AWSIAMUserId\",\n \"\"\n ),\n GroupOriginalType = iff(isempty(GroupName), \"\", \"IAM Group\")\n | extend AdditionalData = bag_pack(\n \"TargetUserARN\", coalesce(tostring(ResponseElements.user.arn), tostring(ResponseElements.role.arn)),\n \"GroupARN\", tostring(ResponseElements.group.arn)\n )\n };\n let ParseCognitoEvents = (T: (EventSource: string, EventName: string, RequestParameters: dynamic)) {\n let CognitoIDPEventNameLookup = datatable(EventName: string, EventType: string)\n [\n \"AddCustomAttributes\", \"GroupModified\",\n \"AdminAddUserToGroup\", \"UserAddedToGroup\",\n \"AdminConfirmSignUp\", \"UserEnabled\",\n \"AdminCreateUser\", \"UserCreated\",\n \"AdminDeleteUser\", \"UserDeleted\",\n \"AdminDeleteUserAttributes\", \"UserModified\",\n \"AdminDisableProviderForUser\", \"UserDisabled\",\n \"AdminDisableUser\", \"UserDisabled\",\n \"AdminEnableUser\", \"UserEnabled\",\n \"AdminForgetDevice\", \"UserModified\",\n \"AdminGetDevice\", \"UserRead\",\n \"AdminGetUser\", \"UserRead\",\n \"AdminLinkUserAuthEvents\", \"UserModified\",\n \"AdminListDevices\", \"UserRead\",\n \"AdminListGroupsForUser\", \"UserRead\",\n \"AdminListUserAuthEvents\", \"UserRead\",\n \"AdminRemoveUserFromGroup\", \"UserRemovedFromGroup\",\n \"AdminResetUserPassword\", \"PasswordReset\",\n \"AdminSetUserMFAPreference\", \"UserModified\",\n \"AdminSetUserPassword\", \"PasswordChanged\",\n \"AdminSetUserSettings\", \"UserModified\",\n \"AdminUpdateDeviceStatus\", \"UserModified\",\n \"AdminUpdateUserAttributes\", \"UserModified\",\n \"ChangePassword\", \"PasswordChanged\",\n \"CompleteWebAuthnRegistration\", \"UserModified\",\n \"ConfirmSignUp\", \"UserCreated\",\n \"CreateGroup\", \"GroupCreated\",\n \"CreateUserPool\", \"GroupCreated\",\n \"DeleteGroup\", \"GroupDeleted\",\n \"DeleteUser\", \"UserDeleted\",\n \"DeleteUserAttributes\", \"UserModified\",\n \"DeleteUserPool\", \"GroupDeleted\",\n \"DeleteWebAuthnCredential\", \"UserModified\",\n \"DescribeUserPool\", \"GroupRead\",\n \"GetGroup\", \"GroupRead\",\n \"GetUser\", \"UserRead\",\n \"GetUserPoolMfaConfig\", \"GroupRead\",\n \"ListGroups\", \"GroupRead\",\n \"ListIdentityProviders\", \"GroupRead\",\n \"ListResourceServers\", \"GroupRead\",\n \"ListTerms\", \"GroupRead\",\n \"ListUserPools\", \"GroupEnumerated\",\n \"ListUsers\", \"GroupEnumerated\",\n \"ListUsersInGroup\", \"GroupEnumerated\",\n \"SetUserPoolMfaConfig\", \"GroupModified\",\n \"SignUp\", \"UserCreated\",\n \"UpdateGroup\", \"GroupModified\",\n \"UpdateUserAttributes\", \"UserModified\",\n \"UpdateUserPool\", \"GroupModified\"\n ];\n T\n | where EventSource == \"cognito-idp.amazonaws.com\"\n | lookup CognitoIDPEventNameLookup on EventName\n | where isnotempty(EventType)\n | extend\n TargetUsername = tostring(RequestParameters.username),\n GroupName = coalesce(tostring(RequestParameters.poolName), tostring(RequestParameters.groupName)),\n GroupId = tostring(RequestParameters.userPoolId)\n | extend GroupOriginalType = case(\n isnotempty(tostring(RequestParameters.groupName)), \"UserPool Group\",\n isnotempty(GroupId), \"UserPool\",\n \"\")\n | extend AdditionalData = bag_pack(\n \"UserPoolId\", tostring(RequestParameters.UserPoolId)\n )\n };\n let parser = (disabled: bool, pack: bool) {\n let SupportedEventSources = dynamic([\n \"cognito-idp.amazonaws.com\",\n \"iam.amazonaws.com\"\n ]);\n let EventSourceNameLookup = datatable(EventSource: string, TargetUserScope: string)\n [\n \"cognito-idp.amazonaws.com\", \"Cognito User Pools\",\n \"iam.amazonaws.com\", \"IAM\"\n ];\n let SupportedEvents = AWSCloudTrail\n | where EventSource in (SupportedEventSources)\n | extend RequestParameters = todynamic(RequestParameters), ResponseElements = todynamic(ResponseElements);\n union isfuzzy=false\n ParseIAMEvents(SupportedEvents),\n ParseCognitoEvents(SupportedEvents)\n | extend\n Type = \"AWSCloudTrail\",\n EventCount = int(1),\n EventStartTime = TimeGenerated,\n EventEndTime = TimeGenerated,\n EventSeverity = \"Informational\",\n EventSchema = \"UserManagement\",\n EventSchemaVersion = \"0.1.2\",\n EventVendor = \"AWS\",\n EventProduct = \"CloudTrail\",\n Dvc = \"CloudTrail\",\n EventResult = iff(isempty(ErrorCode) and isempty(ErrorMessage), \"Success\", \"Failure\"),\n EventMessage = ErrorMessage\n | lookup EventSourceNameLookup on EventSource\n | project-rename\n EventOriginalSubType = EventTypeName,\n EventOriginalType = EventName,\n EventUid = AwsEventId,\n EventOriginalResultDetails = ErrorMessage,\n EventProductVersion = EventVersion\n | project-rename\n ActorUserId = UserIdentityAccountId,\n ActorUsername = UserIdentityUserName,\n ActorOriginalUserType = UserIdentityType,\n HttpUserAgent = UserAgent\n | extend\n ActorUserIdType = iff(isempty(ActorUserId), \"\", \"AWSId\"),\n ActorUsernameType = iff(isempty(ActorUsername), \"\", \"Simple\"),\n SrcIpAddr = iff(ipv4_is_in_range(SourceIpAddress, \"0.0.0.0/0\"), SourceIpAddress, \"\")\n | extend\n TargetUsernameType = iff(isempty(TargetUsername), \"\", \"Simple\"),\n GroupIdType = iff(isempty(GroupId), \"\", \"Simple\"),\n GroupNameType = iff(isempty(GroupName), \"\", \"Simple\")\n | extend AdditionalFields = iff(pack, bag_pack(\n \"ActorAccessKeyId\", UserIdentityAccessKeyId,\n \"AWSRegion\", AWSRegion,\n \"APIVersion\", APIVersion,\n \"ManagementEvent\", ManagementEvent,\n \"ReadOnly\", ReadOnly,\n \"RequestParameters\", RequestParameters,\n \"ResponseElements\", ResponseElements\n ), dynamic([]))\n | extend AdditionalFields = iff(pack, bag_merge(AdditionalFields, AdditionalData), dynamic([]))\n // Alias\n | extend\n User = ActorUsername,\n IpAddr = SrcIpAddr\n | project\n TimeGenerated,\n Type,\n EventCount,\n EventStartTime,\n EventEndTime,\n EventSeverity,\n EventSchema,\n EventSchemaVersion,\n EventVendor,\n EventProduct,\n TargetUserScope,\n Dvc,\n EventResult,\n EventMessage,\n EventType,\n EventOriginalSubType,\n EventOriginalType,\n EventUid,\n EventOriginalResultDetails,\n EventProductVersion,\n ActorUserId,\n ActorUsername,\n ActorOriginalUserType,\n HttpUserAgent,\n ActorUserIdType,\n ActorUsernameType,\n SrcIpAddr,\n TargetUserId,\n TargetUsername,\n TargetUserIdType,\n GroupId,\n GroupName,\n TargetUsernameType,\n GroupIdType,\n GroupNameType,\n GroupOriginalType,\n User,\n IpAddr,\n AdditionalFields\n};\nparser(disabled = disabled, pack = pack);", + "query": "let ParseIAMEvents = (T: (EventSource: string, EventName: string, RequestParameters: dynamic, ResponseElements: dynamic)) {\n let IAMEventNameLookup = datatable(EventName: string, EventType: string)\n [\n \"AddUserToGroup\", \"UserAddedToGroup\",\n \"AttachGroupPolicy\", \"GroupModified\",\n \"AttachUserPolicy\", \"UserModified\",\n \"ChangePassword\", \"PasswordChanged\",\n \"CreateGroup\", \"GroupCreated\",\n \"CreateLoginProfile\", \"UserModified\",\n \"CreateUser\", \"UserCreated\",\n \"DeleteGroup\", \"GroupDeleted\",\n \"DeleteGroupPolicy\", \"GroupModified\",\n \"DeleteLoginProfile\", \"UserModified\",\n \"DeleteRole\", \"UserDeleted\",\n \"DeleteUser\", \"UserDeleted\",\n \"DeleteUserPolicy\", \"UserModified\",\n \"DetachGroupPolicy\", \"GroupModified\",\n \"DetachRolePolicy\", \"UserModified\",\n \"DetachUserPolicy\", \"UserModified\",\n \"EnableMFADevice\", \"UserModified\",\n \"GetGroup\", \"GroupRead\",\n \"GetGroupPolicy\", \"GroupRead\",\n \"GetLoginProfile\", \"UserRead\",\n \"GetMFADevice\", \"UserRead\",\n \"GetRole\", \"UserRead\",\n \"GetUser\", \"UserRead\",\n \"ListAttachedGroupPolicies\", \"GroupRead\",\n \"ListAttachedRolePolicies\", \"UserRead\",\n \"ListAttachedUserPolicies\", \"UserRead\",\n \"ListGroups\", \"GroupEnumerated\",\n \"ListGroupsForUser\", \"UserRead\",\n \"ListMFADevices\", \"UserRead\",\n \"ListRoles\", \"UserRead\",\n \"ListUsers\", \"UserRead\",\n \"PutGroupPolicy\", \"GroupModified\",\n \"PutRolePolicy\", \"UserModified\",\n \"PutUserPolicy\", \"UserModified\",\n \"RemoveUserFromGroup\", \"UserRemovedFromGroup\",\n \"TagRole\", \"UserModified\",\n \"TagUser\", \"UserModified\",\n \"UntagUser\", \"UserModified\",\n \"UpdateGroup\", \"GroupModified\",\n \"UpdateLoginProfile\", \"PasswordChanged\",\n \"UpdateRole\", \"UserModified\",\n \"UpdateRoleDescription\", \"UserModified\",\n \"UpdateSigningCertificate\", \"PasswordChanged\",\n \"UpdateSSHPublicKey\", \"PasswordChanged\",\n \"UpdateUser\", \"UserModified\",\n \"UploadSigningCertificate\", \"UserModified\",\n \"UploadSSHPublicKey\", \"UserModified\"\n ];\n T\n | where EventSource == \"iam.amazonaws.com\"\n | lookup IAMEventNameLookup on EventName\n | where isnotempty(EventType)\n | extend\n TargetUserId = coalesce(tostring(ResponseElements.user.userId), tostring(ResponseElements.role.roleId)),\n TargetUsername = coalesce(tostring(RequestParameters.userName), tostring(RequestParameters.roleName)),\n GroupId = tostring(ResponseElements.group.groupName),\n GroupName = tostring(RequestParameters.groupName)\n | extend \n TargetUserIdType = case(\n TargetUserId startswith \"AROA\", \"AWSIAMRoleId\",\n TargetUserId startswith \"AIDA\", \"AWSIAMUserId\",\n \"\"\n ),\n GroupOriginalType = iff(isempty(GroupName), \"\", \"IAM Group\")\n | extend AdditionalData = bag_pack(\n \"TargetUserARN\", coalesce(tostring(ResponseElements.user.arn), tostring(ResponseElements.role.arn)),\n \"GroupARN\", tostring(ResponseElements.group.arn)\n )\n };\n let ParseCognitoEvents = (T: (EventSource: string, EventName: string, RequestParameters: dynamic)) {\n let CognitoIDPEventNameLookup = datatable(EventName: string, EventType: string)\n [\n \"AddCustomAttributes\", \"GroupModified\",\n \"AdminAddUserToGroup\", \"UserAddedToGroup\",\n \"AdminConfirmSignUp\", \"UserEnabled\",\n \"AdminCreateUser\", \"UserCreated\",\n \"AdminDeleteUser\", \"UserDeleted\",\n \"AdminDeleteUserAttributes\", \"UserModified\",\n \"AdminDisableProviderForUser\", \"UserDisabled\",\n \"AdminDisableUser\", \"UserDisabled\",\n \"AdminEnableUser\", \"UserEnabled\",\n \"AdminForgetDevice\", \"UserModified\",\n \"AdminGetDevice\", \"UserRead\",\n \"AdminGetUser\", \"UserRead\",\n \"AdminLinkUserAuthEvents\", \"UserModified\",\n \"AdminListDevices\", \"UserRead\",\n \"AdminListGroupsForUser\", \"UserRead\",\n \"AdminListUserAuthEvents\", \"UserRead\",\n \"AdminRemoveUserFromGroup\", \"UserRemovedFromGroup\",\n \"AdminResetUserPassword\", \"PasswordReset\",\n \"AdminSetUserMFAPreference\", \"UserModified\",\n \"AdminSetUserPassword\", \"PasswordChanged\",\n \"AdminSetUserSettings\", \"UserModified\",\n \"AdminUpdateDeviceStatus\", \"UserModified\",\n \"AdminUpdateUserAttributes\", \"UserModified\",\n \"ChangePassword\", \"PasswordChanged\",\n \"CompleteWebAuthnRegistration\", \"UserModified\",\n \"ConfirmSignUp\", \"UserCreated\",\n \"CreateGroup\", \"GroupCreated\",\n \"CreateUserPool\", \"GroupCreated\",\n \"DeleteGroup\", \"GroupDeleted\",\n \"DeleteUser\", \"UserDeleted\",\n \"DeleteUserAttributes\", \"UserModified\",\n \"DeleteUserPool\", \"GroupDeleted\",\n \"DeleteWebAuthnCredential\", \"UserModified\",\n \"DescribeUserPool\", \"GroupRead\",\n \"GetGroup\", \"GroupRead\",\n \"GetUser\", \"UserRead\",\n \"GetUserPoolMfaConfig\", \"GroupRead\",\n \"ListGroups\", \"GroupRead\",\n \"ListIdentityProviders\", \"GroupRead\",\n \"ListResourceServers\", \"GroupRead\",\n \"ListTerms\", \"GroupRead\",\n \"ListUserPools\", \"GroupEnumerated\",\n \"ListUsers\", \"GroupEnumerated\",\n \"ListUsersInGroup\", \"GroupEnumerated\",\n \"SetUserPoolMfaConfig\", \"GroupModified\",\n \"SignUp\", \"UserCreated\",\n \"UpdateGroup\", \"GroupModified\",\n \"UpdateUserAttributes\", \"UserModified\",\n \"UpdateUserPool\", \"GroupModified\"\n ];\n T\n | where EventSource == \"cognito-idp.amazonaws.com\"\n | lookup CognitoIDPEventNameLookup on EventName\n | where isnotempty(EventType)\n | extend\n TargetUsername = tostring(RequestParameters.username),\n GroupName = coalesce(tostring(RequestParameters.poolName), tostring(RequestParameters.groupName)),\n GroupId = tostring(RequestParameters.userPoolId)\n | extend GroupOriginalType = case(\n isnotempty(tostring(RequestParameters.groupName)), \"UserPool Group\",\n isnotempty(GroupId), \"UserPool\",\n \"\")\n | extend AdditionalData = bag_pack(\n \"UserPoolId\", tostring(RequestParameters.UserPoolId)\n )\n };\n let parser = (disabled: bool, pack: bool) {\n let SupportedEventSources = dynamic([\n \"cognito-idp.amazonaws.com\",\n \"iam.amazonaws.com\"\n ]);\n let EventSourceNameLookup = datatable(EventSource: string, TargetUserScope: string)\n [\n \"cognito-idp.amazonaws.com\", \"Cognito User Pools\",\n \"iam.amazonaws.com\", \"IAM\"\n ];\n let SupportedEvents = AWSCloudTrail\n | where EventSource in (SupportedEventSources)\n | extend RequestParameters = todynamic(RequestParameters), ResponseElements = todynamic(ResponseElements);\n union isfuzzy=false\n ParseIAMEvents(SupportedEvents),\n ParseCognitoEvents(SupportedEvents)\n | extend\n Type = \"AWSCloudTrail\",\n EventCount = int(1),\n EventStartTime = TimeGenerated,\n EventEndTime = TimeGenerated,\n EventSeverity = \"Informational\",\n EventSchema = \"UserManagement\",\n EventSchemaVersion = \"0.1.2\",\n EventVendor = \"AWS\",\n EventProduct = \"CloudTrail\",\n Dvc = \"CloudTrail\",\n EventResult = iff(isempty(ErrorCode) and isempty(ErrorMessage), \"Success\", \"Failure\"),\n EventMessage = ErrorMessage\n | lookup EventSourceNameLookup on EventSource\n | project-rename\n EventOriginalSubType = EventTypeName,\n EventOriginalType = EventName,\n EventUid = AwsEventId,\n EventOriginalResultDetails = ErrorMessage,\n EventProductVersion = EventVersion\n | project-rename\n ActorUserId = UserIdentityAccountId,\n ActorUsername = UserIdentityUserName,\n ActorOriginalUserType = UserIdentityType,\n HttpUserAgent = UserAgent\n | extend\n ActorUserIdType = iff(isempty(ActorUserId), \"\", \"AWSId\"),\n ActorUsernameType = iff(isempty(ActorUsername), \"\", \"Simple\"),\n SrcIpAddr = iff(ipv4_is_in_range(SourceIpAddress, \"0.0.0.0/0\"), SourceIpAddress, \"\")\n | extend\n TargetUsernameType = iff(isempty(TargetUsername), \"\", \"Simple\"),\n GroupIdType = iff(isempty(GroupId), \"\", \"Simple\"),\n GroupNameType = iff(isempty(GroupName), \"\", \"Simple\")\n | extend AdditionalFields = iff(pack, bag_pack(\n \"ActorAccessKeyId\", UserIdentityAccessKeyId,\n \"AWSRegion\", AWSRegion,\n \"APIVersion\", APIVersion,\n \"ManagementEvent\", ManagementEvent,\n \"ReadOnly\", ReadOnly,\n \"RequestParameters\", RequestParameters,\n \"ResponseElements\", ResponseElements\n ), dynamic([]))\n | extend AdditionalFields = iff(pack, bag_merge(AdditionalFields, AdditionalData), dynamic([]))\n // Alias\n | extend\n User = ActorUsername,\n IpAddr = SrcIpAddr\n | project\n TimeGenerated,\n Type,\n EventCount,\n EventStartTime,\n EventEndTime,\n EventSeverity,\n EventSchema,\n EventSchemaVersion,\n EventVendor,\n EventProduct,\n TargetUserScope,\n Dvc,\n EventResult,\n EventMessage,\n EventType,\n EventOriginalSubType,\n EventOriginalType,\n EventUid,\n EventOriginalResultDetails,\n EventProductVersion,\n ActorUserId,\n ActorUsername,\n ActorOriginalUserType,\n HttpUserAgent,\n ActorUserIdType,\n ActorUsernameType,\n SrcIpAddr,\n TargetUserId,\n TargetUsername,\n TargetUserIdType,\n GroupId,\n GroupName,\n TargetUsernameType,\n GroupIdType,\n GroupNameType,\n GroupOriginalType,\n User,\n IpAddr,\n AdditionalFields\n};\nparser(disabled = disabled, pack = pack);", "version": 1, "functionParameters": "disabled:bool=False,pack:bool=False" } diff --git a/Parsers/ASimUserManagement/ARM/vimUserManagementAWSCloudTrail/vimUserManagementAWSCloudTrail.json b/Parsers/ASimUserManagement/ARM/vimUserManagementAWSCloudTrail/vimUserManagementAWSCloudTrail.json index 51a84d26567..d1df66eb849 100644 --- a/Parsers/ASimUserManagement/ARM/vimUserManagementAWSCloudTrail/vimUserManagementAWSCloudTrail.json +++ b/Parsers/ASimUserManagement/ARM/vimUserManagementAWSCloudTrail/vimUserManagementAWSCloudTrail.json @@ -27,7 +27,7 @@ "displayName": "User Management ASIM filtering parser for AWS Cloud Trail", "category": "ASIM", "FunctionAlias": "vimUserManagementAWSCloudTrail", - "query": "let ParseIAMEvents = (T: (EventSource: string, EventName: string, RequestParameters: dynamic, ResponseElements: dynamic)) {\n let IAMEventNameLookup = datatable(EventName: string, EventType: string)\n [\n \"AddUserToGroup\", \"UserAddedToGroup\",\n \"AttachGroupPolicy\", \"GroupModified\",\n \"AttachUserPolicy\", \"UserModified\",\n \"ChangePassword\", \"PasswordChanged\",\n \"CreateGroup\", \"GroupCreated\",\n \"CreateLoginProfile\", \"UserModified\",\n \"CreateUser\", \"UserCreated\",\n \"DeleteGroup\", \"GroupDeleted\",\n \"DeleteGroupPolicy\", \"GroupModified\",\n \"DeleteLoginProfile\", \"UserModified\",\n \"DeleteRole\", \"UserDeleted\",\n \"DeleteUser\", \"UserDeleted\",\n \"DeleteUserPolicy\", \"UserModified\",\n \"DetachGroupPolicy\", \"GroupModified\",\n \"DetachRolePolicy\", \"UserModified\",\n \"DetachUserPolicy\", \"UserModified\",\n \"EnableMFADevice\", \"UserModified\",\n \"GetGroup\", \"GroupRead\",\n \"GetGroupPolicy\", \"GroupRead\",\n \"GetLoginProfile\", \"UserRead\",\n \"GetMFADevice\", \"UserRead\",\n \"GetRole\", \"UserRead\",\n \"GetUser\", \"UserRead\",\n \"ListAttachedGroupPolicies\", \"GroupRead\",\n \"ListAttachedRolePolicies\", \"UserRead\",\n \"ListAttachedUserPolicies\", \"UserRead\",\n \"ListGroups\", \"GroupEnumerated\",\n \"ListGroupsForUser\", \"UserRead\",\n \"ListMFADevices\", \"UserRead\",\n \"ListRoles\", \"UserRead\",\n \"ListUsers\", \"UserRead\",\n \"PutGroupPolicy\", \"GroupModified\",\n \"PutRolePolicy\", \"UserModified\",\n \"PutUserPolicy\", \"UserModified\",\n \"RemoveUserFromGroup\", \"UserRemovedFromGroup\",\n \"TagRole\", \"UserModified\",\n \"TagUser\", \"UserModified\",\n \"UntagUser\", \"UserModified\",\n \"UntagUser\", \"UserModified\",\n \"UpdateGroup\", \"GroupModified\",\n \"UpdateLoginProfile\", \"PasswordChanged\",\n \"UpdateRole\", \"UserModified\",\n \"UpdateRoleDescription\", \"UserModified\",\n \"UpdateSigningCertificate\", \"PasswordChanged\",\n \"UpdateSSHPublicKey\", \"PasswordChanged\",\n \"UpdateUser\", \"UserModified\",\n \"UploadSigningCertificate\", \"UserModified\",\n \"UploadSSHPublicKey\", \"UserModified\"\n ];\n T\n | where EventSource == \"iam.amazonaws.com\"\n | lookup IAMEventNameLookup on EventName\n | where isnotempty(EventType)\n // Filter on EventType\n | where (array_length(eventtype_in) == 0 or EventType in~ (eventtype_in))\n | extend\n TargetUserId = coalesce(tostring(ResponseElements.user.userId), tostring(ResponseElements.role.roleId)),\n TargetUsername = coalesce(tostring(RequestParameters.userName), tostring(RequestParameters.roleName)),\n GroupId = tostring(ResponseElements.group.groupName),\n GroupName = tostring(RequestParameters.groupName)\n // Post-filtering on TargetUsername\n | where (array_length(targetusername_has_any) == 0 or TargetUsername has_any (targetusername_has_any))\n | extend \n TargetUserIdType = case(\n TargetUserId startswith \"AROA\", \"AWSIAMRoleId\",\n TargetUserId startswith \"AIDA\", \"AWSIAMUserId\",\n \"\"\n ),\n GroupOriginalType = iff(isempty(GroupName), \"\", \"IAM Group\")\n | extend AdditionalData = iff(pack, bag_pack(\n \"TargetUserARN\", coalesce(tostring(ResponseElements.user.arn), tostring(ResponseElements.role.arn)),\n \"GroupARN\", tostring(ResponseElements.group.arn)\n ), dynamic([]))\n };\n let ParseCognitoEvents = (T: (EventSource: string, EventName: string, RequestParameters: dynamic)) {\n let CognitoIDPEventNameLookup = datatable(EventName: string, EventType: string)\n [\n \"AddCustomAttributes\", \"GroupModified\",\n \"AdminAddUserToGroup\", \"UserAddedToGroup\",\n \"AdminConfirmSignUp\", \"UserEnabled\",\n \"AdminCreateUser\", \"UserCreated\",\n \"AdminDeleteUser\", \"UserDeleted\",\n \"AdminDeleteUserAttributes\", \"UserModified\",\n \"AdminDisableProviderForUser\", \"UserDisabled\",\n \"AdminDisableUser\", \"UserDisabled\",\n \"AdminEnableUser\", \"UserEnabled\",\n \"AdminForgetDevice\", \"UserModified\",\n \"AdminGetDevice\", \"UserRead\",\n \"AdminGetUser\", \"UserRead\",\n \"AdminLinkUserAuthEvents\", \"UserModified\",\n \"AdminListDevices\", \"UserRead\",\n \"AdminListGroupsForUser\", \"UserRead\",\n \"AdminListUserAuthEvents\", \"UserRead\",\n \"AdminRemoveUserFromGroup\", \"UserRemovedFromGroup\",\n \"AdminResetUserPassword\", \"PasswordReset\",\n \"AdminSetUserMFAPreference\", \"UserModified\",\n \"AdminSetUserPassword\", \"PasswordChanged\",\n \"AdminSetUserSettings\", \"UserModified\",\n \"AdminUpdateDeviceStatus\", \"UserModified\",\n \"AdminUpdateUserAttributes\", \"UserModified\",\n \"ChangePassword\", \"PasswordChanged\",\n \"CompleteWebAuthnRegistration\", \"UserModified\",\n \"ConfirmSignUp\", \"UserCreated\",\n \"CreateGroup\", \"GroupCreated\",\n \"CreateUserPool\", \"GroupCreated\",\n \"DeleteGroup\", \"GroupDeleted\",\n \"DeleteUser\", \"UserDeleted\",\n \"DeleteUserAttributes\", \"UserModified\",\n \"DeleteUserPool\", \"GroupDeleted\",\n \"DeleteWebAuthnCredential\", \"UserModified\",\n \"DescribeUserPool\", \"GroupRead\",\n \"GetGroup\", \"GroupRead\",\n \"GetUser\", \"UserRead\",\n \"GetUserPoolMfaConfig\", \"GroupRead\",\n \"ListGroups\", \"GroupRead\",\n \"ListIdentityProviders\", \"GroupRead\",\n \"ListResourceServers\", \"GroupRead\",\n \"ListTerms\", \"GroupRead\",\n \"ListUserPools\", \"GroupEnumerated\",\n \"ListUsers\", \"GroupEnumerated\",\n \"ListUsersInGroup\", \"GroupEnumerated\",\n \"SetUserPoolMfaConfig\", \"GroupModified\",\n \"SignUp\", \"UserCreated\",\n \"UpdateGroup\", \"GroupModified\",\n \"UpdateUserAttributes\", \"UserModified\",\n \"UpdateUserPool\", \"GroupModified\"\n ];\n T\n | where EventSource == \"cognito-idp.amazonaws.com\"\n | lookup CognitoIDPEventNameLookup on EventName\n | where isnotempty(EventType)\n // Filter on EventType\n | where (array_length(eventtype_in) == 0 or EventType in~ (eventtype_in))\n | extend\n TargetUsername = tostring(RequestParameters.username),\n GroupName = coalesce(tostring(RequestParameters.poolName), tostring(RequestParameters.groupName)),\n GroupId = tostring(RequestParameters.userPoolId)\n | extend GroupOriginalType = case(\n isnotempty(tostring(RequestParameters.groupName)), \"UserPool Group\",\n isnotempty(GroupId), \"UserPool\",\n \"\")\n | extend AdditionalData = iff(pack, bag_pack(\n \"UserPoolId\", tostring(RequestParameters.UserPoolId)\n ), dynamic([]))\n };\n let parser = (\n starttime:datetime = datetime(null),\n endtime:datetime = datetime(null), srcipaddr_has_any_prefix:dynamic = dynamic([]),\n targetusername_has_any:dynamic = dynamic([]),\n actorusername_has_any:dynamic = dynamic([]),\n eventtype_in:dynamic = dynamic([]),\n disabled:bool= false,\n pack: bool= false\n ) {\n let SupportedEventSources = dynamic([\n \"cognito-idp.amazonaws.com\",\n \"iam.amazonaws.com\"\n ]);\n let EventSourceNameLookup = datatable(EventSource: string, TargetUserScope: string)\n [\n \"cognito-idp.amazonaws.com\", \"Cognito User Pools\",\n \"iam.amazonaws.com\", \"IAM\"\n ];\n let SupportedEvents = AWSCloudTrail\n | where not(disabled)\n | where EventSource in (SupportedEventSources)\n | where (isnull(starttime) or TimeGenerated >= starttime)\n and (isnull(endtime) or TimeGenerated <= endtime)\n | where (array_length(srcipaddr_has_any_prefix) == 0 or has_any_ipv4_prefix(SourceIpAddress, srcipaddr_has_any_prefix))\n and (array_length(actorusername_has_any) == 0 or UserIdentityUserName has_any (actorusername_has_any))\n // Filter on EventType done later in parser\n | where (array_length(targetusername_has_any) == 0 or RequestParameters has_any (targetusername_has_any))\n | extend RequestParameters = todynamic(RequestParameters), ResponseElements = todynamic(ResponseElements);\n union isfuzzy=false\n ParseIAMEvents(SupportedEvents),\n ParseCognitoEvents(SupportedEvents)\n | extend\n Type = \"AWSCloudTrail\",\n EventCount = int(1),\n EventStartTime = TimeGenerated,\n EventEndTime = TimeGenerated,\n EventSeverity = \"Informational\",\n EventSchema = \"UserManagement\",\n EventSchemaVersion = \"0.1.2\",\n EventVendor = \"AWS\",\n EventProduct = \"CloudTrail\",\n Dvc = \"CloudTrail\",\n EventResult = iff(isempty(ErrorCode) and isempty(ErrorMessage), \"Success\", \"Failure\"),\n EventMessage = ErrorMessage\n | lookup EventSourceNameLookup on EventSource\n | project-rename\n EventOriginalSubType = EventTypeName,\n EventOriginalType = EventName,\n EventUid = AwsEventId,\n EventOriginalResultDetails = ErrorMessage,\n EventProductVersion = EventVersion\n | project-rename\n ActorUserId = UserIdentityAccountId,\n ActorUsername = UserIdentityUserName,\n ActorOriginalUserType = UserIdentityType,\n HttpUserAgent = UserAgent\n | extend\n ActorUserIdType = iff(isempty(ActorUserId), \"\", \"AWSId\"),\n ActorUsernameType = iff(isempty(ActorUsername), \"\", \"Simple\"),\n SrcIpAddr = iff(ipv4_is_in_range(SourceIpAddress, \"0.0.0.0/0\"), SourceIpAddress, \"\")\n | extend\n TargetUsernameType = iff(isempty(TargetUsername), \"\", \"Simple\"),\n GroupIdType = iff(isempty(GroupId), \"\", \"Simple\"),\n GroupNameType = iff(isempty(GroupName), \"\", \"Simple\")\n | extend AdditionalFields = iff(pack, bag_pack(\n \"ActorAccessKeyId\", UserIdentityAccessKeyId,\n \"AWSRegion\", AWSRegion,\n \"APIVersion\", APIVersion,\n \"ManagementEvent\", ManagementEvent,\n \"ReadOnly\", ReadOnly,\n \"RequestParameters\", RequestParameters,\n \"ResponseElements\", ResponseElements\n ), dynamic([]))\n | extend AdditionalFields = iff(pack, bag_merge(AdditionalFields, AdditionalData), dynamic([]))\n // Alias\n | extend\n User = ActorUsername,\n IpAddr = SrcIpAddr\n | project\n TimeGenerated,\n Type,\n EventCount,\n EventStartTime,\n EventEndTime,\n EventSeverity,\n EventSchema,\n EventSchemaVersion,\n EventVendor,\n EventProduct,\n TargetUserScope,\n Dvc,\n EventResult,\n EventMessage,\n EventType,\n EventOriginalSubType,\n EventOriginalType,\n EventUid,\n EventOriginalResultDetails,\n EventProductVersion,\n ActorUserId,\n ActorUsername,\n ActorOriginalUserType,\n HttpUserAgent,\n ActorUserIdType,\n ActorUsernameType,\n SrcIpAddr,\n TargetUserId,\n TargetUsername,\n TargetUserIdType,\n GroupId,\n GroupName,\n TargetUsernameType,\n GroupIdType,\n GroupNameType,\n GroupOriginalType,\n User,\n IpAddr,\n AdditionalFields\n};\nparser (\n starttime = starttime,\n endtime = endtime,\n srcipaddr_has_any_prefix = srcipaddr_has_any_prefix,\n targetusername_has_any = targetusername_has_any,\n actorusername_has_any = actorusername_has_any,\n eventtype_in = eventtype_in,\n disabled = disabled,\n pack = pack\n)\n", + "query": "let ParseIAMEvents = (T: (EventSource: string, EventName: string, RequestParameters: dynamic, ResponseElements: dynamic)) {\n let IAMEventNameLookup = datatable(EventName: string, EventType: string)\n [\n \"AddUserToGroup\", \"UserAddedToGroup\",\n \"AttachGroupPolicy\", \"GroupModified\",\n \"AttachUserPolicy\", \"UserModified\",\n \"ChangePassword\", \"PasswordChanged\",\n \"CreateGroup\", \"GroupCreated\",\n \"CreateLoginProfile\", \"UserModified\",\n \"CreateUser\", \"UserCreated\",\n \"DeleteGroup\", \"GroupDeleted\",\n \"DeleteGroupPolicy\", \"GroupModified\",\n \"DeleteLoginProfile\", \"UserModified\",\n \"DeleteRole\", \"UserDeleted\",\n \"DeleteUser\", \"UserDeleted\",\n \"DeleteUserPolicy\", \"UserModified\",\n \"DetachGroupPolicy\", \"GroupModified\",\n \"DetachRolePolicy\", \"UserModified\",\n \"DetachUserPolicy\", \"UserModified\",\n \"EnableMFADevice\", \"UserModified\",\n \"GetGroup\", \"GroupRead\",\n \"GetGroupPolicy\", \"GroupRead\",\n \"GetLoginProfile\", \"UserRead\",\n \"GetMFADevice\", \"UserRead\",\n \"GetRole\", \"UserRead\",\n \"GetUser\", \"UserRead\",\n \"ListAttachedGroupPolicies\", \"GroupRead\",\n \"ListAttachedRolePolicies\", \"UserRead\",\n \"ListAttachedUserPolicies\", \"UserRead\",\n \"ListGroups\", \"GroupEnumerated\",\n \"ListGroupsForUser\", \"UserRead\",\n \"ListMFADevices\", \"UserRead\",\n \"ListRoles\", \"UserRead\",\n \"ListUsers\", \"UserRead\",\n \"PutGroupPolicy\", \"GroupModified\",\n \"PutRolePolicy\", \"UserModified\",\n \"PutUserPolicy\", \"UserModified\",\n \"RemoveUserFromGroup\", \"UserRemovedFromGroup\",\n \"TagRole\", \"UserModified\",\n \"TagUser\", \"UserModified\",\n \"UntagUser\", \"UserModified\",\n \"UpdateGroup\", \"GroupModified\",\n \"UpdateLoginProfile\", \"PasswordChanged\",\n \"UpdateRole\", \"UserModified\",\n \"UpdateRoleDescription\", \"UserModified\",\n \"UpdateSigningCertificate\", \"PasswordChanged\",\n \"UpdateSSHPublicKey\", \"PasswordChanged\",\n \"UpdateUser\", \"UserModified\",\n \"UploadSigningCertificate\", \"UserModified\",\n \"UploadSSHPublicKey\", \"UserModified\"\n ];\n T\n | where EventSource == \"iam.amazonaws.com\"\n | lookup IAMEventNameLookup on EventName\n | where isnotempty(EventType)\n // Filter on EventType\n | where (array_length(eventtype_in) == 0 or EventType in~ (eventtype_in))\n | extend\n TargetUserId = coalesce(tostring(ResponseElements.user.userId), tostring(ResponseElements.role.roleId)),\n TargetUsername = coalesce(tostring(RequestParameters.userName), tostring(RequestParameters.roleName)),\n GroupId = tostring(ResponseElements.group.groupName),\n GroupName = tostring(RequestParameters.groupName)\n // Post-filtering on TargetUsername\n | where (array_length(targetusername_has_any) == 0 or TargetUsername has_any (targetusername_has_any))\n | extend \n TargetUserIdType = case(\n TargetUserId startswith \"AROA\", \"AWSIAMRoleId\",\n TargetUserId startswith \"AIDA\", \"AWSIAMUserId\",\n \"\"\n ),\n GroupOriginalType = iff(isempty(GroupName), \"\", \"IAM Group\")\n | extend AdditionalData = iff(pack, bag_pack(\n \"TargetUserARN\", coalesce(tostring(ResponseElements.user.arn), tostring(ResponseElements.role.arn)),\n \"GroupARN\", tostring(ResponseElements.group.arn)\n ), dynamic([]))\n };\n let ParseCognitoEvents = (T: (EventSource: string, EventName: string, RequestParameters: dynamic)) {\n let CognitoIDPEventNameLookup = datatable(EventName: string, EventType: string)\n [\n \"AddCustomAttributes\", \"GroupModified\",\n \"AdminAddUserToGroup\", \"UserAddedToGroup\",\n \"AdminConfirmSignUp\", \"UserEnabled\",\n \"AdminCreateUser\", \"UserCreated\",\n \"AdminDeleteUser\", \"UserDeleted\",\n \"AdminDeleteUserAttributes\", \"UserModified\",\n \"AdminDisableProviderForUser\", \"UserDisabled\",\n \"AdminDisableUser\", \"UserDisabled\",\n \"AdminEnableUser\", \"UserEnabled\",\n \"AdminForgetDevice\", \"UserModified\",\n \"AdminGetDevice\", \"UserRead\",\n \"AdminGetUser\", \"UserRead\",\n \"AdminLinkUserAuthEvents\", \"UserModified\",\n \"AdminListDevices\", \"UserRead\",\n \"AdminListGroupsForUser\", \"UserRead\",\n \"AdminListUserAuthEvents\", \"UserRead\",\n \"AdminRemoveUserFromGroup\", \"UserRemovedFromGroup\",\n \"AdminResetUserPassword\", \"PasswordReset\",\n \"AdminSetUserMFAPreference\", \"UserModified\",\n \"AdminSetUserPassword\", \"PasswordChanged\",\n \"AdminSetUserSettings\", \"UserModified\",\n \"AdminUpdateDeviceStatus\", \"UserModified\",\n \"AdminUpdateUserAttributes\", \"UserModified\",\n \"ChangePassword\", \"PasswordChanged\",\n \"CompleteWebAuthnRegistration\", \"UserModified\",\n \"ConfirmSignUp\", \"UserCreated\",\n \"CreateGroup\", \"GroupCreated\",\n \"CreateUserPool\", \"GroupCreated\",\n \"DeleteGroup\", \"GroupDeleted\",\n \"DeleteUser\", \"UserDeleted\",\n \"DeleteUserAttributes\", \"UserModified\",\n \"DeleteUserPool\", \"GroupDeleted\",\n \"DeleteWebAuthnCredential\", \"UserModified\",\n \"DescribeUserPool\", \"GroupRead\",\n \"GetGroup\", \"GroupRead\",\n \"GetUser\", \"UserRead\",\n \"GetUserPoolMfaConfig\", \"GroupRead\",\n \"ListGroups\", \"GroupRead\",\n \"ListIdentityProviders\", \"GroupRead\",\n \"ListResourceServers\", \"GroupRead\",\n \"ListTerms\", \"GroupRead\",\n \"ListUserPools\", \"GroupEnumerated\",\n \"ListUsers\", \"GroupEnumerated\",\n \"ListUsersInGroup\", \"GroupEnumerated\",\n \"SetUserPoolMfaConfig\", \"GroupModified\",\n \"SignUp\", \"UserCreated\",\n \"UpdateGroup\", \"GroupModified\",\n \"UpdateUserAttributes\", \"UserModified\",\n \"UpdateUserPool\", \"GroupModified\"\n ];\n T\n | where EventSource == \"cognito-idp.amazonaws.com\"\n | lookup CognitoIDPEventNameLookup on EventName\n | where isnotempty(EventType)\n // Filter on EventType\n | where (array_length(eventtype_in) == 0 or EventType in~ (eventtype_in))\n | extend\n TargetUsername = tostring(RequestParameters.username),\n GroupName = coalesce(tostring(RequestParameters.poolName), tostring(RequestParameters.groupName)),\n GroupId = tostring(RequestParameters.userPoolId)\n | extend GroupOriginalType = case(\n isnotempty(tostring(RequestParameters.groupName)), \"UserPool Group\",\n isnotempty(GroupId), \"UserPool\",\n \"\")\n | extend AdditionalData = iff(pack, bag_pack(\n \"UserPoolId\", tostring(RequestParameters.UserPoolId)\n ), dynamic([]))\n };\n let parser = (\n starttime:datetime = datetime(null),\n endtime:datetime = datetime(null), srcipaddr_has_any_prefix:dynamic = dynamic([]),\n targetusername_has_any:dynamic = dynamic([]),\n actorusername_has_any:dynamic = dynamic([]),\n eventtype_in:dynamic = dynamic([]),\n disabled:bool= false,\n pack: bool= false\n ) {\n let SupportedEventSources = dynamic([\n \"cognito-idp.amazonaws.com\",\n \"iam.amazonaws.com\"\n ]);\n let EventSourceNameLookup = datatable(EventSource: string, TargetUserScope: string)\n [\n \"cognito-idp.amazonaws.com\", \"Cognito User Pools\",\n \"iam.amazonaws.com\", \"IAM\"\n ];\n let SupportedEvents = AWSCloudTrail\n | where not(disabled)\n | where EventSource in (SupportedEventSources)\n | where (isnull(starttime) or TimeGenerated >= starttime)\n and (isnull(endtime) or TimeGenerated <= endtime)\n | where (array_length(srcipaddr_has_any_prefix) == 0 or has_any_ipv4_prefix(SourceIpAddress, srcipaddr_has_any_prefix))\n and (array_length(actorusername_has_any) == 0 or UserIdentityUserName has_any (actorusername_has_any))\n // Filter on EventType done later in parser\n | where (array_length(targetusername_has_any) == 0 or RequestParameters has_any (targetusername_has_any))\n | extend RequestParameters = todynamic(RequestParameters), ResponseElements = todynamic(ResponseElements);\n union isfuzzy=false\n ParseIAMEvents(SupportedEvents),\n ParseCognitoEvents(SupportedEvents)\n | extend\n Type = \"AWSCloudTrail\",\n EventCount = int(1),\n EventStartTime = TimeGenerated,\n EventEndTime = TimeGenerated,\n EventSeverity = \"Informational\",\n EventSchema = \"UserManagement\",\n EventSchemaVersion = \"0.1.2\",\n EventVendor = \"AWS\",\n EventProduct = \"CloudTrail\",\n Dvc = \"CloudTrail\",\n EventResult = iff(isempty(ErrorCode) and isempty(ErrorMessage), \"Success\", \"Failure\"),\n EventMessage = ErrorMessage\n | lookup EventSourceNameLookup on EventSource\n | project-rename\n EventOriginalSubType = EventTypeName,\n EventOriginalType = EventName,\n EventUid = AwsEventId,\n EventOriginalResultDetails = ErrorMessage,\n EventProductVersion = EventVersion\n | project-rename\n ActorUserId = UserIdentityAccountId,\n ActorUsername = UserIdentityUserName,\n ActorOriginalUserType = UserIdentityType,\n HttpUserAgent = UserAgent\n | extend\n ActorUserIdType = iff(isempty(ActorUserId), \"\", \"AWSId\"),\n ActorUsernameType = iff(isempty(ActorUsername), \"\", \"Simple\"),\n SrcIpAddr = iff(ipv4_is_in_range(SourceIpAddress, \"0.0.0.0/0\"), SourceIpAddress, \"\")\n | extend\n TargetUsernameType = iff(isempty(TargetUsername), \"\", \"Simple\"),\n GroupIdType = iff(isempty(GroupId), \"\", \"Simple\"),\n GroupNameType = iff(isempty(GroupName), \"\", \"Simple\")\n | extend AdditionalFields = iff(pack, bag_pack(\n \"ActorAccessKeyId\", UserIdentityAccessKeyId,\n \"AWSRegion\", AWSRegion,\n \"APIVersion\", APIVersion,\n \"ManagementEvent\", ManagementEvent,\n \"ReadOnly\", ReadOnly,\n \"RequestParameters\", RequestParameters,\n \"ResponseElements\", ResponseElements\n ), dynamic([]))\n | extend AdditionalFields = iff(pack, bag_merge(AdditionalFields, AdditionalData), dynamic([]))\n // Alias\n | extend\n User = ActorUsername,\n IpAddr = SrcIpAddr\n | project\n TimeGenerated,\n Type,\n EventCount,\n EventStartTime,\n EventEndTime,\n EventSeverity,\n EventSchema,\n EventSchemaVersion,\n EventVendor,\n EventProduct,\n TargetUserScope,\n Dvc,\n EventResult,\n EventMessage,\n EventType,\n EventOriginalSubType,\n EventOriginalType,\n EventUid,\n EventOriginalResultDetails,\n EventProductVersion,\n ActorUserId,\n ActorUsername,\n ActorOriginalUserType,\n HttpUserAgent,\n ActorUserIdType,\n ActorUsernameType,\n SrcIpAddr,\n TargetUserId,\n TargetUsername,\n TargetUserIdType,\n GroupId,\n GroupName,\n TargetUsernameType,\n GroupIdType,\n GroupNameType,\n GroupOriginalType,\n User,\n IpAddr,\n AdditionalFields\n};\nparser (\n starttime = starttime,\n endtime = endtime,\n srcipaddr_has_any_prefix = srcipaddr_has_any_prefix,\n targetusername_has_any = targetusername_has_any,\n actorusername_has_any = actorusername_has_any,\n eventtype_in = eventtype_in,\n disabled = disabled,\n pack = pack\n)\n", "version": 1, "functionParameters": "starttime:datetime=datetime(null),endtime:datetime=datetime(null),srcipaddr_has_any_prefix:dynamic=dynamic([]),actorusername_has_any:dynamic=dynamic([]),targetusername_has_any:dynamic=dynamic([]),eventtype_in:dynamic=dynamic([]),disabled:bool=False,pack:bool=False" } From c4b3c1b7cd63ba4e4d2c558e374807c2d7df4ba2 Mon Sep 17 00:00:00 2001 From: Brandon Qiao Date: Fri, 23 Oct 2026 11:27:58 -0400 Subject: [PATCH 3/6] semicolon fix --- .../CHANGELOG/ASimUserManagementAWSCloudTrail.md | 1 + .../Parsers/ASimUserManagementAWSCloudTrail.yaml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Parsers/ASimUserManagement/CHANGELOG/ASimUserManagementAWSCloudTrail.md b/Parsers/ASimUserManagement/CHANGELOG/ASimUserManagementAWSCloudTrail.md index 3195dcce8f4..1c5f8798b87 100644 --- a/Parsers/ASimUserManagement/CHANGELOG/ASimUserManagementAWSCloudTrail.md +++ b/Parsers/ASimUserManagement/CHANGELOG/ASimUserManagementAWSCloudTrail.md @@ -3,6 +3,7 @@ ## Version 0.1.1 - (2026-10-23) Remove the duplicate IAM lookup entry for UntagUser so each matching event produces one UserModified output row. +- Remove the trailing semicolon from the parser invocation so callers and KQL validation can append pipeline operators. ## Version 0.1.0 - (2026-01-26) [ASIM] UserManagement - AWSCloudTrail (New Parser) - [PR #13503](https://github.com/Azure/Azure-Sentinel/pull/13503) diff --git a/Parsers/ASimUserManagement/Parsers/ASimUserManagementAWSCloudTrail.yaml b/Parsers/ASimUserManagement/Parsers/ASimUserManagementAWSCloudTrail.yaml index bac84bf6850..f3e0c11496a 100644 --- a/Parsers/ASimUserManagement/Parsers/ASimUserManagementAWSCloudTrail.yaml +++ b/Parsers/ASimUserManagement/Parsers/ASimUserManagementAWSCloudTrail.yaml @@ -271,4 +271,4 @@ ParserQuery: | IpAddr, AdditionalFields }; - parser(disabled = disabled, pack = pack); \ No newline at end of file + parser(disabled = disabled, pack = pack) \ No newline at end of file From 56ce96da090bd158ad6abff3b61dfcf8ab475d95 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <> Date: Fri, 23 Oct 2026 15:31:49 +0000 Subject: [PATCH 4/6] [ASIM Parsers] Generate deployable ARM templates from KQL function YAML files. --- .../ASimUserManagementAWSCloudTrail.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Parsers/ASimUserManagement/ARM/ASimUserManagementAWSCloudTrail/ASimUserManagementAWSCloudTrail.json b/Parsers/ASimUserManagement/ARM/ASimUserManagementAWSCloudTrail/ASimUserManagementAWSCloudTrail.json index 1a11b84676f..bfce7be376c 100644 --- a/Parsers/ASimUserManagement/ARM/ASimUserManagementAWSCloudTrail/ASimUserManagementAWSCloudTrail.json +++ b/Parsers/ASimUserManagement/ARM/ASimUserManagementAWSCloudTrail/ASimUserManagementAWSCloudTrail.json @@ -27,7 +27,7 @@ "displayName": "User Management ASIM parser for AWS Cloud Trail", "category": "ASIM", "FunctionAlias": "ASimUserManagementAWSCloudTrail", - "query": "let ParseIAMEvents = (T: (EventSource: string, EventName: string, RequestParameters: dynamic, ResponseElements: dynamic)) {\n let IAMEventNameLookup = datatable(EventName: string, EventType: string)\n [\n \"AddUserToGroup\", \"UserAddedToGroup\",\n \"AttachGroupPolicy\", \"GroupModified\",\n \"AttachUserPolicy\", \"UserModified\",\n \"ChangePassword\", \"PasswordChanged\",\n \"CreateGroup\", \"GroupCreated\",\n \"CreateLoginProfile\", \"UserModified\",\n \"CreateUser\", \"UserCreated\",\n \"DeleteGroup\", \"GroupDeleted\",\n \"DeleteGroupPolicy\", \"GroupModified\",\n \"DeleteLoginProfile\", \"UserModified\",\n \"DeleteRole\", \"UserDeleted\",\n \"DeleteUser\", \"UserDeleted\",\n \"DeleteUserPolicy\", \"UserModified\",\n \"DetachGroupPolicy\", \"GroupModified\",\n \"DetachRolePolicy\", \"UserModified\",\n \"DetachUserPolicy\", \"UserModified\",\n \"EnableMFADevice\", \"UserModified\",\n \"GetGroup\", \"GroupRead\",\n \"GetGroupPolicy\", \"GroupRead\",\n \"GetLoginProfile\", \"UserRead\",\n \"GetMFADevice\", \"UserRead\",\n \"GetRole\", \"UserRead\",\n \"GetUser\", \"UserRead\",\n \"ListAttachedGroupPolicies\", \"GroupRead\",\n \"ListAttachedRolePolicies\", \"UserRead\",\n \"ListAttachedUserPolicies\", \"UserRead\",\n \"ListGroups\", \"GroupEnumerated\",\n \"ListGroupsForUser\", \"UserRead\",\n \"ListMFADevices\", \"UserRead\",\n \"ListRoles\", \"UserRead\",\n \"ListUsers\", \"UserRead\",\n \"PutGroupPolicy\", \"GroupModified\",\n \"PutRolePolicy\", \"UserModified\",\n \"PutUserPolicy\", \"UserModified\",\n \"RemoveUserFromGroup\", \"UserRemovedFromGroup\",\n \"TagRole\", \"UserModified\",\n \"TagUser\", \"UserModified\",\n \"UntagUser\", \"UserModified\",\n \"UpdateGroup\", \"GroupModified\",\n \"UpdateLoginProfile\", \"PasswordChanged\",\n \"UpdateRole\", \"UserModified\",\n \"UpdateRoleDescription\", \"UserModified\",\n \"UpdateSigningCertificate\", \"PasswordChanged\",\n \"UpdateSSHPublicKey\", \"PasswordChanged\",\n \"UpdateUser\", \"UserModified\",\n \"UploadSigningCertificate\", \"UserModified\",\n \"UploadSSHPublicKey\", \"UserModified\"\n ];\n T\n | where EventSource == \"iam.amazonaws.com\"\n | lookup IAMEventNameLookup on EventName\n | where isnotempty(EventType)\n | extend\n TargetUserId = coalesce(tostring(ResponseElements.user.userId), tostring(ResponseElements.role.roleId)),\n TargetUsername = coalesce(tostring(RequestParameters.userName), tostring(RequestParameters.roleName)),\n GroupId = tostring(ResponseElements.group.groupName),\n GroupName = tostring(RequestParameters.groupName)\n | extend \n TargetUserIdType = case(\n TargetUserId startswith \"AROA\", \"AWSIAMRoleId\",\n TargetUserId startswith \"AIDA\", \"AWSIAMUserId\",\n \"\"\n ),\n GroupOriginalType = iff(isempty(GroupName), \"\", \"IAM Group\")\n | extend AdditionalData = bag_pack(\n \"TargetUserARN\", coalesce(tostring(ResponseElements.user.arn), tostring(ResponseElements.role.arn)),\n \"GroupARN\", tostring(ResponseElements.group.arn)\n )\n };\n let ParseCognitoEvents = (T: (EventSource: string, EventName: string, RequestParameters: dynamic)) {\n let CognitoIDPEventNameLookup = datatable(EventName: string, EventType: string)\n [\n \"AddCustomAttributes\", \"GroupModified\",\n \"AdminAddUserToGroup\", \"UserAddedToGroup\",\n \"AdminConfirmSignUp\", \"UserEnabled\",\n \"AdminCreateUser\", \"UserCreated\",\n \"AdminDeleteUser\", \"UserDeleted\",\n \"AdminDeleteUserAttributes\", \"UserModified\",\n \"AdminDisableProviderForUser\", \"UserDisabled\",\n \"AdminDisableUser\", \"UserDisabled\",\n \"AdminEnableUser\", \"UserEnabled\",\n \"AdminForgetDevice\", \"UserModified\",\n \"AdminGetDevice\", \"UserRead\",\n \"AdminGetUser\", \"UserRead\",\n \"AdminLinkUserAuthEvents\", \"UserModified\",\n \"AdminListDevices\", \"UserRead\",\n \"AdminListGroupsForUser\", \"UserRead\",\n \"AdminListUserAuthEvents\", \"UserRead\",\n \"AdminRemoveUserFromGroup\", \"UserRemovedFromGroup\",\n \"AdminResetUserPassword\", \"PasswordReset\",\n \"AdminSetUserMFAPreference\", \"UserModified\",\n \"AdminSetUserPassword\", \"PasswordChanged\",\n \"AdminSetUserSettings\", \"UserModified\",\n \"AdminUpdateDeviceStatus\", \"UserModified\",\n \"AdminUpdateUserAttributes\", \"UserModified\",\n \"ChangePassword\", \"PasswordChanged\",\n \"CompleteWebAuthnRegistration\", \"UserModified\",\n \"ConfirmSignUp\", \"UserCreated\",\n \"CreateGroup\", \"GroupCreated\",\n \"CreateUserPool\", \"GroupCreated\",\n \"DeleteGroup\", \"GroupDeleted\",\n \"DeleteUser\", \"UserDeleted\",\n \"DeleteUserAttributes\", \"UserModified\",\n \"DeleteUserPool\", \"GroupDeleted\",\n \"DeleteWebAuthnCredential\", \"UserModified\",\n \"DescribeUserPool\", \"GroupRead\",\n \"GetGroup\", \"GroupRead\",\n \"GetUser\", \"UserRead\",\n \"GetUserPoolMfaConfig\", \"GroupRead\",\n \"ListGroups\", \"GroupRead\",\n \"ListIdentityProviders\", \"GroupRead\",\n \"ListResourceServers\", \"GroupRead\",\n \"ListTerms\", \"GroupRead\",\n \"ListUserPools\", \"GroupEnumerated\",\n \"ListUsers\", \"GroupEnumerated\",\n \"ListUsersInGroup\", \"GroupEnumerated\",\n \"SetUserPoolMfaConfig\", \"GroupModified\",\n \"SignUp\", \"UserCreated\",\n \"UpdateGroup\", \"GroupModified\",\n \"UpdateUserAttributes\", \"UserModified\",\n \"UpdateUserPool\", \"GroupModified\"\n ];\n T\n | where EventSource == \"cognito-idp.amazonaws.com\"\n | lookup CognitoIDPEventNameLookup on EventName\n | where isnotempty(EventType)\n | extend\n TargetUsername = tostring(RequestParameters.username),\n GroupName = coalesce(tostring(RequestParameters.poolName), tostring(RequestParameters.groupName)),\n GroupId = tostring(RequestParameters.userPoolId)\n | extend GroupOriginalType = case(\n isnotempty(tostring(RequestParameters.groupName)), \"UserPool Group\",\n isnotempty(GroupId), \"UserPool\",\n \"\")\n | extend AdditionalData = bag_pack(\n \"UserPoolId\", tostring(RequestParameters.UserPoolId)\n )\n };\n let parser = (disabled: bool, pack: bool) {\n let SupportedEventSources = dynamic([\n \"cognito-idp.amazonaws.com\",\n \"iam.amazonaws.com\"\n ]);\n let EventSourceNameLookup = datatable(EventSource: string, TargetUserScope: string)\n [\n \"cognito-idp.amazonaws.com\", \"Cognito User Pools\",\n \"iam.amazonaws.com\", \"IAM\"\n ];\n let SupportedEvents = AWSCloudTrail\n | where EventSource in (SupportedEventSources)\n | extend RequestParameters = todynamic(RequestParameters), ResponseElements = todynamic(ResponseElements);\n union isfuzzy=false\n ParseIAMEvents(SupportedEvents),\n ParseCognitoEvents(SupportedEvents)\n | extend\n Type = \"AWSCloudTrail\",\n EventCount = int(1),\n EventStartTime = TimeGenerated,\n EventEndTime = TimeGenerated,\n EventSeverity = \"Informational\",\n EventSchema = \"UserManagement\",\n EventSchemaVersion = \"0.1.2\",\n EventVendor = \"AWS\",\n EventProduct = \"CloudTrail\",\n Dvc = \"CloudTrail\",\n EventResult = iff(isempty(ErrorCode) and isempty(ErrorMessage), \"Success\", \"Failure\"),\n EventMessage = ErrorMessage\n | lookup EventSourceNameLookup on EventSource\n | project-rename\n EventOriginalSubType = EventTypeName,\n EventOriginalType = EventName,\n EventUid = AwsEventId,\n EventOriginalResultDetails = ErrorMessage,\n EventProductVersion = EventVersion\n | project-rename\n ActorUserId = UserIdentityAccountId,\n ActorUsername = UserIdentityUserName,\n ActorOriginalUserType = UserIdentityType,\n HttpUserAgent = UserAgent\n | extend\n ActorUserIdType = iff(isempty(ActorUserId), \"\", \"AWSId\"),\n ActorUsernameType = iff(isempty(ActorUsername), \"\", \"Simple\"),\n SrcIpAddr = iff(ipv4_is_in_range(SourceIpAddress, \"0.0.0.0/0\"), SourceIpAddress, \"\")\n | extend\n TargetUsernameType = iff(isempty(TargetUsername), \"\", \"Simple\"),\n GroupIdType = iff(isempty(GroupId), \"\", \"Simple\"),\n GroupNameType = iff(isempty(GroupName), \"\", \"Simple\")\n | extend AdditionalFields = iff(pack, bag_pack(\n \"ActorAccessKeyId\", UserIdentityAccessKeyId,\n \"AWSRegion\", AWSRegion,\n \"APIVersion\", APIVersion,\n \"ManagementEvent\", ManagementEvent,\n \"ReadOnly\", ReadOnly,\n \"RequestParameters\", RequestParameters,\n \"ResponseElements\", ResponseElements\n ), dynamic([]))\n | extend AdditionalFields = iff(pack, bag_merge(AdditionalFields, AdditionalData), dynamic([]))\n // Alias\n | extend\n User = ActorUsername,\n IpAddr = SrcIpAddr\n | project\n TimeGenerated,\n Type,\n EventCount,\n EventStartTime,\n EventEndTime,\n EventSeverity,\n EventSchema,\n EventSchemaVersion,\n EventVendor,\n EventProduct,\n TargetUserScope,\n Dvc,\n EventResult,\n EventMessage,\n EventType,\n EventOriginalSubType,\n EventOriginalType,\n EventUid,\n EventOriginalResultDetails,\n EventProductVersion,\n ActorUserId,\n ActorUsername,\n ActorOriginalUserType,\n HttpUserAgent,\n ActorUserIdType,\n ActorUsernameType,\n SrcIpAddr,\n TargetUserId,\n TargetUsername,\n TargetUserIdType,\n GroupId,\n GroupName,\n TargetUsernameType,\n GroupIdType,\n GroupNameType,\n GroupOriginalType,\n User,\n IpAddr,\n AdditionalFields\n};\nparser(disabled = disabled, pack = pack);", + "query": "let ParseIAMEvents = (T: (EventSource: string, EventName: string, RequestParameters: dynamic, ResponseElements: dynamic)) {\n let IAMEventNameLookup = datatable(EventName: string, EventType: string)\n [\n \"AddUserToGroup\", \"UserAddedToGroup\",\n \"AttachGroupPolicy\", \"GroupModified\",\n \"AttachUserPolicy\", \"UserModified\",\n \"ChangePassword\", \"PasswordChanged\",\n \"CreateGroup\", \"GroupCreated\",\n \"CreateLoginProfile\", \"UserModified\",\n \"CreateUser\", \"UserCreated\",\n \"DeleteGroup\", \"GroupDeleted\",\n \"DeleteGroupPolicy\", \"GroupModified\",\n \"DeleteLoginProfile\", \"UserModified\",\n \"DeleteRole\", \"UserDeleted\",\n \"DeleteUser\", \"UserDeleted\",\n \"DeleteUserPolicy\", \"UserModified\",\n \"DetachGroupPolicy\", \"GroupModified\",\n \"DetachRolePolicy\", \"UserModified\",\n \"DetachUserPolicy\", \"UserModified\",\n \"EnableMFADevice\", \"UserModified\",\n \"GetGroup\", \"GroupRead\",\n \"GetGroupPolicy\", \"GroupRead\",\n \"GetLoginProfile\", \"UserRead\",\n \"GetMFADevice\", \"UserRead\",\n \"GetRole\", \"UserRead\",\n \"GetUser\", \"UserRead\",\n \"ListAttachedGroupPolicies\", \"GroupRead\",\n \"ListAttachedRolePolicies\", \"UserRead\",\n \"ListAttachedUserPolicies\", \"UserRead\",\n \"ListGroups\", \"GroupEnumerated\",\n \"ListGroupsForUser\", \"UserRead\",\n \"ListMFADevices\", \"UserRead\",\n \"ListRoles\", \"UserRead\",\n \"ListUsers\", \"UserRead\",\n \"PutGroupPolicy\", \"GroupModified\",\n \"PutRolePolicy\", \"UserModified\",\n \"PutUserPolicy\", \"UserModified\",\n \"RemoveUserFromGroup\", \"UserRemovedFromGroup\",\n \"TagRole\", \"UserModified\",\n \"TagUser\", \"UserModified\",\n \"UntagUser\", \"UserModified\",\n \"UpdateGroup\", \"GroupModified\",\n \"UpdateLoginProfile\", \"PasswordChanged\",\n \"UpdateRole\", \"UserModified\",\n \"UpdateRoleDescription\", \"UserModified\",\n \"UpdateSigningCertificate\", \"PasswordChanged\",\n \"UpdateSSHPublicKey\", \"PasswordChanged\",\n \"UpdateUser\", \"UserModified\",\n \"UploadSigningCertificate\", \"UserModified\",\n \"UploadSSHPublicKey\", \"UserModified\"\n ];\n T\n | where EventSource == \"iam.amazonaws.com\"\n | lookup IAMEventNameLookup on EventName\n | where isnotempty(EventType)\n | extend\n TargetUserId = coalesce(tostring(ResponseElements.user.userId), tostring(ResponseElements.role.roleId)),\n TargetUsername = coalesce(tostring(RequestParameters.userName), tostring(RequestParameters.roleName)),\n GroupId = tostring(ResponseElements.group.groupName),\n GroupName = tostring(RequestParameters.groupName)\n | extend \n TargetUserIdType = case(\n TargetUserId startswith \"AROA\", \"AWSIAMRoleId\",\n TargetUserId startswith \"AIDA\", \"AWSIAMUserId\",\n \"\"\n ),\n GroupOriginalType = iff(isempty(GroupName), \"\", \"IAM Group\")\n | extend AdditionalData = bag_pack(\n \"TargetUserARN\", coalesce(tostring(ResponseElements.user.arn), tostring(ResponseElements.role.arn)),\n \"GroupARN\", tostring(ResponseElements.group.arn)\n )\n };\n let ParseCognitoEvents = (T: (EventSource: string, EventName: string, RequestParameters: dynamic)) {\n let CognitoIDPEventNameLookup = datatable(EventName: string, EventType: string)\n [\n \"AddCustomAttributes\", \"GroupModified\",\n \"AdminAddUserToGroup\", \"UserAddedToGroup\",\n \"AdminConfirmSignUp\", \"UserEnabled\",\n \"AdminCreateUser\", \"UserCreated\",\n \"AdminDeleteUser\", \"UserDeleted\",\n \"AdminDeleteUserAttributes\", \"UserModified\",\n \"AdminDisableProviderForUser\", \"UserDisabled\",\n \"AdminDisableUser\", \"UserDisabled\",\n \"AdminEnableUser\", \"UserEnabled\",\n \"AdminForgetDevice\", \"UserModified\",\n \"AdminGetDevice\", \"UserRead\",\n \"AdminGetUser\", \"UserRead\",\n \"AdminLinkUserAuthEvents\", \"UserModified\",\n \"AdminListDevices\", \"UserRead\",\n \"AdminListGroupsForUser\", \"UserRead\",\n \"AdminListUserAuthEvents\", \"UserRead\",\n \"AdminRemoveUserFromGroup\", \"UserRemovedFromGroup\",\n \"AdminResetUserPassword\", \"PasswordReset\",\n \"AdminSetUserMFAPreference\", \"UserModified\",\n \"AdminSetUserPassword\", \"PasswordChanged\",\n \"AdminSetUserSettings\", \"UserModified\",\n \"AdminUpdateDeviceStatus\", \"UserModified\",\n \"AdminUpdateUserAttributes\", \"UserModified\",\n \"ChangePassword\", \"PasswordChanged\",\n \"CompleteWebAuthnRegistration\", \"UserModified\",\n \"ConfirmSignUp\", \"UserCreated\",\n \"CreateGroup\", \"GroupCreated\",\n \"CreateUserPool\", \"GroupCreated\",\n \"DeleteGroup\", \"GroupDeleted\",\n \"DeleteUser\", \"UserDeleted\",\n \"DeleteUserAttributes\", \"UserModified\",\n \"DeleteUserPool\", \"GroupDeleted\",\n \"DeleteWebAuthnCredential\", \"UserModified\",\n \"DescribeUserPool\", \"GroupRead\",\n \"GetGroup\", \"GroupRead\",\n \"GetUser\", \"UserRead\",\n \"GetUserPoolMfaConfig\", \"GroupRead\",\n \"ListGroups\", \"GroupRead\",\n \"ListIdentityProviders\", \"GroupRead\",\n \"ListResourceServers\", \"GroupRead\",\n \"ListTerms\", \"GroupRead\",\n \"ListUserPools\", \"GroupEnumerated\",\n \"ListUsers\", \"GroupEnumerated\",\n \"ListUsersInGroup\", \"GroupEnumerated\",\n \"SetUserPoolMfaConfig\", \"GroupModified\",\n \"SignUp\", \"UserCreated\",\n \"UpdateGroup\", \"GroupModified\",\n \"UpdateUserAttributes\", \"UserModified\",\n \"UpdateUserPool\", \"GroupModified\"\n ];\n T\n | where EventSource == \"cognito-idp.amazonaws.com\"\n | lookup CognitoIDPEventNameLookup on EventName\n | where isnotempty(EventType)\n | extend\n TargetUsername = tostring(RequestParameters.username),\n GroupName = coalesce(tostring(RequestParameters.poolName), tostring(RequestParameters.groupName)),\n GroupId = tostring(RequestParameters.userPoolId)\n | extend GroupOriginalType = case(\n isnotempty(tostring(RequestParameters.groupName)), \"UserPool Group\",\n isnotempty(GroupId), \"UserPool\",\n \"\")\n | extend AdditionalData = bag_pack(\n \"UserPoolId\", tostring(RequestParameters.UserPoolId)\n )\n };\n let parser = (disabled: bool, pack: bool) {\n let SupportedEventSources = dynamic([\n \"cognito-idp.amazonaws.com\",\n \"iam.amazonaws.com\"\n ]);\n let EventSourceNameLookup = datatable(EventSource: string, TargetUserScope: string)\n [\n \"cognito-idp.amazonaws.com\", \"Cognito User Pools\",\n \"iam.amazonaws.com\", \"IAM\"\n ];\n let SupportedEvents = AWSCloudTrail\n | where EventSource in (SupportedEventSources)\n | extend RequestParameters = todynamic(RequestParameters), ResponseElements = todynamic(ResponseElements);\n union isfuzzy=false\n ParseIAMEvents(SupportedEvents),\n ParseCognitoEvents(SupportedEvents)\n | extend\n Type = \"AWSCloudTrail\",\n EventCount = int(1),\n EventStartTime = TimeGenerated,\n EventEndTime = TimeGenerated,\n EventSeverity = \"Informational\",\n EventSchema = \"UserManagement\",\n EventSchemaVersion = \"0.1.2\",\n EventVendor = \"AWS\",\n EventProduct = \"CloudTrail\",\n Dvc = \"CloudTrail\",\n EventResult = iff(isempty(ErrorCode) and isempty(ErrorMessage), \"Success\", \"Failure\"),\n EventMessage = ErrorMessage\n | lookup EventSourceNameLookup on EventSource\n | project-rename\n EventOriginalSubType = EventTypeName,\n EventOriginalType = EventName,\n EventUid = AwsEventId,\n EventOriginalResultDetails = ErrorMessage,\n EventProductVersion = EventVersion\n | project-rename\n ActorUserId = UserIdentityAccountId,\n ActorUsername = UserIdentityUserName,\n ActorOriginalUserType = UserIdentityType,\n HttpUserAgent = UserAgent\n | extend\n ActorUserIdType = iff(isempty(ActorUserId), \"\", \"AWSId\"),\n ActorUsernameType = iff(isempty(ActorUsername), \"\", \"Simple\"),\n SrcIpAddr = iff(ipv4_is_in_range(SourceIpAddress, \"0.0.0.0/0\"), SourceIpAddress, \"\")\n | extend\n TargetUsernameType = iff(isempty(TargetUsername), \"\", \"Simple\"),\n GroupIdType = iff(isempty(GroupId), \"\", \"Simple\"),\n GroupNameType = iff(isempty(GroupName), \"\", \"Simple\")\n | extend AdditionalFields = iff(pack, bag_pack(\n \"ActorAccessKeyId\", UserIdentityAccessKeyId,\n \"AWSRegion\", AWSRegion,\n \"APIVersion\", APIVersion,\n \"ManagementEvent\", ManagementEvent,\n \"ReadOnly\", ReadOnly,\n \"RequestParameters\", RequestParameters,\n \"ResponseElements\", ResponseElements\n ), dynamic([]))\n | extend AdditionalFields = iff(pack, bag_merge(AdditionalFields, AdditionalData), dynamic([]))\n // Alias\n | extend\n User = ActorUsername,\n IpAddr = SrcIpAddr\n | project\n TimeGenerated,\n Type,\n EventCount,\n EventStartTime,\n EventEndTime,\n EventSeverity,\n EventSchema,\n EventSchemaVersion,\n EventVendor,\n EventProduct,\n TargetUserScope,\n Dvc,\n EventResult,\n EventMessage,\n EventType,\n EventOriginalSubType,\n EventOriginalType,\n EventUid,\n EventOriginalResultDetails,\n EventProductVersion,\n ActorUserId,\n ActorUsername,\n ActorOriginalUserType,\n HttpUserAgent,\n ActorUserIdType,\n ActorUsernameType,\n SrcIpAddr,\n TargetUserId,\n TargetUsername,\n TargetUserIdType,\n GroupId,\n GroupName,\n TargetUsernameType,\n GroupIdType,\n GroupNameType,\n GroupOriginalType,\n User,\n IpAddr,\n AdditionalFields\n};\nparser(disabled = disabled, pack = pack)", "version": 1, "functionParameters": "disabled:bool=False,pack:bool=False" } From f6d734ad86aff2060f26f92f631fdf8e52fc1aa5 Mon Sep 17 00:00:00 2001 From: Brandon Qiao Date: Fri, 23 Oct 2026 12:56:46 -0400 Subject: [PATCH 5/6] changelog --- .../CHANGELOG/ASimUserManagementAWSCloudTrail.md | 2 +- .../CHANGELOG/vimUserManagementAWSCloudTrail.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Parsers/ASimUserManagement/CHANGELOG/ASimUserManagementAWSCloudTrail.md b/Parsers/ASimUserManagement/CHANGELOG/ASimUserManagementAWSCloudTrail.md index 1c5f8798b87..3d4f02183d8 100644 --- a/Parsers/ASimUserManagement/CHANGELOG/ASimUserManagementAWSCloudTrail.md +++ b/Parsers/ASimUserManagement/CHANGELOG/ASimUserManagementAWSCloudTrail.md @@ -2,7 +2,7 @@ ## Version 0.1.1 -- (2026-10-23) Remove the duplicate IAM lookup entry for UntagUser so each matching event produces one UserModified output row. +- (2026-10-23) Remove the duplicate IAM lookup entry for UntagUser so each matching event produces one UserModified output row. - [PR #15408](https://github.com/Azure/Azure-Sentinel/pull/15408) - Remove the trailing semicolon from the parser invocation so callers and KQL validation can append pipeline operators. ## Version 0.1.0 diff --git a/Parsers/ASimUserManagement/CHANGELOG/vimUserManagementAWSCloudTrail.md b/Parsers/ASimUserManagement/CHANGELOG/vimUserManagementAWSCloudTrail.md index c6e9e0ea153..3f6969887a8 100644 --- a/Parsers/ASimUserManagement/CHANGELOG/vimUserManagementAWSCloudTrail.md +++ b/Parsers/ASimUserManagement/CHANGELOG/vimUserManagementAWSCloudTrail.md @@ -2,7 +2,7 @@ ## Version 0.1.1 -- (2026-10-23) Remove the duplicate IAM lookup entry for UntagUser so each matching event produces one UserModified output row. +- (2026-10-23) Remove the duplicate IAM lookup entry for UntagUser so each matching event produces one UserModified output row. - [PR #15408](https://github.com/Azure/Azure-Sentinel/pull/15408) ## Version 0.1.0 - (2026-01-26) [ASIM] UserManagement - AWSCloudTrail (New Parser) - [PR #13503](https://github.com/Azure/Azure-Sentinel/pull/13503) From ca7beacdc98877656059f2961e1e0414fcbbcb29 Mon Sep 17 00:00:00 2001 From: Brandon Qiao Date: Fri, 23 Oct 2026 16:25:42 -0400 Subject: [PATCH 6/6] new docs --- .../CHANGELOG/ASimUserManagementAWSCloudTrail.md | 2 +- .../CHANGELOG/vimUserManagementAWSCloudTrail.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Parsers/ASimUserManagement/CHANGELOG/ASimUserManagementAWSCloudTrail.md b/Parsers/ASimUserManagement/CHANGELOG/ASimUserManagementAWSCloudTrail.md index 3d4f02183d8..d3163a4a6a7 100644 --- a/Parsers/ASimUserManagement/CHANGELOG/ASimUserManagementAWSCloudTrail.md +++ b/Parsers/ASimUserManagement/CHANGELOG/ASimUserManagementAWSCloudTrail.md @@ -2,7 +2,7 @@ ## Version 0.1.1 -- (2026-10-23) Remove the duplicate IAM lookup entry for UntagUser so each matching event produces one UserModified output row. - [PR #15408](https://github.com/Azure/Azure-Sentinel/pull/15408) +- (2026-10-23) Remove the duplicate IAM lookup entry for UntagUser so each matching event produces one UserModified output row. - [PR #15413](https://github.com/Azure/Azure-Sentinel/pull/15413) - Remove the trailing semicolon from the parser invocation so callers and KQL validation can append pipeline operators. ## Version 0.1.0 diff --git a/Parsers/ASimUserManagement/CHANGELOG/vimUserManagementAWSCloudTrail.md b/Parsers/ASimUserManagement/CHANGELOG/vimUserManagementAWSCloudTrail.md index 3f6969887a8..4f996249c61 100644 --- a/Parsers/ASimUserManagement/CHANGELOG/vimUserManagementAWSCloudTrail.md +++ b/Parsers/ASimUserManagement/CHANGELOG/vimUserManagementAWSCloudTrail.md @@ -2,7 +2,7 @@ ## Version 0.1.1 -- (2026-10-23) Remove the duplicate IAM lookup entry for UntagUser so each matching event produces one UserModified output row. - [PR #15408](https://github.com/Azure/Azure-Sentinel/pull/15408) +- (2026-10-23) Remove the duplicate IAM lookup entry for UntagUser so each matching event produces one UserModified output row. - [PR #15413](https://github.com/Azure/Azure-Sentinel/pull/15413) ## Version 0.1.0 - (2026-01-26) [ASIM] UserManagement - AWSCloudTrail (New Parser) - [PR #13503](https://github.com/Azure/Azure-Sentinel/pull/13503)