Ensure Amazon Bedrock API Keys Are Not Long-Term Credentials
Overview
This check identifies Amazon Bedrock API keys that are configured without expiration dates or with expiration dates far in the future. API keys without proper expiration are considered "long-term credentials" and represent a security risk because they remain valid indefinitely.
Amazon Bedrock API keys are service-specific credentials that allow applications to authenticate with Bedrock services. Unlike temporary credentials, long-term API keys do not automatically expire, making them vulnerable if compromised.
Risk
Long-term Bedrock API keys create several security concerns:
- Unauthorized access: If a key is leaked or stolen, attackers can use it indefinitely until someone manually revokes it
- Cost exposure: Compromised keys can lead to unexpected usage charges from unauthorized Bedrock API calls
- Data exposure: Attackers could access your prompts, model outputs, and other sensitive inference data
- Compliance violations: Many security frameworks require credential rotation, which long-term keys violate
Severity: High
Remediation Steps
Prerequisites
You need access to the AWS Console with permissions to manage IAM users and their credentials. Specifically, you need the iam:ListServiceSpecificCredentials and iam:DeleteServiceSpecificCredential permissions.
AWS Console Method
- Sign in to the AWS Management Console
- Navigate to IAM (Identity and Access Management)
- In the left sidebar, click Users
- Select the user who owns the flagged Bedrock API key
- Click the Security credentials tab
- Scroll down to find the API keys for Amazon Bedrock section
- Locate the API key without an expiration date (or with a distant expiration)
- Click Delete next to the problematic key
- Confirm the deletion when prompted
After deleting the long-term key, create a replacement key with a reasonable expiration period (see "Creating a New Key with Expiration" below).
Creating a New Key with Expiration
When you need Bedrock API key access, create a new key with a defined expiration:
- In the IAM Console, go to Users and select the appropriate user
- Click the Security credentials tab
- Under API keys for Amazon Bedrock, click Create API key
- Set an appropriate expiration period (recommended: 90 days or less)
- Store the credentials securely - they are only shown once
AWS CLI Method
List existing Bedrock API keys for a user:
aws iam list-service-specific-credentials \
--user-name <username> \
--service-name bedrock.amazonaws.com \
--region us-east-1
This returns details including ServiceSpecificCredentialId and expiration information.
Delete a long-term API key:
aws iam delete-service-specific-credential \
--user-name <username> \
--service-specific-credential-id <credential-id> \
--region us-east-1
Replace:
<username>with the IAM user's name<credential-id>with the credential ID from the list command
Create a new API key with expiration:
aws iam create-service-specific-credential \
--user-name <username> \
--service-name bedrock.amazonaws.com \
--credential-age-days 90 \
--region us-east-1
The --credential-age-days parameter sets how many days until the key expires. Choose a value appropriate for your security requirements (90 days or less is recommended).
List all Bedrock API keys across all users:
aws iam list-service-specific-credentials \
--service-name bedrock.amazonaws.com \
--all-users \
--region us-east-1
CloudFormation
CloudFormation does not directly support creating service-specific credentials like Bedrock API keys. These credentials must be created through the AWS Console, CLI, or SDK after the IAM user is provisioned.
However, you can use CloudFormation to create the IAM user with appropriate Bedrock permissions, then create the API key separately:
AWSTemplateFormatVersion: '2010-09-09'
Description: IAM user for Amazon Bedrock access
Resources:
BedrockUser:
Type: AWS::IAM::User
Properties:
UserName: bedrock-service-user
Policies:
- PolicyName: BedrockAccess
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- bedrock:InvokeModel
- bedrock:InvokeModelWithResponseStream
Resource: '*'
Outputs:
UserName:
Description: IAM user name for Bedrock API key creation
Value: !Ref BedrockUser
After deploying this template, create the API key with expiration using the CLI:
aws iam create-service-specific-credential \
--user-name bedrock-service-user \
--service-name bedrock.amazonaws.com \
--credential-age-days 90 \
--region us-east-1
Terraform
Terraform's AWS provider does not currently support the aws_iam_service_specific_credential resource for creating Bedrock API keys. You can create the IAM user with Terraform and then use a null_resource with a local-exec provisioner to create the API key.
# Create IAM user for Bedrock access
resource "aws_iam_user" "bedrock_user" {
name = "bedrock-service-user"
}
# Attach Bedrock permissions
resource "aws_iam_user_policy" "bedrock_policy" {
name = "bedrock-access"
user = aws_iam_user.bedrock_user.name
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream"
]
Resource = "*"
}
]
})
}
# Create service-specific credential with expiration
# Note: This requires AWS CLI to be installed and configured
resource "null_resource" "bedrock_api_key" {
depends_on = [aws_iam_user.bedrock_user]
provisioner "local-exec" {
command = <<-EOT
aws iam create-service-specific-credential \
--user-name ${aws_iam_user.bedrock_user.name} \
--service-name bedrock.amazonaws.com \
--credential-age-days 90 \
--region us-east-1
EOT
}
# Recreate if the user changes
triggers = {
user_name = aws_iam_user.bedrock_user.name
}
}
Important: The null_resource approach has limitations:
- Credentials are only created on first apply
- Terraform cannot track or manage the credential lifecycle
- Consider using a dedicated secrets management solution for production
Alternative: Use IAM Roles Instead of API Keys
The most secure approach is to avoid long-term API keys entirely. Instead, use IAM roles with temporary credentials:
For EC2 instances: Attach an IAM role with Bedrock permissions to your EC2 instance. The instance automatically receives temporary credentials that rotate.
For Lambda functions: Assign an execution role with Bedrock permissions. Lambda handles credential rotation automatically.
For applications outside AWS:
Use IAM Identity Center (SSO) or assume a role using aws sts assume-role to get temporary credentials:
aws sts assume-role \
--role-arn arn:aws:iam::<account-id>:role/BedrockAccessRole \
--role-session-name bedrock-session \
--region us-east-1
This returns temporary credentials that expire automatically (default: 1 hour).
Verification
After remediation, verify the fix:
- Return to the IAM Console and check the user's Security credentials tab
- Confirm the long-term API key has been deleted
- If you created a replacement key, verify it shows an appropriate expiration date
- Re-run the Prowler check to confirm the finding is resolved:
Verification Commands
# List remaining Bedrock API keys for the user
aws iam list-service-specific-credentials \
--user-name <username> \
--service-name bedrock.amazonaws.com \
--region us-east-1
# Re-run the specific Prowler check
prowler aws --check bedrock_api_key_no_long_term_credentials
Additional Resources
- AWS IAM Service-Specific Credentials Documentation
- Amazon Bedrock Security Best Practices
- AWS Security Token Service (STS) Documentation
- Prowler Check Documentation
Notes
- Credential rotation policy: Establish a policy requiring Bedrock API keys to expire within 90 days or less
- Application updates: Before deleting an API key, ensure any applications using it are updated to use the new credentials or switched to IAM roles
- Secrets management: Store API credentials in AWS Secrets Manager or a similar vault, not in application code or configuration files
- Audit logging: Enable AWS CloudTrail to monitor Bedrock API key usage and detect suspicious activity
- Least privilege: Ensure IAM users with Bedrock API keys have only the minimum permissions required for their tasks