Skip to main content

Ensure Amazon Bedrock API Keys Do Not Have Administrative Privileges

Overview

This check verifies that Amazon Bedrock API keys (service-specific credentials linked to IAM users) do not have administrative privileges or privilege escalation capabilities. API keys should follow the principle of least privilege, granting only the permissions necessary for specific tasks.

Risk

Amazon Bedrock API keys with excessive permissions pose significant security risks:

  • Data exfiltration: Attackers could invoke models at scale to extract sensitive information
  • Cost explosion: Unauthorized large-scale model invocations can generate unexpected charges
  • Privilege escalation: Keys with IAM modification permissions could be used to gain persistent access
  • Service disruption: Unauthorized modifications to Bedrock configurations could impact operations

Remediation Steps

Prerequisites

You need IAM administrative access to review and modify user policies. The affected IAM user should be identified from the Prowler check results.

Tools setup (optional)

If using the AWS CLI, ensure it is installed and configured:

aws --version
aws configure

AWS Console Method

  1. Open the IAM Console

    • Go to IAM Users
    • Select the user identified in the Prowler finding
  2. Review attached policies

    • Click the Permissions tab
    • Look for policies granting excessive access:
      • AdministratorAccess
      • PowerUserAccess
      • Any policy with bedrock:* or * actions
      • Any policy with iam:* actions (allows privilege escalation)
  3. Remove overly permissive policies

    • For managed policies: Click the X next to the policy name to detach it
    • For inline policies: Expand the policy and click Delete
  4. Add a least-privilege policy

    • Click Add permissions > Create inline policy
    • Switch to the JSON tab
    • Paste the following policy:
    {
    "Version": "2012-10-17",
    "Statement": [
    {
    "Sid": "AllowBedrockModelInvocation",
    "Effect": "Allow",
    "Action": [
    "bedrock:InvokeModel",
    "bedrock:InvokeModelWithResponseStream"
    ],
    "Resource": [
    "arn:aws:bedrock:us-east-1::foundation-model/*"
    ]
    },
    {
    "Sid": "AllowListModels",
    "Effect": "Allow",
    "Action": [
    "bedrock:ListFoundationModels",
    "bedrock:GetFoundationModel"
    ],
    "Resource": "*"
    }
    ]
    }
    • Click Review policy, name it BedrockMinimalAccess, and click Create policy
  5. Consider deleting the service-specific credential

    • If the credential may have been compromised, navigate to Security credentials tab
    • Under Credentials for Amazon Bedrock, delete the existing credential and create a new one
AWS CLI (optional)

List current policies for the user

# List attached managed policies
aws iam list-attached-user-policies \
--user-name <your-iam-user> \
--region us-east-1

# List inline policies
aws iam list-user-policies \
--user-name <your-iam-user> \
--region us-east-1

Remove overly permissive policies

# Detach AdministratorAccess (if attached)
aws iam detach-user-policy \
--user-name <your-iam-user> \
--policy-arn arn:aws:iam::aws:policy/AdministratorAccess \
--region us-east-1

# Delete an inline policy
aws iam delete-user-policy \
--user-name <your-iam-user> \
--policy-name <policy-name> \
--region us-east-1

Create a least-privilege inline policy

aws iam put-user-policy \
--user-name <your-iam-user> \
--policy-name BedrockMinimalAccess \
--policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowBedrockModelInvocation",
"Effect": "Allow",
"Action": [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream"
],
"Resource": [
"arn:aws:bedrock:us-east-1::foundation-model/*"
]
},
{
"Sid": "AllowListModels",
"Effect": "Allow",
"Action": [
"bedrock:ListFoundationModels",
"bedrock:GetFoundationModel"
],
"Resource": "*"
}
]
}' \
--region us-east-1

Rotate the service-specific credential (if needed)

# List existing credentials
aws iam list-service-specific-credentials \
--user-name <your-iam-user> \
--service-name bedrock.amazonaws.com \
--region us-east-1

# Delete the old credential
aws iam delete-service-specific-credential \
--user-name <your-iam-user> \
--service-specific-credential-id <credential-id> \
--region us-east-1

# Create a new credential
aws iam create-service-specific-credential \
--user-name <your-iam-user> \
--service-name bedrock.amazonaws.com \
--region us-east-1
CloudFormation (optional)

