Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions tuts/094-aws-cloudtrail-gs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# CloudTrail: Enable logging and look up events

Create a CloudTrail trail that logs API activity to an S3 bucket, look up recent events, and clean up.

## Source

https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-tutorial.html

## Use case

- ID: cloudtrail/getting-started
- Phase: create
- Complexity: beginner
- Core actions: cloudtrail:CreateTrail, cloudtrail:StartLogging, cloudtrail:LookupEvents

## What it does

1. Creates an S3 bucket for trail logs
2. Sets the bucket policy to allow CloudTrail writes
3. Creates a trail pointing to the bucket
4. Starts logging
5. Looks up recent API events
6. Describes the trail configuration

## Running

```bash
bash aws-cloudtrail-gs.sh
```

To auto-run with cleanup:

```bash
echo 'y' | bash aws-cloudtrail-gs.sh
```

## Resources created

- CloudTrail trail
- S3 bucket (with CloudTrail bucket policy)

## Estimated time

- Run: ~10 seconds

## Cost

S3 storage only. CloudTrail delivers management event logs to S3 at no charge for the first trail. S3 storage costs apply for the log files.

## Related docs

- [Getting started with CloudTrail tutorials](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-tutorial.html)
- [Creating a trail](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-create-and-update-a-trail.html)
- [Amazon S3 bucket policy for CloudTrail](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/create-s3-bucket-policy-for-cloudtrail.html)
- [Looking up events with LookupEvents](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/view-cloudtrail-events-cli.html)
- [CloudTrail pricing](https://aws.amazon.com/cloudtrail/pricing/)
8 changes: 8 additions & 0 deletions tuts/094-aws-cloudtrail-gs/REVISION-HISTORY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Revision History: 094-aws-cloudtrail-gs

## Shell (CLI script)

### 2026-04-14 v1 published
- Type: functional
- Initial version

117 changes: 117 additions & 0 deletions tuts/094-aws-cloudtrail-gs/aws-cloudtrail-gs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# Enable CloudTrail logging and look up recent events

This tutorial shows you how to create an AWS CloudTrail trail that logs API activity to an S3 bucket, look up recent events, and clean up.

## Prerequisites

- AWS CLI configured with credentials and a default region
- Permissions for `cloudtrail:CreateTrail`, `cloudtrail:StartLogging`, `cloudtrail:LookupEvents`, `cloudtrail:DescribeTrails`, `cloudtrail:DeleteTrail`, `s3:CreateBucket`, `s3:PutBucketPolicy`, `s3:DeleteBucket`

## Step 1: Create an S3 bucket for trail logs

CloudTrail delivers log files to an S3 bucket. Create a bucket with a unique name:

```bash
BUCKET_NAME="cloudtrail-tut-$(openssl rand -hex 4)-$(aws sts get-caller-identity --query Account --output text)"

aws s3api create-bucket --bucket "$BUCKET_NAME" \
--create-bucket-configuration LocationConstraint="$AWS_DEFAULT_REGION"
```

For `us-east-1`, omit the `--create-bucket-configuration` parameter.

## Step 2: Set the bucket policy for CloudTrail

CloudTrail requires a bucket policy that grants it permission to check the bucket ACL and write log files:

```bash
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)

cat > bucket-policy.json << EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AWSCloudTrailAclCheck",
"Effect": "Allow",
"Principal": {"Service": "cloudtrail.amazonaws.com"},
"Action": "s3:GetBucketAcl",
"Resource": "arn:aws:s3:::$BUCKET_NAME"
},
{
"Sid": "AWSCloudTrailWrite",
"Effect": "Allow",
"Principal": {"Service": "cloudtrail.amazonaws.com"},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::$BUCKET_NAME/AWSLogs/$ACCOUNT_ID/*",
"Condition": {"StringEquals": {"s3:x-amz-acl": "bucket-owner-full-control"}}
}
]
}
EOF

aws s3api put-bucket-policy --bucket "$BUCKET_NAME" --policy file://bucket-policy.json
```

The first statement lets CloudTrail verify bucket ownership. The second lets it write log files under the `AWSLogs/` prefix.

## Step 3: Create a trail

Create a trail that points to your S3 bucket:

```bash
TRAIL_NAME="tutorial-trail-$(openssl rand -hex 4)"

aws cloudtrail create-trail --name "$TRAIL_NAME" --s3-bucket-name "$BUCKET_NAME" \
--query '{Trail:Name,Bucket:S3BucketName}' --output table
```

The trail is created but not yet logging. By default it records management events in all Regions.

## Step 4: Start logging

```bash
aws cloudtrail start-logging --name "$TRAIL_NAME"
```

CloudTrail begins recording API activity and delivering log files to the S3 bucket within about 15 minutes.

## Step 5: Look up recent events

Use `lookup-events` to search the last 10 minutes of API activity:

```bash
START_TIME=$(date -u -d '10 minutes ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null \
|| date -u -v-10M +%Y-%m-%dT%H:%M:%SZ)

aws cloudtrail lookup-events \
--start-time "$START_TIME" \
--max-results 5 \
--query 'Events[].{Time:EventTime,Name:EventName,User:Username}' --output table
```

This returns events from the Event history, which is available regardless of whether a trail exists. The trail you created delivers the same events (plus more detail) to S3.

## Step 6: Describe the trail

```bash
aws cloudtrail describe-trails --trail-name-list "$TRAIL_NAME" \
--query 'trailList[0].{Name:Name,Bucket:S3BucketName,IsMultiRegion:IsMultiRegionTrail}' \
--output table
```

## Cleanup

Delete the trail, then empty and delete the S3 bucket:

```bash
aws cloudtrail delete-trail --name "$TRAIL_NAME"
aws s3 rm "s3://$BUCKET_NAME" --recursive --quiet
aws s3 rb "s3://$BUCKET_NAME"
```

The script automates all steps including cleanup. Run it with:

```bash
bash aws-cloudtrail-gs.sh
```
110 changes: 110 additions & 0 deletions tuts/094-aws-cloudtrail-gs/aws-cloudtrail-gs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#!/bin/bash
# Tutorial: Enable CloudTrail logging and look up recent events
# Source: https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-tutorial.html

WORK_DIR=$(mktemp -d)
LOG_FILE="$WORK_DIR/cloudtrail-$(date +%Y%m%d-%H%M%S).log"
exec > >(tee -a "$LOG_FILE") 2>&1

REGION=${AWS_DEFAULT_REGION:-${AWS_REGION:-$(aws configure get region 2>/dev/null)}}
if [ -z "$REGION" ]; then
echo "ERROR: No AWS region configured. Set one with: export AWS_DEFAULT_REGION=us-east-1"
exit 1
fi
export AWS_DEFAULT_REGION="$REGION"
ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text)
echo "Region: $REGION"
echo "Account: $ACCOUNT_ID"

