Collect AWS IAM logs
This document explains how to ingest AWS IAM logs to Google Security Operations. The parser transforms raw JSON formatted logs into a structured Unified Data Model (UDM). It extracts relevant fields like user details, role information, permissions, and timestamps, mapping them to corresponding UDM fields for consistent security analysis.
Before you begin
- Ensure that you have a Google SecOps instance.
- Ensure that you have privileged access to AWS.
Configure AWS IAM and S3
- Create an Amazon S3 bucket following this user guide: Creating a bucket.
- Save the bucket Name and Region for later use.
- Create a user following this user guide: Creating an IAM user.
- Select the created User.
- Select the Security credentials tab.
- Click Create Access Key in the Access Keys section.
- Select Third-party service as the Use case.
- Click Next.
- Optional: add a description tag.
- Click Create access key.
- Click Download CSV file to save the Access Key and Secret Access Key for later use.
- Click Done.
- Select the Permissions tab.
- Click Add permissions in the Permissions policies section.
- Select Add permissions.
- Select Attach policies directly
- Search for and select the AmazonS3FullAccess policy.
- Click Next.
- Click Add permissions.
Configure CloudTrail to capture IAM logs
- Sign in to the AWS Management Console.
- In the search bar, type and select CloudTrail from the services list.
- Click Create trail.
- Provide a Trail name; for example, IAMActivityTrail.- Apply trail to all regions: select Yes to capture activities across all regions.
- Storage location: select the S3 bucket created earlier or create a new one.
- S3 Bucket: enter a name for the S3 bucket; for example, iam-logs-bucket.
- Select Create a new IAM role (if not created earlier).
- Management events: select Read and Write to capture both read and write events on IAM resources.
- Data events: enable S3 and Lambda data events.
 
- Click Create to create the trail.
Configure CloudTrail to Export Logs to S3
- Go to Services > S3.
- Select the S3 bucket where CloudTrail logs are stored; for example, iam-logs-bucket.
- Ensure that CloudTrail has the right permissions to write logs to the bucket.
- Add the following policy if it's not already present: - { "Version": "2012-10-17", "Statement": [ { "Sid": "CloudTrailS3Access", "Effect": "Allow", "Principal": { "Service": "cloudtrail.amazonaws.com" }, "Action": "s3:PutObject", "Resource": "arn:aws:s3:::your-bucket-name/AWSLogs/*" } ] }
- Enable Versioning on the S3 bucket to ensure that logs are stored with multiple versions. 
- Go to Properties > Bucket Versioning > Enable. 
Optional: Configure Lambda for real-time export
- Go to the AWS Lambda Console.
- Click Create function.
- Select Author from Scratch.
- Set the function name as ExportIAMLogsToS3.
- Select a Python 3.x runtime.
- Assign an IAM Role to the function that has permissions to: - { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "logs:GetLogEvents", "logs:FilterLogEvents", "logs:DescribeLogGroups", "logs:DescribeLogStreams" ], "Resource": "*" }, { "Effect": "Allow", "Action": [ "s3:PutObject" ], "Resource": "arn:aws:s3:::your-bucket-name/*" } ] }
- Use the following Python code to fetch IAM logs and upload them to S3: - import boto3 import gzip from io import BytesIO s3 = boto3.client('s3') logs = boto3.client('logs') def lambda_handler(event, context): log_group = event['logGroup'] log_stream = event['logStream'] log_events = logs.get_log_events( logGroupName=log_group, logStreamName=log_stream, startFromHead=True ) log_data = "\n".join([event['message'] for event in log_events['events']]) # Compress and upload to S3 compressed_data = gzip.compress(log_data.encode('utf-8')) s3.put_object( Bucket='your-s3-bucket-name', Key='iam-logs/{log_stream}.gz', Body=compressed_data )
- Replace your-s3-bucket-namewith your actual bucket name.
Configure Lambda Trigger for CloudWatch Logs
- In the Lambda Console, go to Designer.
- Choose Add Trigger > CloudWatch Logs.
- Select the CloudWatch Logs log group associated with your IAM logs; for example, /aws/cloudtrail/.
- Click Add.
Set up feeds
There are two different entry points to set up feeds in the Google SecOps platform:
- SIEM Settings > Feeds > Add New Feed
- Content Hub > Content Packs > Get Started
How to set up the AWS IAM feed
- Click the Amazon Cloud Platform pack.
- Locate the AWS IAM log type.
- Specify the values in the following fields. - Source Type: Third party API
- Username: Username to authenticate with
- Secret: Secret to authenticate with
 - Advanced options - Feed Name: A prepopulated value that identifies the feed.
- Asset Namespace: Namespace associated with the feed.
- Ingestion Labels: Labels applied to all events from this feed.
 
