From 136c8abe94762c493d550210ecd41c80fe9e65fd Mon Sep 17 00:00:00 2001 From: Mirko Bonasorte Date: Tue, 10 Mar 2026 17:36:24 +0100 Subject: [PATCH 1/2] fix(plugins/cloudtrail): Assumed role user from session name, falling back to the identity userName Signed-off-by: Mirko Bonasorte --- plugins/cloudtrail/pkg/cloudtrail/extract.go | 30 +++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/plugins/cloudtrail/pkg/cloudtrail/extract.go b/plugins/cloudtrail/pkg/cloudtrail/extract.go index e48e7268..b5790955 100644 --- a/plugins/cloudtrail/pkg/cloudtrail/extract.go +++ b/plugins/cloudtrail/pkg/cloudtrail/extract.go @@ -121,10 +121,7 @@ func getUser(jdata *fastjson.Value) (bool, string, int, int) { case "AWSService": jun = jdata.Get("userIdentity", "invokedBy") case "AssumedRole": - jun = jdata.Get("userIdentity", "sessionContext", "sessionIssuer", "userName") - if jun == nil { - return true, "AssumedRole", 0, 0 - } + return getUserFromAssumedRole(jdata) case "AWSAccount": return true, "AWSAccount", 0, 0 case "FederatedUser": @@ -140,6 +137,31 @@ func getUser(jdata *fastjson.Value) (bool, string, int, int) { return false, "", 0, 0 } +func getUserFromAssumedRole(jdata *fastjson.Value) (bool, string, int, int) { + arn := jdata.Get("userIdentity", "arn") + if arn != nil { + parts := strings.Split(string(arn.GetStringBytes()), "/") + if len(parts) == 3 { + return true, parts[len(parts)-1], arn.Offset(), arn.Len() + } + } + + principal := jdata.Get("userIdentity", "principalId") + if principal != nil { + parts := strings.Split(string(principal.GetStringBytes()), ":") + if len(parts) == 2 { + return true, parts[0], principal.Offset(), principal.Len() + } + } + + userName := jdata.Get("userIdentity", "sessionContext", "sessionIssuer", "userName") + if userName != nil { + return true, string(userName.GetStringBytes()), userName.Offset(), userName.Len() + } + + return true, "AssumedRole", 0, 0 +} + func getEvtInfo(jdata *fastjson.Value) string { var present bool var evtuser string From eaf10720d4b3dcc51b0ed78f9c2074b184c392f3 Mon Sep 17 00:00:00 2001 From: Mirko Bonasorte Date: Wed, 11 Mar 2026 10:08:10 +0100 Subject: [PATCH 2/2] doc(plugins/cloudtrail): Assumed role user from session name, falling back to the identity userName Signed-off-by: Mirko Bonasorte --- plugins/cloudtrail/README.md | 146 +++++++++---------- plugins/cloudtrail/pkg/cloudtrail/extract.go | 2 +- 2 files changed, 74 insertions(+), 74 deletions(-) diff --git a/plugins/cloudtrail/README.md b/plugins/cloudtrail/README.md index 97d4770e..c3bf8121 100644 --- a/plugins/cloudtrail/README.md +++ b/plugins/cloudtrail/README.md @@ -19,79 +19,79 @@ The event source for cloudtrail events is `aws_cloudtrail`. Here is the current set of supported fields: -| NAME | TYPE | ARG | DESCRIPTION | -|------------------------------------------|----------|------|----------------------------------------------------------------------------------------------------------------------------------------------------------| -| `ct.id` | `string` | None | the unique ID of the cloudtrail event (eventID in the json). | -| `ct.error` | `string` | None | The error code from the event. Will be "" (e.g. the NULL/empty/none value) if there was no error. | -| `ct.errormessage` | `string` | None | The description of an error. Will be "" (e.g. the NULL/empty/none value) if there was no error. | -| `ct.time` | `string` | None | the timestamp of the cloudtrail event (eventTime in the json). | -| `ct.src` | `string` | None | the source of the cloudtrail event (eventSource in the json). | -| `ct.shortsrc` | `string` | None | the source of the cloudtrail event (eventSource in the json, without the '.amazonaws.com' trailer). | -| `ct.name` | `string` | None | the name of the cloudtrail event (eventName in the json). | -| `ct.user` | `string` | None | the user of the cloudtrail event (userIdentity.userName in the json). | -| `ct.user.accountid` | `string` | None | the account id of the user of the cloudtrail event. | -| `ct.user.identitytype` | `string` | None | the kind of user identity (e.g. Root, IAMUser,AWSService, etc.) | -| `ct.user.principalid` | `string` | None | A unique identifier for the user that made the request. | -| `ct.user.arn` | `string` | None | the Amazon Resource Name (ARN) of the user that made the request. | -| `ct.region` | `string` | None | the region of the cloudtrail event (awsRegion in the json). | -| `ct.response.subnetid` | `string` | None | the subnet ID included in the response. | -| `ct.response.reservationid` | `string` | None | the reservation ID included in the response. | -| `ct.response` | `string` | None | All response elements. | -| `ct.request.availabilityzone` | `string` | None | the availability zone included in the request. | -| `ct.request.cluster` | `string` | None | the cluster included in the request. | -| `ct.request.functionname` | `string` | None | the function name included in the request. | -| `ct.request.groupname` | `string` | None | the group name included in the request. | -| `ct.request.host` | `string` | None | the host included in the request | -| `ct.request.name` | `string` | None | the name of the entity being acted on in the request. | -| `ct.request.policy` | `string` | None | the policy included in the request | -| `ct.request.reason` | `string` | None | the reason included in the request. | -| `ct.request.target` | `string` | None | the target included in the request. | -| `ct.request.documentname` | `string` | None | the document name included in the request. | -| `ct.request.serialnumber` | `string` | None | the serial number provided in the request. | -| `ct.request.servicename` | `string` | None | the service name provided in the request. | -| `ct.request.subnetid` | `string` | None | the subnet ID provided in the request. | -| `ct.request.taskdefinition` | `string` | None | the task definition prrovided in the request. | -| `ct.request.username` | `string` | None | the username provided in the request. | -| `ct.request` | `string` | None | All request parameters. | -| `ct.srcip` | `string` | None | the IP address generating the event (sourceIPAddress in the json). | -| `ct.useragent` | `string` | None | the user agent generating the event (userAgent in the json). | -| `ct.info` | `string` | None | summary information about the event. This varies depending on the event type and, for some events, it contains event-specific details. | -| `ct.managementevent` | `string` | None | 'true' if the event is a management event (AwsApiCall, AwsConsoleAction, AwsConsoleSignIn, or AwsServiceEvent), 'false' otherwise. | -| `ct.readonly` | `string` | None | 'true' if the event only reads information (e.g. DescribeInstances), 'false' if the event modifies the state (e.g. RunInstances, CreateLoadBalancer...). | -| `ct.requestid` | `string` | None | The value that identifies the request. | -| `ct.eventtype` | `string` | None | Identifies the type of event that generated the event record. | -| `ct.apiversion` | `string` | None | The API version associated with the AwsApiCall eventType value. | -| `ct.resources` | `string` | None | A list of resources accessed in the event. | -| `ct.recipientaccountid` | `string` | None | The account ID that received this event. | -| `ct.serviceeventdetails` | `string` | None | Identifies the service event, including what triggered the event and the result. | -| `ct.sharedeventid` | `string` | None | GUID generated by CloudTrail to uniquely identify CloudTrail events. | -| `ct.vpcendpointid` | `string` | None | Identifies the VPC endpoint in which requests were made. | -| `ct.eventcategory` | `string` | None | Shows the event category that is used in LookupEvents calls. | -| `ct.addendum.reason` | `string` | None | The reason that the event or some of its contents were missing. | -| `ct.addendum.updatedfields` | `string` | None | The event record fields that are updated by the addendum. | -| `ct.addendum.originalrequestid` | `string` | None | The original unique ID of the request. | -| `ct.addendum.originaleventid` | `string` | None | The original event ID. | -| `ct.sessioncredentialfromconsole` | `string` | None | Shows whether or not an event originated from an AWS Management Console session. | -| `ct.edgedevicedetails` | `string` | None | Information about edge devices that are targets of a request. | -| `ct.tlsdetails.tlsversion` | `string` | None | The TLS version of a request. | -| `ct.tlsdetails.ciphersuite` | `string` | None | The cipher suite (combination of security algorithms used) of a request. | -| `ct.tlsdetails.clientprovidedhostheader` | `string` | None | The client-provided host name used in the service API call. | -| `ct.additionaleventdata` | `string` | None | All additional event data attributes. | -| `s3.uri` | `string` | None | the s3 URI (s3:///). | -| `s3.bucket` | `string` | None | the bucket name for s3 events. | -| `s3.key` | `string` | None | the S3 key name. | -| `s3.bytes` | `uint64` | None | the size of an s3 download or upload, in bytes. | -| `s3.bytes.in` | `uint64` | None | the size of an s3 upload, in bytes. | -| `s3.bytes.out` | `uint64` | None | the size of an s3 download, in bytes. | -| `s3.cnt.get` | `uint64` | None | the number of get operations. This field is 1 for GetObject events, 0 otherwise. | -| `s3.cnt.put` | `uint64` | None | the number of put operations. This field is 1 for PutObject events, 0 otherwise. | -| `s3.cnt.other` | `uint64` | None | the number of non I/O operations. This field is 0 for GetObject and PutObject events, 1 for all the other events. | -| `ec2.name` | `string` | None | the name of the ec2 instances, typically stored in the instance tags. | -| `ec2.imageid` | `string` | None | the ID for the image used to run the ec2 instance in the response. | -| `ecr.repository` | `string` | None | the name of the ecr Repository specified in the request. | -| `ecr.imagetag` | `string` | None | the tag of the image specified in the request. | -| `iam.role` | `string` | None | the IAM role specified in the request. | -| `iam.policy` | `string` | None | the IAM policy specified in the request. | +| NAME | TYPE | ARG | DESCRIPTION | +|------------------------------------------|----------|------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `ct.id` | `string` | None | the unique ID of the cloudtrail event (eventID in the json). | +| `ct.error` | `string` | None | The error code from the event. Will be "" (e.g. the NULL/empty/none value) if there was no error. | +| `ct.errormessage` | `string` | None | The description of an error. Will be "" (e.g. the NULL/empty/none value) if there was no error. | +| `ct.time` | `string` | None | the timestamp of the cloudtrail event (eventTime in the json). | +| `ct.src` | `string` | None | the source of the cloudtrail event (eventSource in the json). | +| `ct.shortsrc` | `string` | None | the source of the cloudtrail event (eventSource in the json, without the '.amazonaws.com' trailer). | +| `ct.name` | `string` | None | the name of the cloudtrail event (eventName in the json). | +| `ct.user` | `string` | None | the user of the cloudtrail event. For IAMUser/Root events, this is userIdentity.userName. For AssumedRole events, this is the session name extracted from userIdentity.arn, falling back to userIdentity.principalId or userIdentity.sessionContext.sessionIssuer.userName. | +| `ct.user.accountid` | `string` | None | the account id of the user of the cloudtrail event. | +| `ct.user.identitytype` | `string` | None | the kind of user identity (e.g. Root, IAMUser,AWSService, etc.) | +| `ct.user.principalid` | `string` | None | A unique identifier for the user that made the request. | +| `ct.user.arn` | `string` | None | the Amazon Resource Name (ARN) of the user that made the request. | +| `ct.region` | `string` | None | the region of the cloudtrail event (awsRegion in the json). | +| `ct.response.subnetid` | `string` | None | the subnet ID included in the response. | +| `ct.response.reservationid` | `string` | None | the reservation ID included in the response. | +| `ct.response` | `string` | None | All response elements. | +| `ct.request.availabilityzone` | `string` | None | the availability zone included in the request. | +| `ct.request.cluster` | `string` | None | the cluster included in the request. | +| `ct.request.functionname` | `string` | None | the function name included in the request. | +| `ct.request.groupname` | `string` | None | the group name included in the request. | +| `ct.request.host` | `string` | None | the host included in the request | +| `ct.request.name` | `string` | None | the name of the entity being acted on in the request. | +| `ct.request.policy` | `string` | None | the policy included in the request | +| `ct.request.reason` | `string` | None | the reason included in the request. | +| `ct.request.target` | `string` | None | the target included in the request. | +| `ct.request.documentname` | `string` | None | the document name included in the request. | +| `ct.request.serialnumber` | `string` | None | the serial number provided in the request. | +| `ct.request.servicename` | `string` | None | the service name provided in the request. | +| `ct.request.subnetid` | `string` | None | the subnet ID provided in the request. | +| `ct.request.taskdefinition` | `string` | None | the task definition prrovided in the request. | +| `ct.request.username` | `string` | None | the username provided in the request. | +| `ct.request` | `string` | None | All request parameters. | +| `ct.srcip` | `string` | None | the IP address generating the event (sourceIPAddress in the json). | +| `ct.useragent` | `string` | None | the user agent generating the event (userAgent in the json). | +| `ct.info` | `string` | None | summary information about the event. This varies depending on the event type and, for some events, it contains event-specific details. | +| `ct.managementevent` | `string` | None | 'true' if the event is a management event (AwsApiCall, AwsConsoleAction, AwsConsoleSignIn, or AwsServiceEvent), 'false' otherwise. | +| `ct.readonly` | `string` | None | 'true' if the event only reads information (e.g. DescribeInstances), 'false' if the event modifies the state (e.g. RunInstances, CreateLoadBalancer...). | +| `ct.requestid` | `string` | None | The value that identifies the request. | +| `ct.eventtype` | `string` | None | Identifies the type of event that generated the event record. | +| `ct.apiversion` | `string` | None | The API version associated with the AwsApiCall eventType value. | +| `ct.resources` | `string` | None | A list of resources accessed in the event. | +| `ct.recipientaccountid` | `string` | None | The account ID that received this event. | +| `ct.serviceeventdetails` | `string` | None | Identifies the service event, including what triggered the event and the result. | +| `ct.sharedeventid` | `string` | None | GUID generated by CloudTrail to uniquely identify CloudTrail events. | +| `ct.vpcendpointid` | `string` | None | Identifies the VPC endpoint in which requests were made. | +| `ct.eventcategory` | `string` | None | Shows the event category that is used in LookupEvents calls. | +| `ct.addendum.reason` | `string` | None | The reason that the event or some of its contents were missing. | +| `ct.addendum.updatedfields` | `string` | None | The event record fields that are updated by the addendum. | +| `ct.addendum.originalrequestid` | `string` | None | The original unique ID of the request. | +| `ct.addendum.originaleventid` | `string` | None | The original event ID. | +| `ct.sessioncredentialfromconsole` | `string` | None | Shows whether or not an event originated from an AWS Management Console session. | +| `ct.edgedevicedetails` | `string` | None | Information about edge devices that are targets of a request. | +| `ct.tlsdetails.tlsversion` | `string` | None | The TLS version of a request. | +| `ct.tlsdetails.ciphersuite` | `string` | None | The cipher suite (combination of security algorithms used) of a request. | +| `ct.tlsdetails.clientprovidedhostheader` | `string` | None | The client-provided host name used in the service API call. | +| `ct.additionaleventdata` | `string` | None | All additional event data attributes. | +| `s3.uri` | `string` | None | the s3 URI (s3:///). | +| `s3.bucket` | `string` | None | the bucket name for s3 events. | +| `s3.key` | `string` | None | the S3 key name. | +| `s3.bytes` | `uint64` | None | the size of an s3 download or upload, in bytes. | +| `s3.bytes.in` | `uint64` | None | the size of an s3 upload, in bytes. | +| `s3.bytes.out` | `uint64` | None | the size of an s3 download, in bytes. | +| `s3.cnt.get` | `uint64` | None | the number of get operations. This field is 1 for GetObject events, 0 otherwise. | +| `s3.cnt.put` | `uint64` | None | the number of put operations. This field is 1 for PutObject events, 0 otherwise. | +| `s3.cnt.other` | `uint64` | None | the number of non I/O operations. This field is 0 for GetObject and PutObject events, 1 for all the other events. | +| `ec2.name` | `string` | None | the name of the ec2 instances, typically stored in the instance tags. | +| `ec2.imageid` | `string` | None | the ID for the image used to run the ec2 instance in the response. | +| `ecr.repository` | `string` | None | the name of the ecr Repository specified in the request. | +| `ecr.imagetag` | `string` | None | the tag of the image specified in the request. | +| `iam.role` | `string` | None | the IAM role specified in the request. | +| `iam.policy` | `string` | None | the IAM policy specified in the request. | ## Handling AWS Authentication diff --git a/plugins/cloudtrail/pkg/cloudtrail/extract.go b/plugins/cloudtrail/pkg/cloudtrail/extract.go index b5790955..f3c9c077 100644 --- a/plugins/cloudtrail/pkg/cloudtrail/extract.go +++ b/plugins/cloudtrail/pkg/cloudtrail/extract.go @@ -38,7 +38,7 @@ var supportedFields = []sdk.FieldEntry{ {Type: "string", Name: "ct.src", Display: "AWS Service", Desc: "the source of the cloudtrail event (eventSource in the json)."}, {Type: "string", Name: "ct.shortsrc", Display: "AWS Service", Desc: "the source of the cloudtrail event (eventSource in the json, without the '.amazonaws.com' trailer)."}, {Type: "string", Name: "ct.name", Display: "Event Name", Desc: "the name of the cloudtrail event (eventName in the json)."}, - {Type: "string", Name: "ct.user", Display: "User Name", Desc: "the user of the cloudtrail event (userIdentity.userName in the json).", Properties: []string{"conversation"}}, + {Type: "string", Name: "ct.user", Display: "User Name", Desc: "the user of the cloudtrail event. For IAMUser/Root events, this is userIdentity.userName. For AssumedRole events, this is the session name extracted from userIdentity.arn, falling back to userIdentity.principalId or userIdentity.sessionContext.sessionIssuer.userName.", Properties: []string{"conversation"}}, {Type: "string", Name: "ct.user.accountid", Display: "User Account ID", Desc: "the account id of the user of the cloudtrail event."}, {Type: "string", Name: "ct.user.identitytype", Display: "User Identity Type", Desc: "the kind of user identity (e.g. Root, IAMUser,AWSService, etc.)"}, {Type: "string", Name: "ct.user.principalid", Display: "User Principal Id", Desc: "A unique identifier for the user that made the request."},