Back to Checks
Amazon Bedrock model invocation logs are encrypted in the S3 bucket and KMS-encrypted in the CloudWatch log group
bedrock_model_invocation_logs_encryption_enabled
Service: bedrockSeverity: high
OfficialBuilt-inVerified
Categories:encryptionlogginggen-ai
Resource Type:AwsS3Bucket
Bedrock model invocation logs are stored in encrypted destinations: S3 buckets with bucket encryption and CloudWatch Logs groups protected by an AWS KMS key.
This evaluates whether configured log targets enforce encryption at rest for request/response content and associated metadata.
Risk
Without encryption at rest, prompts, outputs, images, and token/usage metadata in logs can be read if S3 or CloudWatch storage or replicas are accessed by unauthorized principals.
Impacts:
- Loss of data confidentiality
- Secret or PII exposure enabling account abuse
- Operational intel for lateral movement
Run this check with Prowler
Run in Prowler CloudRun
prowler aws --checks bedrock_model_invocation_logs_encryption_enabledRecommendation
Ensure all invocation logs are encrypted end to end:
- Enable S3 default encryption, preferably
SSE-KMS, and restrict key usage - Assign a KMS key to CloudWatch log groups
- Enforce least privilege on keys and logs, rotate keys, and monitor access for defense in depth
Remediation
Terraform
resource "aws_s3_bucket" "example" {
bucket = "<example_resource_name>"
}
resource "aws_s3_bucket_server_side_encryption_configuration" "example" {
bucket = aws_s3_bucket.example.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256" # critical: enables default encryption for the S3 bucket
}
}
}
resource "aws_cloudwatch_log_group" "example" {
name = "<example_resource_name>"
kms_key_id = "<example_kms_key_arn>" # critical: encrypts the log group with a KMS key
}NativeIaC
Resources:
EncryptedLogsBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: <example_resource_name>
BucketEncryption: # critical: enables default encryption for the bucket (SSE-S3)
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
EncryptedLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: <example_resource_name>
KmsKeyId: <example_kms_key_arn> # critical: encrypts the CloudWatch log group with a KMS keyOther
1In the Bedrock console, go to Settings and note the S3 bucket and CloudWatch log group used for Model invocation logging.
2S3 bucket: AWS Console > S3 > Buckets > <bucket> > Properties > Default encryption > Enable > Choose SSE-S3 (AES-256) > Save.
3CloudWatch Logs: AWS Console > CloudWatch > Logs > Log groups > select <log group> > Actions > Edit > KMS encryption > select <KMS key> > Save.
Check Code
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.bedrock.bedrock_client import bedrock_client
from prowler.providers.aws.services.cloudwatch.logs_client import logs_client
from prowler.providers.aws.services.s3.s3_client import s3_client
class bedrock_model_invocation_logs_encryption_enabled(Check):
def execute(self):
findings = []
for region, logging in bedrock_client.logging_configurations.items():
if logging.enabled:
s3_encryption = True
cloudwatch_encryption = True
report = Check_Report_AWS(metadata=self.metadata(), resource=logging)
report.region = region
report.resource_id = "model-invocation-logging"
report.resource_arn = (
bedrock_client._get_model_invocation_logging_arn_template(region)
)
report.status = "PASS"
report.status_extended = "Bedrock Model Invocation logs are encrypted."
if logging.s3_bucket:
bucket_arn = (
f"arn:{s3_client.audited_partition}:s3:::{logging.s3_bucket}"
)
if (
bucket_arn in s3_client.buckets
and not s3_client.buckets[bucket_arn].encryption
):
s3_encryption = False
if logging.cloudwatch_log_group:
log_group_arn = f"arn:{logs_client.audited_partition}:logs:{region}:{logs_client.audited_account}:log-group:{logging.cloudwatch_log_group}"
all_log_groups = getattr(logs_client, "all_log_groups", None) or {}
if (
log_group_arn in all_log_groups
and not all_log_groups[log_group_arn].kms_id
) or (
log_group_arn + ":*" in all_log_groups
and not all_log_groups[log_group_arn + ":*"].kms_id
):
cloudwatch_encryption = False
if not s3_encryption and not cloudwatch_encryption:
report.status = "FAIL"
report.status_extended = f"Bedrock Model Invocation logs are not encrypted in S3 bucket: {logging.s3_bucket} and CloudWatch Log Group: {logging.cloudwatch_log_group}."
elif not s3_encryption:
report.status = "FAIL"
report.status_extended = f"Bedrock Model Invocation logs are not encrypted in S3 bucket: {logging.s3_bucket}."
elif not cloudwatch_encryption:
report.status = "FAIL"
report.status_extended = f"Bedrock Model Invocation logs are not encrypted in CloudWatch Log Group: {logging.cloudwatch_log_group}."
findings.append(report)
return findingsReferences
- https://docs.aws.amazon.com/bedrock/latest/userguide/data-protection.html
- https://docs.aws.amazon.com/bedrock/latest/userguide/model-invocation-logging.html
- https://support.icompaas.com/support/solutions/articles/62000233532-ensure-that-amazon-bedrock-model-invocation-logs-are-encrypted-with-kms
- https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/configure-bedrock-invocation-logging-cloudformation.html