RANDOM_ID=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 8 | head -n 1)
TRAIL_NAME="tutorial-trail-${RANDOM_ID}"
BUCKET_NAME="cloudtrail-tut-${RANDOM_ID}-${ACCOUNT_ID}"

handle_error() { echo "ERROR on line $1"; trap - ERR; cleanup; exit 1; }
trap 'handle_error $LINENO' ERR

cleanup() {
echo ""
echo "Cleaning up resources..."
aws cloudtrail delete-trail --name "$TRAIL_NAME" 2>/dev/null && echo " Deleted trail $TRAIL_NAME"
# Empty and delete the bucket
if aws s3 ls "s3://$BUCKET_NAME" > /dev/null 2>&1; then
aws s3 rm "s3://$BUCKET_NAME" --recursive --quiet 2>/dev/null
aws s3 rb "s3://$BUCKET_NAME" 2>/dev/null && echo " Deleted bucket $BUCKET_NAME"
fi
rm -rf "$WORK_DIR"
echo "Cleanup complete."
}

# Step 1: Create S3 bucket for trail logs
echo "Step 1: Creating S3 bucket for trail logs: $BUCKET_NAME"
if [ "$REGION" = "us-east-1" ]; then
aws s3api create-bucket --bucket "$BUCKET_NAME" > /dev/null
else
aws s3api create-bucket --bucket "$BUCKET_NAME" \
--create-bucket-configuration LocationConstraint="$REGION" > /dev/null
fi

