Amazon Bedrock Model Invocation Logs Encryption
Overview
This check verifies that your Amazon Bedrock model invocation logs are encrypted using AWS KMS. When you enable model invocation logging in Bedrock, the service records details about each API call to your generative AI models. These logs can be stored in CloudWatch Logs and/or S3. This check ensures both destinations use KMS encryption to protect sensitive data.
Risk
Without KMS encryption on your Bedrock model invocation logs, sensitive information could be exposed:
- Prompt and response data: The actual content sent to and received from AI models, which may contain confidential business information, customer data, or proprietary content
- Token usage metadata: Information about how models are being used could reveal business patterns
- PII exposure: Prompts and responses may inadvertently contain personally identifiable information
- Compliance violations: Many regulatory frameworks (C5, ISO27001, KISA-ISMS-P, NIS2) require encryption of sensitive log data
- Lateral movement risk: Unencrypted logs could provide attackers with operational intelligence if storage systems are compromised
Remediation Steps
Prerequisites
- AWS account access with permissions to modify Bedrock settings, S3 buckets, and CloudWatch Log Groups
- An existing KMS key, or permission to create one
Required IAM permissions
To configure encrypted logging for Bedrock, you need:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"bedrock:GetModelInvocationLoggingConfiguration",
"bedrock:PutModelInvocationLoggingConfiguration"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"logs:AssociateKmsKey",
"logs:DescribeLogGroups",
"logs:CreateLogGroup"
],
"Resource": "arn:aws:logs:us-east-1:*:log-group:*"
},
{
"Effect": "Allow",
"Action": [
"s3:PutBucketEncryption",
"s3:GetBucketEncryption"
],
"Resource": "arn:aws:s3:::*"
},
{
"Effect": "Allow",
"Action": [
"kms:DescribeKey",
"kms:CreateGrant",
"kms:CreateKey"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"iam:CreateRole",
"iam:PutRolePolicy",
"iam:PassRole"
],
"Resource": "arn:aws:iam::*:role/BedrockModelInvocationLoggingRole"
}
]
}
AWS Console Method
Step 1: Create or identify a KMS key
- Open the AWS KMS Console at https://console.aws.amazon.com/kms
- Ensure you are in the us-east-1 region (top-right corner)
- Click Customer managed keys in the left sidebar
- Either select an existing symmetric key, or click Create key:
- Key type: Symmetric
- Key usage: Encrypt and decrypt
- Give it a name like
bedrock-logging-key
- Copy the Key ARN for later use
KMS key policy for Bedrock logging
Your KMS key policy must allow CloudWatch Logs and S3 to use the key. Add these statements to your key policy:
{
"Sid": "Allow CloudWatch Logs",
"Effect": "Allow",
"Principal": {
"Service": "logs.us-east-1.amazonaws.com"
},
"Action": [
"kms:Encrypt*",
"kms:Decrypt*",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:Describe*"
],
"Resource": "*",
"Condition": {
"ArnLike": {
"kms:EncryptionContext:aws:logs:arn": "arn:aws:logs:us-east-1:<YOUR_ACCOUNT_ID>:log-group:*"
}
}
},
{
"Sid": "Allow S3 Service",
"Effect": "Allow",
"Principal": {
"Service": "s3.amazonaws.com"
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*"
}
Replace <YOUR_ACCOUNT_ID> with your 12-digit AWS account ID.
Step 2: Enable KMS encryption on your S3 bucket (if using S3 logging)
- Open the S3 Console at https://console.aws.amazon.com/s3
- Click on your Bedrock logging bucket (or create a new one)
- Go to the Properties tab
- Scroll to Default encryption and click Edit
- Select Server-side encryption with AWS KMS keys (SSE-KMS)
- Choose Choose from your AWS KMS keys and select your KMS key
- Enable Bucket Key for cost optimization
- Click Save changes
Step 3: Enable KMS encryption on your CloudWatch Log Group (if using CloudWatch logging)
- Open the CloudWatch Console at https://console.aws.amazon.com/cloudwatch
- In the left sidebar, click Logs then Log groups
- Find or create a log group for Bedrock logs (e.g.,
/aws/bedrock/model-invocation-logs) - Select the log group and click Actions > Edit
- In the Encryption section, select Customer managed key
- Choose your KMS key from the dropdown
- Click Save changes
Step 4: Configure Bedrock model invocation logging
- Open the Amazon Bedrock Console at https://console.aws.amazon.com/bedrock
- In the left sidebar, click Settings
- Find the Model invocation logging section and click Edit
- Enable logging and configure your destinations:
- For S3: Select your KMS-encrypted bucket
- For CloudWatch Logs: Select your KMS-encrypted log group
- Select an IAM role that allows Bedrock to write to these destinations
- Click Save
AWS CLI (optional)
Check current logging configuration
aws bedrock get-model-invocation-logging-configuration \
--region us-east-1
Enable encrypted logging with both S3 and CloudWatch
First, create a logging configuration file:
cat > bedrock-logging-config.json << 'EOF'
{
"cloudWatchConfig": {
"logGroupName": "/aws/bedrock/model-invocation-logs",
"roleArn": "arn:aws:iam::<YOUR_ACCOUNT_ID>:role/BedrockModelInvocationLoggingRole",
"largeDataDeliveryS3Config": {
"bucketName": "<YOUR_BUCKET_NAME>",
"keyPrefix": "bedrock-logs/large-data"
}
},
"s3Config": {
"bucketName": "<YOUR_BUCKET_NAME>",
"keyPrefix": "bedrock-logs"
},
"textDataDeliveryEnabled": true,
"imageDataDeliveryEnabled": true,
"embeddingDataDeliveryEnabled": true
}
EOF
Then apply the configuration:
aws bedrock put-model-invocation-logging-configuration \
--logging-config file://bedrock-logging-config.json \
--region us-east-1
Replace:
<YOUR_ACCOUNT_ID>with your 12-digit AWS account ID<YOUR_BUCKET_NAME>with your S3 bucket name
Create the IAM role for Bedrock logging
# Create the trust policy
cat > trust-policy.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "bedrock.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
# Create the role
aws iam create-role \
--role-name BedrockModelInvocationLoggingRole \
--assume-role-policy-document file://trust-policy.json \
--region us-east-1
# Create the permissions policy
cat > logging-policy.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:us-east-1:<YOUR_ACCOUNT_ID>:log-group:/aws/bedrock/model-invocation-logs:*"
},
{
"Effect": "Allow",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::<YOUR_BUCKET_NAME>/*"
},
{
"Effect": "Allow",
"Action": [
"kms:GenerateDataKey",
"kms:Decrypt"
],
"Resource": "arn:aws:kms:us-east-1:<YOUR_ACCOUNT_ID>:key/<YOUR_KEY_ID>"
}
]
}
EOF
# Attach the policy to the role
aws iam put-role-policy \
--role-name BedrockModelInvocationLoggingRole \
--policy-name BedrockLoggingPolicy \
--policy-document file://logging-policy.json
CloudFormation (optional)
This template creates a complete encrypted logging setup for Bedrock, including:
- A KMS key with proper permissions
- An encrypted CloudWatch Log Group
- An encrypted S3 bucket
- An IAM role for Bedrock to write logs
AWSTemplateFormatVersion: '2010-09-09'
Description: Amazon Bedrock Model Invocation Logging with KMS Encryption
Parameters:
LogGroupName:
Type: String
Description: Name of the CloudWatch Log Group for Bedrock logs
Default: /aws/bedrock/model-invocation-logs
S3BucketName:
Type: String
Description: Name of the S3 bucket for Bedrock logs
RetentionInDays:
Type: Number
Description: Number of days to retain CloudWatch log events
Default: 30
AllowedValues: [1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1096, 1827, 2192, 2557, 2922, 3288, 3653]
Resources:
BedrockLoggingKMSKey:
Type: AWS::KMS::Key
Properties:
Description: KMS key for Bedrock model invocation log encryption
EnableKeyRotation: true
KeyPolicy:
Version: '2012-10-17'
Statement:
- Sid: Enable IAM User Permissions
Effect: Allow
Principal:
AWS: !Sub 'arn:aws:iam::${AWS::AccountId}:root'
Action: 'kms:*'
Resource: '*'
- Sid: Allow CloudWatch Logs
Effect: Allow
Principal:
Service: !Sub 'logs.${AWS::Region}.amazonaws.com'
Action:
- kms:Encrypt*
- kms:Decrypt*
- kms:ReEncrypt*
- kms:GenerateDataKey*
- kms:Describe*
Resource: '*'
Condition:
ArnLike:
'kms:EncryptionContext:aws:logs:arn': !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:*'
- Sid: Allow S3 Service
Effect: Allow
Principal:
Service: s3.amazonaws.com
Action:
- kms:Encrypt
- kms:Decrypt
- kms:ReEncrypt*
- kms:GenerateDataKey*
- kms:DescribeKey
Resource: '*'
BedrockLoggingKMSKeyAlias:
Type: AWS::KMS::Alias
Properties:
AliasName: alias/bedrock-logging-key
TargetKeyId: !Ref BedrockLoggingKMSKey
BedrockLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Ref LogGroupName
KmsKeyId: !GetAtt BedrockLoggingKMSKey.Arn
RetentionInDays: !Ref RetentionInDays
BedrockLoggingBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref S3BucketName
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: aws:kms
KMSMasterKeyID: !GetAtt BedrockLoggingKMSKey.Arn
BucketKeyEnabled: true
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
BedrockLoggingRole:
Type: AWS::IAM::Role
Properties:
RoleName: BedrockModelInvocationLoggingRole
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: bedrock.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: BedrockLoggingPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- logs:CreateLogStream
- logs:PutLogEvents
Resource: !Sub 'arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:${LogGroupName}:*'
- Effect: Allow
Action:
- s3:PutObject
Resource: !Sub 'arn:aws:s3:::${S3BucketName}/*'
- Effect: Allow
Action:
- kms:GenerateDataKey
- kms:Decrypt
Resource: !GetAtt BedrockLoggingKMSKey.Arn
Outputs:
KMSKeyArn:
Description: ARN of the KMS key for Bedrock logging encryption
Value: !GetAtt BedrockLoggingKMSKey.Arn
LogGroupArn:
Description: ARN of the CloudWatch Log Group
Value: !GetAtt BedrockLogGroup.Arn
S3BucketArn:
Description: ARN of the S3 bucket for logs
Value: !GetAtt BedrockLoggingBucket.Arn
LoggingRoleArn:
Description: ARN of the IAM role for Bedrock logging
Value: !GetAtt BedrockLoggingRole.Arn
Deploy with:
aws cloudformation deploy \
--template-file template.yaml \
--stack-name bedrock-encrypted-logging \
--parameter-overrides S3BucketName=my-bedrock-logs-bucket \
--capabilities CAPABILITY_NAMED_IAM \
--region us-east-1
Note: After deploying the infrastructure, you still need to enable model invocation logging in the Bedrock console or via CLI, pointing to the created resources.
Terraform (optional)
variable "log_group_name" {
description = "Name of the CloudWatch Log Group for Bedrock logs"
type = string
default = "/aws/bedrock/model-invocation-logs"
}
variable "s3_bucket_name" {
description = "Name of the S3 bucket for Bedrock logs"
type = string
}
variable "retention_in_days" {
description = "Number of days to retain CloudWatch log events"
type = number
default = 30
}
data "aws_caller_identity" "current" {}
data "aws_region" "current" {}
resource "aws_kms_key" "bedrock_logging" {
description = "KMS key for Bedrock model invocation log encryption"
deletion_window_in_days = 30
enable_key_rotation = true
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "Enable IAM User Permissions"
Effect = "Allow"
Principal = { AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root" }
Action = "kms:*"
Resource = "*"
},
{
Sid = "Allow CloudWatch Logs"
Effect = "Allow"
Principal = { Service = "logs.${data.aws_region.current.id}.amazonaws.com" }
Action = [
"kms:Encrypt*",
"kms:Decrypt*",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:Describe*"
]
Resource = "*"
Condition = {
ArnLike = {
"kms:EncryptionContext:aws:logs:arn" = "arn:aws:logs:${data.aws_region.current.id}:${data.aws_caller_identity.current.account_id}:log-group:*"
}
}
},
{
Sid = "Allow S3 Service"
Effect = "Allow"
Principal = { Service = "s3.amazonaws.com" }
Action = [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
]
Resource = "*"
}
]
})
}
resource "aws_kms_alias" "bedrock_logging" {
name = "alias/bedrock-logging-key"
target_key_id = aws_kms_key.bedrock_logging.key_id
}
resource "aws_cloudwatch_log_group" "bedrock" {
name = var.log_group_name
kms_key_id = aws_kms_key.bedrock_logging.arn
retention_in_days = var.retention_in_days
}
resource "aws_s3_bucket" "bedrock_logs" {
bucket = var.s3_bucket_name
}
resource "aws_s3_bucket_server_side_encryption_configuration" "bedrock_logs" {
bucket = aws_s3_bucket.bedrock_logs.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
kms_master_key_id = aws_kms_key.bedrock_logging.arn
}
bucket_key_enabled = true
}
}
resource "aws_s3_bucket_public_access_block" "bedrock_logs" {
bucket = aws_s3_bucket.bedrock_logs.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_iam_role" "bedrock_logging" {
name = "BedrockModelInvocationLoggingRole"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Service = "bedrock.amazonaws.com"
}
Action = "sts:AssumeRole"
}
]
})
}
resource "aws_iam_role_policy" "bedrock_logging" {
name = "BedrockLoggingPolicy"
role = aws_iam_role.bedrock_logging.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"logs:CreateLogStream",
"logs:PutLogEvents"
]
Resource = "${aws_cloudwatch_log_group.bedrock.arn}:*"
},
{
Effect = "Allow"
Action = "s3:PutObject"
Resource = "${aws_s3_bucket.bedrock_logs.arn}/*"
},
{
Effect = "Allow"
Action = [
"kms:GenerateDataKey",
"kms:Decrypt"
]
Resource = aws_kms_key.bedrock_logging.arn
}
]
})
}
output "kms_key_arn" {
description = "ARN of the KMS key for Bedrock logging encryption"
value = aws_kms_key.bedrock_logging.arn
}
output "log_group_arn" {
description = "ARN of the CloudWatch Log Group"
value = aws_cloudwatch_log_group.bedrock.arn
}
output "s3_bucket_arn" {
description = "ARN of the S3 bucket for logs"
value = aws_s3_bucket.bedrock_logs.arn
}
output "logging_role_arn" {
description = "ARN of the IAM role for Bedrock logging"
value = aws_iam_role.bedrock_logging.arn
}
Deploy with:
terraform init
terraform plan -var="s3_bucket_name=my-bedrock-logs-bucket"
terraform apply -var="s3_bucket_name=my-bedrock-logs-bucket"
Note: After deploying the infrastructure, you still need to enable model invocation logging in the Bedrock console or via CLI, pointing to the created resources.
Verification
After configuring encryption, verify that your Bedrock logging destinations are properly encrypted:
-
Check S3 bucket encryption:
- Open the S3 Console at https://console.aws.amazon.com/s3
- Click on your logging bucket
- Go to Properties > Default encryption
- Confirm it shows SSE-KMS with your customer-managed key
-
Check CloudWatch Log Group encryption:
- Open the CloudWatch Console at https://console.aws.amazon.com/cloudwatch
- Navigate to Logs > Log groups
- Click on your Bedrock log group
- In the Details section, confirm KMS key ARN shows your customer-managed key
-
Check Bedrock logging configuration:
- Open the Amazon Bedrock Console at https://console.aws.amazon.com/bedrock
- Go to Settings
- Verify model invocation logging is enabled and points to your encrypted destinations
Verify with AWS CLI
Check Bedrock logging configuration
aws bedrock get-model-invocation-logging-configuration \
--region us-east-1
Check CloudWatch Log Group encryption
aws logs describe-log-groups \
--log-group-name-prefix /aws/bedrock \
--region us-east-1 \
--query 'logGroups[*].{Name:logGroupName,KmsKeyId:kmsKeyId}'
A properly encrypted log group will show a KMS key ARN:
[
{
"Name": "/aws/bedrock/model-invocation-logs",
"KmsKeyId": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"
}
]
Check S3 bucket encryption
aws s3api get-bucket-encryption \
--bucket <YOUR_BUCKET_NAME> \
--region us-east-1
A properly encrypted bucket will show SSE-KMS configuration:
{
"ServerSideEncryptionConfiguration": {
"Rules": [
{
"ApplyServerSideEncryptionByDefault": {
"SSEAlgorithm": "aws:kms",
"KMSMasterKeyID": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"
},
"BucketKeyEnabled": true
}
]
}
}
Additional Resources
- AWS Documentation: Model invocation logging
- AWS Documentation: Data protection in Amazon Bedrock
- AWS CLI Reference: put-model-invocation-logging-configuration
- AWS KMS Developer Guide
- Terraform: aws_kms_key
Notes
- Both destinations need encryption: This check validates that BOTH your S3 bucket (if configured) uses KMS encryption AND your CloudWatch Log Group (if configured) uses a customer-managed KMS key.
- Encryption applies to new data only: After enabling KMS encryption, only new log data is encrypted with your key. Existing data retains its previous encryption.
- Key availability is critical: If your KMS key is deleted or disabled, Bedrock cannot write new logs and you cannot read existing encrypted logs. Ensure proper key management and backup procedures.
- Cost considerations: Using customer-managed KMS keys incurs additional charges for key storage and API calls. Enable S3 Bucket Keys to reduce KMS costs for S3 encryption.
- IAM role permissions: The IAM role used by Bedrock for logging must have permissions to use your KMS key for encryption operations.
- Cross-region considerations: KMS keys are region-specific. Ensure your KMS key is in the same region as your Bedrock configuration and logging destinations.