Skip to main content

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

  1. Open the AWS KMS Console at https://console.aws.amazon.com/kms
  2. Ensure you are in the us-east-1 region (top-right corner)
  3. Click Customer managed keys in the left sidebar
  4. 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
  5. 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)

  1. Open the S3 Console at https://console.aws.amazon.com/s3
  2. Click on your Bedrock logging bucket (or create a new one)
  3. Go to the Properties tab
  4. Scroll to Default encryption and click Edit
  5. Select Server-side encryption with AWS KMS keys (SSE-KMS)
  6. Choose Choose from your AWS KMS keys and select your KMS key
  7. Enable Bucket Key for cost optimization
  8. Click Save changes

Step 3: Enable KMS encryption on your CloudWatch Log Group (if using CloudWatch logging)

  1. Open the CloudWatch Console at https://console.aws.amazon.com/cloudwatch
  2. In the left sidebar, click Logs then Log groups
  3. Find or create a log group for Bedrock logs (e.g., /aws/bedrock/model-invocation-logs)
  4. Select the log group and click Actions > Edit
  5. In the Encryption section, select Customer managed key
  6. Choose your KMS key from the dropdown
  7. Click Save changes

Step 4: Configure Bedrock model invocation logging

  1. Open the Amazon Bedrock Console at https://console.aws.amazon.com/bedrock
  2. In the left sidebar, click Settings
  3. Find the Model invocation logging section and click Edit
  4. Enable logging and configure your destinations:
    • For S3: Select your KMS-encrypted bucket
    • For CloudWatch Logs: Select your KMS-encrypted log group
  5. Select an IAM role that allows Bedrock to write to these destinations
  6. 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:

  1. 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
  2. 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
  3. Check Bedrock logging configuration:

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

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.