Collect AWS Lambda Function logs
This document explains how to ingest AWS Lambda Function logs to Google Security Operations using Amazon S3.
AWS Lambda is a serverless compute service that runs your code in response to events and automatically manages the underlying compute resources. Lambda automatically sends all function logs (platform logs, extension logs, and application output) to Amazon CloudWatch Logs, creating a log group per function. This integration uses Amazon Data Firehose to stream Lambda log events from CloudWatch Logs to an S3 bucket, which Google SecOps then ingests using an Amazon S3 V2 feed.
Before you begin
Make sure you have the following prerequisites:
- A Google SecOps instance
- Privileged access to the AWS Management Consolewith permissions to manage:
- AWS Lambda(functions, logging configuration)
- Amazon CloudWatch Logs(log groups, subscription filters)
- Amazon Data Firehose(delivery streams)
- Amazon S3(buckets)
- AWS IAM(roles, policies, users)
Verify the CloudWatch Logs log group for your Lambda function
-
AWS Lambda automatically creates a CloudWatch Logs log group for each function when it is first invoked. The default log group naming convention is:
/aws/lambda/<function-name>
To verify:
- In the AWS Console, go to CloudWatch > Logs > Log groups.
- Search for
/aws/lambda/. -
Confirm that a log group exists for each Lambda function whose logs you want to ingest.
Configure an AWS S3 bucket
- Create an Amazon S3 bucketfollowing this user guide: Creating a bucket .
- Save the bucket Nameand Regionfor future reference (for example,
lambda-logs-to-secops).
Configure an IAM role for Amazon Data Firehose
Amazon Data Firehose requires an IAM role to write logs to your S3 bucket.
Create the IAM policy
- In the AWS Console, go to IAM > Policies > Create policy.
- Select the JSONtab.
-
Paste the following policy (replace
lambda-logs-to-secopswith your actual bucket name):{ "Version" : "2012-10-17" , "Statement" : [ { "Sid" : "S3Delivery" , "Effect" : "Allow" , "Action" : [ "s3:AbortMultipartUpload" , "s3:GetBucketLocation" , "s3:GetObject" , "s3:ListBucket" , "s3:ListBucketMultipartUploads" , "s3:PutObject" ], "Resource" : [ "arn:aws:s3:::lambda-logs-to-secops" , "arn:aws:s3:::lambda-logs-to-secops/*" ] }, { "Sid" : "CloudWatchLogging" , "Effect" : "Allow" , "Action" : [ "logs:PutLogEvents" ], "Resource" : "arn:aws:logs:*:*:log-group:/aws/kinesisfirehose/lambda-logs-to-secops:log-stream:*" } ] } -
Click Next.
-
In the Policy namefield, enter
LambdaLogsFirehoseS3Policy. -
Click Create policy.
Create the IAM role
- Go to IAM > Roles > Create role.
- Select Custom trust policy.
-
Paste the following trust policy:
{ "Version" : "2012-10-17" , "Statement" : [ { "Effect" : "Allow" , "Principal" : { "Service" : "firehose.amazonaws.com" }, "Action" : "sts:AssumeRole" } ] } -
Click Next.
-
Search for and select LambdaLogsFirehoseS3Policy.
-
Click Next.
-
In the Role namefield, enter
LambdaLogsFirehoseToS3Role. -
Click Create role.
Create the Amazon Data Firehose stream
- Open the Kinesis consoleat https://console.aws.amazon.com/kinesis .
- In the navigation pane, select Amazon Data Firehose.
- Click Create Firehose stream.
- Under Choose source and destination, provide the following configuration:
- Source: Select Direct PUT.
- Destination: Select Amazon S3.
- In the Firehose stream namefield, enter
lambda-logs-to-secops. -
Under Transform records, in the Decompress source records from Amazon CloudWatch Logssection:
- Select Turn on decompression.
- Do notselect Turn on message extraction.
-
Under Destination settings:
- S3 bucket: Select the S3 bucket
lambda-logs-to-secops. - S3 bucket prefix(optional): Enter
lambda-logs/. - S3 bucket error output prefix(optional): Enter
firehose-errors/.
- S3 bucket: Select the S3 bucket
-
Under Buffer hints:
- Buffer size:
5MiB (default). - Buffer interval:
300seconds (default).
- Buffer size:
-
Under Advanced settings:
- Server-side encryption: Optional. Enable if encryption is required.
- Error logging: Select Enabled(recommended).
- Permissions: Select Choose existing IAM role, then select
LambdaLogsFirehoseToS3Role.
-
Click Create Firehose stream.
-
Wait for the stream Statusto show Active.
Configure an IAM role for CloudWatch Logs
CloudWatch Logs requires an IAM role to send log data to the Firehose stream.
Create the IAM policy
- Go to IAM > Policies > Create policy.
- Select the JSONtab.
-
Paste the following policy (replace
<region>and<account-id>with your AWS region and account ID):{ "Version" : "2012-10-17" , "Statement" : [ { "Effect" : "Allow" , "Action" : [ "firehose:PutRecord" , "firehose:PutRecordBatch" ], "Resource" : "arn:aws:firehose:<region>:<account-id>:deliverystream/lambda-logs-to-secops" } ] } -
Click Next.
-
In the Policy namefield, enter
LambdaLogsCWLtoFirehosePolicy. -
Click Create policy.
Create the IAM role
- Go to IAM > Roles > Create role.
- Select Custom trust policy.
-
Paste the following trust policy (replace
<region>with your AWS region):{ "Version" : "2012-10-17" , "Statement" : [ { "Effect" : "Allow" , "Principal" : { "Service" : "logs.<region>.amazonaws.com" }, "Action" : "sts:AssumeRole" } ] } -
Click Next.
-
Search for and select LambdaLogsCWLtoFirehosePolicy.
-
Click Next.
-
In the Role namefield, enter
LambdaLogsCWLtoFirehoseRole. -
Click Create role.
Create a CloudWatch Logs subscription filter
- In the AWS Console, go to CloudWatch > Logs > Log groups.
- Select the log group
/aws/lambda/<function-name>. - Select the Subscription filterstab.
- Click Create > Create Amazon Data Firehose subscription filter.
- Provide the following configuration details:
- Destination: Select the Firehose stream
lambda-logs-to-secops. - Grant permission: Select the role
LambdaLogsCWLtoFirehoseRole. - Subscription filter name: Enter a descriptive name (for example,
lambda-logs-to-secops-filter). - Log format: Select Other.
- Subscription filter pattern: Leave empty to send all Lambda function log events.
- Destination: Select the Firehose stream
-
Click Start streaming.
Configure an IAM user for Google SecOps
Google SecOps needs an IAM user with access to the S3 bucket to ingest the delivered logs.
- Create a Userfollowing this user guide: Creating an IAM user .
- Select the created User.
- Select Security credentialstab.
- Click Create Access Keyin section Access Keys.
- Select Third-party serviceas Use case.
- Click Next.
- Optional: Add description tag.
- Click Create access key.
- Click Download .csv fileto save the Access Keyand Secret Access Keyfor future reference.
- Click Done.
- Select Permissionstab.
- Click Add permissionsin section Permissions policies.
- Select Add permissions.
- Select Attach policies directly.
- Search for AmazonS3FullAccesspolicy.
- Select the policy.
- Click Next.
- Click Add permissions.
Configure a feed in Google SecOps to ingest AWS Lambda Function logs
- Go to SIEM Settings > Feeds.
- Click Add New Feed.
- On the next page, click Configure a single feed.
- Enter a unique name for the Feed name.
- Select Amazon S3 V2as the Source type.
- Select AWS Lambda Functionas the Log type.
- Click Nextand then click Submit.
- Specify values for the following fields:
- S3 URI:
s3://lambda-logs-to-secops/lambda-logs/ - Source deletion option: Select the deletion option according to your preference
- Maximum File Age: Include files modified in the last number of days (default is 180 days)
- Access Key ID: User access key with access to the S3 bucket
- Secret Access Key: User secret key with access to the S3 bucket
- Asset namespace: The asset namespace
- Ingestion labels: The label to be applied to the events from this feed
- S3 URI:
- Click Nextand then click Submit.
UDM mapping table
| Log Field | UDM Mapping | Logic |
|---|---|---|
Activity_id_label
|
additional.fields
|
Merged |
Arrays_label
|
additional.fields
|
Merged |
Name_label
|
additional.fields
|
Merged |
Type_1_label
|
additional.fields
|
Merged |
Type_id_label
|
additional.fields
|
Merged |
Type_label
|
additional.fields
|
Merged |
Uid_label
|
additional.fields
|
Merged |
Uid_label_1
|
additional.fields
|
Merged |
Value_label
|
additional.fields
|
Merged |
__type_label
|
additional.fields
|
Merged |
attempts_label
|
additional.fields
|
Merged |
class_name_label
|
additional.fields
|
Merged |
contentType_label
|
additional.fields
|
Merged |
env_label
|
additional.fields
|
Merged |
extendedRequestId_label
|
additional.fields
|
Merged |
feature_name_label
|
additional.fields
|
Merged |
line_number_label
|
additional.fields
|
Merged |
logType_label
|
additional.fields
|
Merged |
product_name_label
|
additional.fields
|
Merged |
requestid_label
|
additional.fields
|
Merged |
sourceAccount_label
|
additional.fields
|
Merged |
stack_label
|
additional.fields
|
Merged |
totalRetryDelay_label
|
additional.fields
|
Merged |
vendor_name_label
|
additional.fields
|
Merged |
version_label
|
additional.fields
|
Merged |
has_principal
|
extensions.auth.type
|
Mapped: true
→ AUTHTYPE_UNSPECIFIED
|
description
|
metadata.description
|
Directly mapped |
file_desc
|
metadata.description
|
Directly mapped |
Time
|
metadata.event_timestamp
|
Parsed as UNIX
|
time
|
metadata.event_timestamp
|
Parsed as yyyy-MM-ddTHH:mm:ss.SSSZ
|
has_principal
|
metadata.event_type
|
Mapped: true
→ USER_LOGIN
, true
→ NETWORK_HTTP
, true
→ NETWORK_CONNECTION
, `true... |
has_principal_user
|
metadata.event_type
|
Mapped: true
→ USER_RESOURCE_ACCESS
|
Api.Operation
|
metadata.product_event_type
|
Directly mapped |
name
|
metadata.product_event_type
|
Directly mapped |
Api.Request.Uid
|
metadata.product_log_id
|
Directly mapped |
id
|
metadata.product_log_id
|
Directly mapped |
meta_data.requestId
|
metadata.product_log_id
|
Directly mapped |
Metadata.Version
|
metadata.product_version
|
Directly mapped |
version
|
metadata.product_version
|
Directly mapped |
meta_data.httpStatusCode
|
network.http.response_code
|
Directly mapped |
Http_request.User_agent
|
network.http.user_agent
|
Directly mapped |
Actor.Invoked_by
|
principal.administrative_domain
|
Directly mapped |
Src_endpoint.Domain
|
principal.asset.hostname
|
Directly mapped |
Src_endpoint.Domain
|
principal.hostname
|
Directly mapped |
Cloud.Region
|
principal.resource.attribute.cloud.availability_zone
|
Directly mapped |
Actor.User.Name
|
principal.user.userid
|
Directly mapped |
Status
|
security_result.action_details
|
Directly mapped |
Category_name
|
security_result.category_details
|
Merged |
error
|
security_result.description
|
Directly mapped |
errorMessage
|
security_result.description
|
Directly mapped |
Metadata_uid_label
|
security_result.detection_fields
|
Merged |
category_uid_label
|
security_result.detection_fields
|
Merged |
class_uid_label
|
security_result.detection_fields
|
Merged |
errorType_label
|
security_result.detection_fields
|
Merged |
event_code_label
|
security_result.detection_fields
|
Merged |
fault_label
|
security_result.detection_fields
|
Merged |
functionName_label
|
security_result.detection_fields
|
Merged |
severity_id_label
|
security_result.detection_fields
|
Merged |
sourceArn_label
|
security_result.detection_fields
|
Merged |
type_name_label
|
security_result.detection_fields
|
Merged |
type_uid_label
|
security_result.detection_fields
|
Merged |
user_type_label
|
security_result.detection_fields
|
Merged |
Severity
|
security_result.severity
|
Mapped: Informational
→ INFORMATIONAL
|
severity
|
security_result.severity
|
Mapped: INFO
→ INFORMATIONAL
|
msg
|
security_result.summary
|
Directly mapped |
Api.Service.Name
|
target.application
|
Directly mapped |
service
|
target.application
|
Directly mapped |
size
|
target.file.size
|
Directly mapped |
filename
|
target.process.file.full_path
|
Directly mapped |
Activity_name
|
target.resource.name
|
Directly mapped |
targetVar
|
target.resource.name
|
Directly mapped |
|
N/A
|
extensions.auth.type
|
Constant: AUTHTYPE_UNSPECIFIED
|
|
N/A
|
metadata.event_type
|
Constant: USER_UNCATEGORIZED
|
|
N/A
|
metadata.product_name
|
Constant: AWS_Lambda_Function
|
|
N/A
|
metadata.vendor_name
|
Constant: AWS_Lambda_Function
|
|
N/A
|
principal.resource.attribute.cloud.environment
|
Constant: AMAZON_WEB_SERVICES
|
|
N/A
|
security_result.severity
|
Constant: INFORMATIONAL
|
Need more help? Get answers from Community members and Google SecOps professionals.