Use this template to create a least-privilege IAM policy for Bedrock access:

AWSTemplateFormatVersion: '2010-09-09'
Description: Least-privilege IAM policy for Amazon Bedrock API access

Parameters:
UserName:
Type: String
Description: The IAM user to attach the policy to

Resources:
BedrockMinimalPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
ManagedPolicyName: BedrockMinimalAccess
Description: Minimal permissions for Amazon Bedrock model invocation
PolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: AllowBedrockModelInvocation
Effect: Allow
Action:
- bedrock:InvokeModel
- bedrock:InvokeModelWithResponseStream
Resource:
- !Sub 'arn:aws:bedrock:${AWS::Region}::foundation-model/*'
- Sid: AllowListModels
Effect: Allow
Action:
- bedrock:ListFoundationModels
- bedrock:GetFoundationModel
Resource: '*'
Users:
- !Ref UserName

Outputs:
PolicyArn:
Description: ARN of the created Bedrock minimal access policy
Value: !Ref BedrockMinimalPolicy

Deploy the stack:

aws cloudformation create-stack \
--stack-name bedrock-minimal-access \
--template-body file://template.yaml \
--parameters ParameterKey=UserName,ParameterValue=<your-iam-user> \
--capabilities CAPABILITY_NAMED_IAM \
--region us-east-1
Terraform (optional)
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 4.0"
}
}
}

variable "iam_user_name" {
description = "The IAM user to attach the policy to"
type = string
}

variable "aws_region" {
description = "AWS region for Bedrock resources"
type = string
default = "us-east-1"
}

# Least-privilege policy for Bedrock
resource "aws_iam_policy" "bedrock_minimal" {
name = "BedrockMinimalAccess"
description = "Minimal permissions for Amazon Bedrock model invocation"

policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "AllowBedrockModelInvocation"
Effect = "Allow"
Action = [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream"
]
Resource = [
"arn:aws:bedrock:${var.aws_region}::foundation-model/*"
]
},
{
Sid = "AllowListModels"
Effect = "Allow"
Action = [
"bedrock:ListFoundationModels",
"bedrock:GetFoundationModel"
]
Resource = "*"
}
]
})
}

# Attach policy to the specified user
resource "aws_iam_user_policy_attachment" "bedrock_minimal" {
user = var.iam_user_name
policy_arn = aws_iam_policy.bedrock_minimal.arn
}

output "policy_arn" {
description = "ARN of the created Bedrock minimal access policy"
value = aws_iam_policy.bedrock_minimal.arn
}

Apply the configuration:

terraform init
terraform apply -var="iam_user_name=<your-iam-user>"

Verification

After remediation, verify the changes took effect:

  1. In the IAM Console, confirm the user no longer has administrative or wildcard Bedrock policies

  2. Re-run the Prowler check to confirm the finding is resolved:

    prowler aws --check bedrock_api_key_no_administrative_privileges
Advanced verification

Use IAM Access Analyzer to simulate API calls and verify permissions are correctly scoped:

# List remaining policies
aws iam list-attached-user-policies \
--user-name <your-iam-user> \
--region us-east-1

aws iam list-user-policies \
--user-name <your-iam-user> \
--region us-east-1

# Simulate a Bedrock action to verify it's allowed
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::<account-id>:user/<your-iam-user> \
--action-names bedrock:InvokeModel \
--region us-east-1

# Simulate an IAM action to verify it's denied
aws iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::<account-id>:user/<your-iam-user> \
--action-names iam:CreateUser \
--region us-east-1

Additional Resources

Notes

  • Scope appropriately: The example policy allows access to all foundation models. If your use case requires only specific models, restrict the Resource element to specific model ARNs (e.g., arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-3-sonnet-20240229-v1:0).

  • Consider custom models: If you use custom Bedrock models, add permissions for your account's model ARNs: arn:aws:bedrock:us-east-1:<account-id>:custom-model/*.

  • Prefer IAM roles: For production workloads, consider using IAM roles with temporary credentials instead of long-lived API keys. This reduces the risk of credential compromise.

  • Enable MFA: If service-specific credentials must be used, ensure the IAM user has MFA enabled and consider adding MFA conditions to the policy.

  • Regular audits: Implement a regular review process for Bedrock API key permissions. Use AWS IAM Access Analyzer to identify unused permissions that can be removed.