Back to Checks
Custom IAM policy does not allow 'kms:*' privileges
iam_policy_no_full_access_to_kms
Service: iamSeverity: medium
OfficialBuilt-inVerified
Categories:identity-access
Resource Type:AwsIamPolicy
Customer-managed IAM policies are examined for statements that grant AWS KMS full access using kms:*. The focus is on policies allowing service-wide actions rather than narrowly scoped, key-specific permissions.
Risk
Allowing kms:* lets principals decrypt data, change key policies, and disable or delete keys. Impact: Confidentiality-unauthorized decryption; Integrity-manipulation of cryptographic controls; Availability-data unreadable if keys are disabled/deleted. It can also enable privilege escalation.
Run this check with Prowler
Run in Prowler CloudRun
prowler aws --checks iam_policy_no_full_access_to_kmsRecommendation
Adopt least privilege and separation of duties:
- Replace
kms:*with only needed actions scoped to specific key ARNs - Apply policy conditions (e.g.,
kms:ViaService) and guardrails (permissions boundaries/SCPs) - Monitor KMS usage and refine access based on activity
Remediation
CLI
aws iam create-policy-version --policy-arn <POLICY_ARN> --policy-document '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":["kms:Encrypt"],"Resource":"arn:aws:kms:<REGION>:<ACCOUNT_ID>:key/<KEY_ID>"}]}' --set-as-defaultTerraform
# Customer managed policy without kms:* full access
resource "aws_iam_policy" "<example_resource_name>" {
name = "<example_resource_name>"
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = ["kms:Encrypt"] # FIX: remove 'kms:*'; allow only specific KMS action
Resource = "arn:aws:kms:<REGION>:<ACCOUNT_ID>:key/<example_resource_id>" # FIX: scope to a specific key
}]
})
}NativeIaC
# CloudFormation: customer managed policy without kms:* full access
Resources:
<example_resource_name>:
Type: AWS::IAM::ManagedPolicy
Properties:
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- kms:Encrypt # FIX: remove 'kms:*'; allow only specific KMS action
Resource: arn:aws:kms:<REGION>:<ACCOUNT_ID>:key/<example_resource_id> # FIX: scope to a specific keyOther
1In the AWS Console, open IAM > Policies
2Find the custom policy that allows kms:* and choose Edit policy > JSON
3Replace any "Action": "kms:*" (or ["kms:*"]) with only required actions (e.g., ["kms:Encrypt"]) and, if possible, set "Resource" to a specific key ARN
4Save changes (a new default policy version is created)
5Re-run the check to confirm it passes
Check Code
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.iam.iam_client import iam_client
from prowler.providers.aws.services.iam.lib.policy import check_full_service_access
critical_service = "kms"
class iam_policy_no_full_access_to_kms(Check):
def execute(self) -> Check_Report_AWS:
findings = []
for policy in iam_client.policies.values():
# Check only custom policies
if policy.type == "Custom":
if not policy.attached and not iam_client.provider.scan_unused_services:
continue
report = Check_Report_AWS(metadata=self.metadata(), resource=policy)
report.region = iam_client.region
report.status = "PASS"
report.status_extended = f"Custom Policy {policy.name} does not allow '{critical_service}:*' privileges."
if policy.document and check_full_service_access(
critical_service, policy.document
):
report.status = "FAIL"
report.status_extended = f"Custom Policy {policy.name} allows '{critical_service}:*' privileges."
findings.append(report)
return findings