- Click Create feed. 
For more information about configuring multiple feeds for different log types within this product family, see Configure feeds by product.
UDM Mapping Table
| Log Field | UDM Mapping | Logic | 
|---|---|---|
| Arn | entity.entity.resource.name | Directly mapped from the Arnfield for USER and RESOURCE entity types. For GROUP entity type, it's mapped fromGroup.Arn. | 
| AssumeRolePolicyDocument | entity.entity.resource.attribute.permissions.name | Directly mapped from the AssumeRolePolicyDocumentfield, but only for RESOURCE entity type. | 
| CreateDate | entity.entity.user.attribute.creation_time | Directly mapped from the CreateDatefield and converted to Chronicle's timestamp format for USER entity type. | 
| CreateDate | entity.entity.resource.attribute.creation_time | Directly mapped from the CreateDatefield and converted to Chronicle's timestamp format for RESOURCE entity type. | 
| Group.Arn | entity.entity.resource.name | Directly mapped from the Group.Arnfield for GROUP entity type. | 
| Group.CreateDate | entity.entity.group.attribute.creation_time | Directly mapped from the Group.CreateDatefield and converted to Chronicle's timestamp format. | 
| Group.GroupID | entity.entity.group.product_object_id | Directly mapped from the Group.GroupIDfield. | 
| Group.GroupName | entity.entity.group.group_display_name | Directly mapped from the Group.GroupNamefield. | 
| Group.GroupName | entity.entity.group.email_addresses | Directly mapped from the Group.GroupNamefield. | 
| Group.Path | entity.entity.group.attribute.labels.value | Directly mapped from the Group.Pathfield, the key is hardcoded topath | 
| IsTruncated | entity.entity.group.attribute.labels.value | Directly mapped from the IsTruncatedfield and converted to string, the key is hardcoded tois_truncated | 
| Marker | entity.entity.group.attribute.labels.value | Directly mapped from the Markerfield, the key is hardcoded tomarker | 
| PasswordLastUsed | entity.entity.user.last_login_time | Directly mapped from the PasswordLastUsedfield and converted to Chronicle's timestamp format. | 
| Path | entity.entity.user.attribute.labels.value | Directly mapped from the Pathfield for USER entity type, the key is hardcoded topath. | 
| Path | entity.entity.resource.attribute.labels.value | Directly mapped from the Pathfield for RESOURCE entity type, the key is hardcoded topath. | 
| PermissionsBoundary.PermissionsBoundaryArn | entity.entity.resource.attribute.labels.value | Directly mapped from the PermissionsBoundary.PermissionsBoundaryArnfield, the key is hardcoded topermissions_boundary_arn. | 
| PermissionsBoundary.PermissionsBoundaryType | entity.entity.resource.attribute.labels.value | Directly mapped from the PermissionsBoundary.PermissionsBoundaryTypefield, the key is hardcoded topermissions_boundary_type. | 
| RoleID | entity.entity.resource.product_object_id | Directly mapped from the RoleIDfield. | 
| RoleLastUsed.LastUsedDate | entity.entity.resource.attribute.labels.value | Directly mapped from the RoleLastUsed.LastUsedDatefield, the key is hardcoded torole_last_used_date. | 
| RoleLastUsed.Region | entity.entity.location.name | Directly mapped from the RoleLastUsed.Regionfield. | 
| RoleName | entity.entity.resource.attribute.roles.name | Directly mapped from the RoleNamefield. | 
| Tags.Key | entity.entity.user.attribute.labels.key | Used as the key for the labelsfield within the user attribute. | 
| Tags.Value | entity.entity.user.attribute.labels.value | Used as the value for the labelsfield within the user attribute. | 
| UserID | entity.entity.user.product_object_id | Directly mapped from the UserIDfield. | 
| UserName | entity.entity.user.userid | Directly mapped from the UserNamefield. | 
| Users.Arn | relations.entity.resource.name | Directly mapped from the Users.Arnfield within the user relation. | 
| Users.CreateDate | relations.entity.user.attribute.creation_time | Directly mapped from the Users.CreateDatefield within the user relation and converted to Chronicle's timestamp format. | 
| Users.PasswordLastUsed | relations.entity.user.last_login_time | Directly mapped from the Users.PasswordLastUsedfield within the user relation and converted to Chronicle's timestamp format. | 
| Users.Path | relations.entity.user.attribute.labels.value | Directly mapped from the Users.Pathfield within the user relation, the key is hardcoded topath. | 
| Users.PermissionsBoundary.PermissionsBoundaryArn | relations.entity.resource.attribute.labels.value | Directly mapped from the Users.PermissionsBoundary.PermissionsBoundaryArnfield within the user relation, the key is hardcoded topermissions_boundary_arn. | 
| Users.PermissionsBoundary.PermissionsBoundaryType | relations.entity.resource.attribute.labels.value | Directly mapped from the Users.PermissionsBoundary.PermissionsBoundaryTypefield within the user relation, the key is hardcoded topermissions_boundary_type. | 
| Users.UserID | relations.entity.user.product_object_id | Directly mapped from the Users.UserIDfield within the user relation. | 
| Users.UserName | relations.entity.user.userid | Directly mapped from the Users.UserNamefield within the user relation. | 
| N/A | entity.metadata.collected_timestamp | Populated with the event timestamp from the raw log. | 
| N/A | entity.metadata.vendor_name | Hardcoded to AWS. | 
| N/A | entity.metadata.product_name | Hardcoded to AWS IAM. | 
| N/A | entity.metadata.entity_type | Determined based on the presence of specific fields: USER if UserIDexists, RESOURCE ifRoleNameexists, and GROUP ifGroup.GroupNameexists. | 
| N/A | entity.entity.resource.resource_subtype | Set to Userfor USER and GROUP entity types. | 
| N/A | entity.entity.resource.resource_type | Set to ACCESS_POLICYfor RESOURCE entity type. | 
| N/A | entity.entity.resource.attribute.cloud.environment | Hardcoded to AMAZON_WEB_SERVICES. | 
| N/A | relations.entity_type | Hardcoded to USERfor user relations within a group. | 
| N/A | relations.relationship | Hardcoded to MEMBERfor user relations within a group. | 
| N/A | relations.direction | Hardcoded to UNIDIRECTIONALfor user relations within a group. | 
| N/A | relations.entity.resource.resource_subtype | Hardcoded to Userfor user relations within a group. | 
Need more help? Get answers from Community members and Google SecOps professionals.