Lambda function Invoke API calls are recorded by CloudTrail
AWS Lambda function invocations are recorded as CloudTrail data events when trails include AWS::Lambda::Function resources.
The finding reflects whether a function's Invoke activity is being logged by an eligible trail.
Risk
Without Lambda Invoke data events, per-invocation accountability is lost. Adversaries or misused automation can run code without an audit trail, obscuring actor, time, and source. This hinders forensics and enables covert exfiltration or unauthorized changes, impacting confidentiality and integrity.
Run this check with Prowler
Run in Prowler Cloudprowler aws --checks awslambda_function_invoke_api_operations_cloudtrail_logging_enabledRecommendation
Enable CloudTrail data event logging for AWS::Lambda::Function to capture Invoke calls across required Regions and accounts. Apply least privilege selectors to scope events, centralize logs with strong retention, and integrate alerts for anomalous invokes as part of defense in depth.
Remediation
CLI
aws cloudtrail put-event-selectors --trail-name <example_resource_name> --advanced-event-selectors '[{"FieldSelectors":[{"Field":"eventCategory","Equals":["Data"]},{"Field":"resources.type","Equals":["AWS::Lambda::Function"]}]}]'Terraform
resource "aws_cloudtrail" "<example_resource_name>" {
name = "<example_resource_name>"
s3_bucket_name = "<example_resource_name>"
event_selector {
data_resource {
type = "AWS::Lambda::Function" # Critical: enable Lambda data events
values = ["arn:aws:lambda:<REGION>:<ACCOUNT_ID>:function"] # Critical: capture Invoke for all functions in this account/region
}
}
}NativeIaC
Resources:
<example_resource_name>:
Type: AWS::CloudTrail::Trail
Properties:
S3BucketName: <example_resource_name>
IsLogging: true
EventSelectors:
- DataResources:
- Type: AWS::Lambda::Function # Critical: enables Lambda data event logging
Values:
- arn:aws:lambda:<REGION>:<ACCOUNT_ID>:function # Critical: logs Invoke events for all functions in the specified account/regionOther
Check Code
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.awslambda.awslambda_client import awslambda_client
from prowler.providers.aws.services.cloudtrail.cloudtrail_client import (
cloudtrail_client,
)
class awslambda_function_invoke_api_operations_cloudtrail_logging_enabled(Check):
def execute(self):
findings = []
for function in awslambda_client.functions.values():
report = Check_Report_AWS(metadata=self.metadata(), resource=function)
report.status = "FAIL"
report.status_extended = (
f"Lambda function {function.name} is not recorded by CloudTrail."
)
lambda_recorded_cloudtrail = False
if cloudtrail_client.trails:
for trail in cloudtrail_client.trails.values():
for data_event in trail.data_events:
# classic event selectors
if not data_event.is_advanced:
if "DataResources" in data_event.event_selector:
for resource in data_event.event_selector[
"DataResources"
]:
if resource["Type"] == "AWS::Lambda::Function" and (
function.arn in resource["Values"]
or f"arn:{awslambda_client.audited_partition}:lambda"
in resource["Values"]
):
lambda_recorded_cloudtrail = True
break
elif data_event.is_advanced:
for field_selector in data_event.event_selector[
"FieldSelectors"
]:
if (
field_selector["Field"] == "resources.type"
and "AWS::Lambda::Function"
in field_selector["Equals"]
):
lambda_recorded_cloudtrail = True
break
if lambda_recorded_cloudtrail:
break
if lambda_recorded_cloudtrail:
report.status = "PASS"
report.status_extended = f"Lambda function {function.name} is recorded by CloudTrail trail {trail.name}."
break
findings.append(report)
return findings