AWS CloudTrail is an AWS service that helps you enable governance, compliance, and operational and risk auditing of your AWS account. Actions taken by a user, role, or an AWS service are recorded as events in CloudTrail.
Visibility into your AWS account activity is a key aspect of security and operational best practices.
You can use CloudTrail to view, search, download, archive, analyze, and respond to account activity across your AWS infrastructure. You can identify who or what took which action, what resources were acted upon, when the event occurred, and other details to help you analyze and respond to activity in your AWS account.
There are many ways to query CloudTrail logs, one can use AWS Athena, third party software, a combination of Glue crawlers and Redshift.
In this post I am going to show some practical examples of querying CloudTrail Logs using the AWS CLI.
Query Examples
The CLI has two different commands for querying the logs, the first is by running a query against CloudTrail and the second is by running a query against CloudWatch Logs.
There are some differences in which the commands operate and how many events are brought back. Both commands allow for pagination by providing a token.
See links provided at the end of this post to read up more on the two methods to query events.
Simple Query
|
|
The above queries are simple queries which look back 30 minutes
into the logs. Notice the format of the date passed to the --start-time
in the two queries.
Both of them should output similar content. The output from these queries is not that easy to read, so I use jq
a lot to view the results.
Let us take a look at another example where we filter and select only certain events.
Query with Filter
|
|
In the above example, I added a lookup-attribute
for CloudTrail lookup-event
query and in the CloudWatch command the filter-pattern
was used to limit results.
I prefer the --filter-pattern
option as I find it easier to use conditions compared to the --lookup-attributes
.
|
|
In the above query I used Not Equal to
expression --filter-pattern '{ $.eventSource != "kms.amazonaws.com" }'
to filter out KMS events.
If you prefer to filter or select using jq
then the following example shows exactly how to do that.
|
|
In the above query, I am using jq select
to filter out events.
query and List Events with counts
aws logs filter-log-events --log-group-name CloudTrail/DefaultLogGroup \
--start-time $(date -v "-30M" +%s000) \
--filter-pattern '{ $.eventSource != "kms.amazonaws.com" }' \
--query 'events[].message' --output text | jq '.eventName' | sort | uniq -c | sort -n
1 "CreateLogStream"
1 "DescribeInstances"
1 "GetAccountPublicAccessBlock"
1 "ListMultiRegionAccessPoints"
7 "AssumeRole"
10 "DescribeEventAggregates"
21 "GetBucketAcl"
105 "FilterLogEvents"
Query to find events with errors
|
|
The above query will only pick events if there is an errorCode in the event.
Some can argue that it is better to filter the query itself rather than use jq
, but I find jq
very useful and more versatile, so I prefer using it.