# Step 2: Set bucket policy to allow CloudTrail writes
echo "Step 2: Setting bucket policy for CloudTrail"
cat > "$WORK_DIR/bucket-policy.json" << EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AWSCloudTrailAclCheck",
"Effect": "Allow",
"Principal": {"Service": "cloudtrail.amazonaws.com"},
"Action": "s3:GetBucketAcl",
"Resource": "arn:aws:s3:::$BUCKET_NAME"
},
{
"Sid": "AWSCloudTrailWrite",
"Effect": "Allow",
"Principal": {"Service": "cloudtrail.amazonaws.com"},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::$BUCKET_NAME/AWSLogs/$ACCOUNT_ID/*",
"Condition": {"StringEquals": {"s3:x-amz-acl": "bucket-owner-full-control"}}
}
]
}
EOF
aws s3api put-bucket-policy --bucket "$BUCKET_NAME" --policy "file://$WORK_DIR/bucket-policy.json"
echo " Bucket policy applied"

# Step 3: Create a trail
echo "Step 3: Creating trail: $TRAIL_NAME"
aws cloudtrail create-trail --name "$TRAIL_NAME" --s3-bucket-name "$BUCKET_NAME" \
--query '{Trail:Name,Bucket:S3BucketName}' --output table

# Step 4: Start logging
echo "Step 4: Starting logging"
aws cloudtrail start-logging --name "$TRAIL_NAME"
echo " Logging started"

# Step 5: Look up recent events
echo "Step 5: Looking up recent API events (last 10 minutes)"
START_TIME=$(date -u -d '10 minutes ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-10M +%Y-%m-%dT%H:%M:%SZ)
aws cloudtrail lookup-events \
--start-time "$START_TIME" \
--max-results 5 \
--query 'Events[].{Time:EventTime,Name:EventName,User:Username}' --output table

# Step 6: Describe the trail
echo "Step 6: Describing the trail"
aws cloudtrail describe-trails --trail-name-list "$TRAIL_NAME" \
--query 'trailList[0].{Name:Name,Bucket:S3BucketName,IsMultiRegion:IsMultiRegionTrail,IsLogging:HasCustomEventSelectors}' --output table

echo ""
echo "Tutorial complete."
echo "Do you want to clean up all resources? (y/n): "
read -r CHOICE
if [[ "$CHOICE" =~ ^[Yy]$ ]]; then
cleanup
else
echo "Resources left running. The trail logs API activity to S3."
echo "Manual cleanup:"
echo " aws cloudtrail delete-trail --name $TRAIL_NAME"
echo " aws s3 rm s3://$BUCKET_NAME --recursive"
echo " aws s3 rb s3://$BUCKET_NAME"
fi
55 changes: 55 additions & 0 deletions tuts/099-amazon-cloudwatch-logs-gs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# CloudWatch Logs: Create log groups and query logs

## Source

https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/WhatIsCloudWatchLogs.html

## Use case

- **ID**: cloudwatch-logs/getting-started
- **Level**: beginner
- **Core actions**: `logs:CreateLogGroup`, `logs:PutLogEvents`, `logs:FilterLogEvents`, `logs:StartQuery`

## Steps

1. Create a log group
2. Set retention to 7 days
3. Create a log stream
4. Put 5 log events (INFO/WARN/ERROR)
5. Get log events
6. Filter for ERROR and WARN
7. Run a Logs Insights query

## Resources created

| Resource | Type |
|----------|------|
| `/tutorials/cloudwatch-logs-gs` | Log group |

## Cost

Negligible for 5 log events. All resources removed during cleanup.

## Duration

~14 seconds

## Related docs

- [What is Amazon CloudWatch Logs?](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/WhatIsCloudWatchLogs.html)
- [CloudWatch Logs Insights query syntax](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CWL_QuerySyntax.html)
- [Filter and pattern syntax](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/FilterAndPatternSyntax.html)

---

## Appendix

| Field | Value |
|-------|-------|
| Date | 2026-04-14 |
| Script lines | 91 |
| Exit code | 0 |
| Runtime | 14s |
| Steps | 7 |
| Issues | None |
| Version | v1 |
8 changes: 8 additions & 0 deletions tuts/099-amazon-cloudwatch-logs-gs/REVISION-HISTORY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Revision History: 099-amazon-cloudwatch-logs-gs

## Shell (CLI script)

### 2026-04-14 v1 published
- Type: functional
- Initial version

Loading
Loading