Skip to content

Commit

Permalink
Add table aws_cloudtrail_lookup_event Closes #1902 (#2047)
Browse files Browse the repository at this point in the history
  • Loading branch information
ParthaI authored Jan 15, 2024
1 parent 84df6ae commit 7bbf9b9
Show file tree
Hide file tree
Showing 3 changed files with 345 additions and 0 deletions.
1 change: 1 addition & 0 deletions aws/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ func Plugin(ctx context.Context) *plugin.Plugin {
"aws_cloudtrail_channel": tableAwsCloudtrailChannel(ctx),
"aws_cloudtrail_event_data_store": tableAwsCloudtrailEventDataStore(ctx),
"aws_cloudtrail_import": tableAwsCloudtrailImport(ctx),
"aws_cloudtrail_lookup_event": tableAwsCloudtrailLookupEvent(ctx),
"aws_cloudtrail_query": tableAwsCloudTrailQuery(ctx),
"aws_cloudtrail_trail": tableAwsCloudtrailTrail(ctx),
"aws_cloudtrail_trail_event": tableAwsCloudtrailTrailEvent(ctx),
Expand Down
219 changes: 219 additions & 0 deletions aws/table_aws_cloudtrail_lookup_event.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
package aws

import (
"context"
"time"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/cloudtrail"
"github.com/aws/aws-sdk-go-v2/service/cloudtrail/types"

cloudtrailv1 "github.com/aws/aws-sdk-go/service/cloudtrail"

"github.com/turbot/steampipe-plugin-sdk/v5/grpc/proto"
"github.com/turbot/steampipe-plugin-sdk/v5/plugin"
"github.com/turbot/steampipe-plugin-sdk/v5/plugin/transform"
)

//// TABLE DEFINITION

func tableAwsCloudtrailLookupEvent(_ context.Context) *plugin.Table {
return &plugin.Table{
Name: "aws_cloudtrail_lookup_event",
Description: "AWS CloudTrail Lookup Event",
List: &plugin.ListConfig{
Hydrate: listCloudtrailLookupEvents,
Tags: map[string]string{"service": "cloudtrail", "action": "LookupEvents"},
IgnoreConfig: &plugin.IgnoreConfig{
ShouldIgnoreErrorFunc: shouldIgnoreErrors([]string{"InvalidLookupAttributesException"}),
},
KeyColumns: plugin.KeyColumnSlice{
{Name: "event_id", Require: plugin.Optional},
{Name: "event_name", Require: plugin.Optional},
{Name: "event_source", Require: plugin.Optional},
{Name: "read_only", Require: plugin.Optional},
{Name: "end_time", Require: plugin.Optional},
{Name: "start_time", Require: plugin.Optional},
{Name: "resource_name", Require: plugin.Optional},
{Name: "resource_type", Require: plugin.Optional},
{Name: "username", Require: plugin.Optional},
{Name: "access_key_id", Require: plugin.Optional},
},
},
GetMatrixItemFunc: SupportedRegionMatrix(cloudtrailv1.EndpointsID),
Columns: awsRegionalColumns([]*plugin.Column{
{
Name: "event_id",
Description: "The CloudTrail ID of the event returned.",
Type: proto.ColumnType_STRING,
},
{
Name: "event_name",
Description: "The name of the event returned.",
Type: proto.ColumnType_STRING,
},
{
Name: "event_source",
Description: "The Amazon Web Services service to which the request was made.",
Type: proto.ColumnType_STRING,
},
{
Name: "read_only",
Description: "Information about whether the event is a write event or a read event.",
Type: proto.ColumnType_STRING,
},
{
Name: "access_key_id",
Description: "The AWS access key ID that was used to sign the request. If the request was made with temporary security credentials, this is the access key ID of the temporary credentials.",
Type: proto.ColumnType_STRING,
},
{
Name: "event_time",
Description: "The date and time of the event returned.",
Type: proto.ColumnType_TIMESTAMP,
},
{
Name: "end_time",
Description: "Specifies that only events that occur before or at the specified time are returned. If the specified end time is before the specified start time, an error is returned.",
Type: proto.ColumnType_TIMESTAMP,
Transform: transform.FromQual("end_time"),
},
{
Name: "start_time",
Description: "Specifies that only events that occur after or at the specified time are returned. If the specified start time is after the specified end time, an error is returned.",
Type: proto.ColumnType_TIMESTAMP,
Transform: transform.FromQual("start_time"),
},
{
Name: "resource_name",
Description: "The name of the resource.",
Type: proto.ColumnType_STRING,
Transform: transform.FromQual("resource_name"),
},
{
Name: "resource_type",
Description: "The resource type.",
Type: proto.ColumnType_STRING,
Transform: transform.FromQual("resource_type"),
},
{
Name: "username",
Description: "A user name or role name of the requester that called the API in the event returned.",
Type: proto.ColumnType_STRING,
},
{
Name: "resources",
Description: "A list of resources referenced by the event returned.",
Type: proto.ColumnType_JSON,
},
{
Name: "cloud_trail_event",
Description: "A JSON string that contains a representation of the event returned.",
Type: proto.ColumnType_JSON,
},

// Steampipe standard columns
{
Name: "title",
Description: resourceInterfaceDescription("title"),
Type: proto.ColumnType_STRING,
Transform: transform.FromField("EventName"),
},
}),
}
}

//// LIST FUNCTION

func listCloudtrailLookupEvents(ctx context.Context, d *plugin.QueryData, _ *plugin.HydrateData) (interface{}, error) {
// Get client
svc, err := CloudTrailClient(ctx, d)
if err != nil {
plugin.Logger(ctx).Info("aws_cloudtrail_lookup_event.listCloudtrailLookupEvents", "client_error", err)
return nil, err
}

input := buildCloudtrailLookupEventFilter(ctx, d.Quals)
maxItems := int32(50)

// Reduce the basic request limit down if the user has only requested a small number of rows
if d.QueryContext.Limit != nil {
limit := int32(*d.QueryContext.Limit)
if limit < maxItems {
maxItems = int32(limit)
}
}
input.MaxResults = &maxItems

pageLeft := true
for pageLeft {
// apply rate limiting
d.WaitForListRateLimit(ctx)

resp, err := svc.LookupEvents(ctx, input)
if err != nil {
plugin.Logger(ctx).Info("aws_cloudtrail_lookup_event.listCloudtrailLookupEvents", "api_error", err)
return nil, err
}

for _, event := range resp.Events {
d.StreamListItem(ctx, event)

// Context may get cancelled due to manual cancellation or if the limit has been reached
if d.RowsRemaining(ctx) == 0 {
return nil, nil
}
}
if resp.NextToken != nil {
input.NextToken = resp.NextToken
} else {
pageLeft = false
}
}

return nil, err
}

//// UTILITY FUNCTION

// Build Cloudtrail Lookup Event list call input filter
func buildCloudtrailLookupEventFilter(ctx context.Context, quals plugin.KeyColumnQualMap) *cloudtrail.LookupEventsInput {

input := &cloudtrail.LookupEventsInput{
MaxResults: aws.Int32(50),
}
attributeKeyMap := map[string]types.LookupAttributeKey{
"event_id": types.LookupAttributeKeyEventId,
"event_name": types.LookupAttributeKeyEventName,
"read_only": types.LookupAttributeKeyReadOnly,
"username": types.LookupAttributeKeyUsername,
"event_source": types.LookupAttributeKeyEventSource,
"resource_name": types.LookupAttributeKeyResourceName,
"resource_type": types.LookupAttributeKeyResourceType,
"access_key_id": types.LookupAttributeKeyAccessKeyId,
}

var lookupAttributes []types.LookupAttribute
for columnName, attributeKey := range attributeKeyMap {
if quals[columnName] != nil {
value := getQualsValueByColumn(quals, columnName, "string")
lookupAttribute := types.LookupAttribute{
AttributeKey: attributeKey,
AttributeValue: aws.String(value.(string)),
}
lookupAttributes = append(lookupAttributes, lookupAttribute)
}
}
input.LookupAttributes = lookupAttributes

if quals["start_time"] != nil {
value := getQualsValueByColumn(quals, "start_time", "time")
input.StartTime = aws.Time(value.(time.Time))
}
if quals["end_time"] != nil {
value := getQualsValueByColumn(quals, "end_time", "time")
input.StartTime = aws.Time(value.(time.Time))
}

return input
}
125 changes: 125 additions & 0 deletions docs/tables/aws_cloudtrail_lookup_event.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
---
title: "Steampipe Table: aws_cloudtrail_lookup_event - Query AWS CloudTrail Lookup Events using SQL"
description: "Allows users to query AWS CloudTrail Lookup Events, providing information about each trail event within AWS CloudTrail. The table can be used to retrieve details such as the event time, event name, resources involved, and much more."
---

# Table: aws_cloudtrail_lookup_event - Query AWS CloudTrail Lookup Events using SQL

AWS CloudTrail Lookup Events is a feature within AWS CloudTrail, a service that provides a record of actions taken by a user, role, or an AWS service in AWS. This feature specifically allows you to look up and retrieve information about the events recorded by CloudTrail.

## Table Usage Guide

The `aws_cloudtrail_lookup_event` table in Steampipe provides you with information about each trail event within AWS CloudTrail. This table allows you, as a DevOps engineer, to query event-specific details, including event time, event name, resources involved, and more. You can utilize this table to gather insights on trail events, such as event source, user identity, and request parameters. The schema outlines the various attributes of the CloudTrail event for you, including the event ID, event version, read only, and associated tags.

**Important notes:**
- For improved performance, it is advised that you use the optional qual `start_time` and `end_time` to limit the result set to a specific time period.
- This table supports optional quals. Queries with optional quals are optimised to use CloudWatch filters. Optional quals are supported for the following columns:
- `read_only`
- `event_id`
- `event_name`
- `event_source`
- `resource_name`
- `resource_type`
- `access_key_id`
- `start_time`
- `end_time`
- `username`

## Examples

### List events that occurred over the last five minutes
This query is useful for gaining insights into recent activity within your AWS environment. It provides a quick overview of the events that have taken place in the last five minutes, which can be particularly useful for immediate incident response or real-time monitoring.

```sql+postgres
select
event_name,
event_source,
event_time,
username,
jsonb_pretty(cloud_trail_event) as cloud_trail_event
from
aws_cloudtrail_lookup_event
where
start_time = now()
and end_time = now() - interval '5 minutes';
```

```sql+sqlite
select
event_name,
event_source,
event_time,
username,
json(cloud_trail_event) as cloud_trail_event
from
aws_cloudtrail_lookup_event
where
start_time = datetime('now')
and end_time = datetime('now', '-5 minutes');
```

### List all action events, i.e., not ReadOnly that occurred over the last hour
Explore which action events have occurred in the last hour on AWS Cloudtrail. This is useful for identifying recent activities that have potentially altered your system.

```sql+postgres
select
event_name,
event_source,
event_time,
username,
jsonb_pretty(cloud_trail_event) as cloud_trail_event
from
aws_cloudtrail_lookup_event
where
start_time = now()
and end_time = now() - interval '1 hour'
and read_only = 'true'
order by
event_time asc;
```

```sql+sqlite
select
event_name,
event_source,
event_time,
username,
json(cloud_trail_event) as cloud_trail_event
from
aws_cloudtrail_lookup_event
where
start_time = datetime('now')
and end_time = datetime('now', '-1 hour')
and read_only = 'true'
order by
event_time asc;
```

### List events for a specific service (IAM) that occurred over the last hour
This query allows users to monitor recent activity for a specific service, in this case, AWS's Identity and Access Management (IAM). It is particularly useful for security audits, as it provides a chronological overview of events, including who initiated them and what actions were taken, over the last hour.

```sql+postgres
select
event_name,
event_source,
event_time,
jsonb_pretty(cloud_trail_event) as cloud_trail_event
from
aws_cloudtrail_lookup_event
where
and event_source = 'iam.amazonaws.com'
and event_time >= now() - interval '1 hour';
```

```sql+sqlite
select
event_name,
event_source,
event_time,
json(cloud_trail_event) as cloud_trail_event
from
aws_cloudtrail_lookup_event
where
and event_source = 'iam.amazonaws.com'
and event_time >= datetime('now', '-1 hour');
```

0 comments on commit 7bbf9b9

Please sign in to comment.