Back to Checks
gcp

Cloud KMS key has no public IAM access

kms_key_not_publicly_accessible
Service: kmsSeverity: high
OfficialBuilt-inVerified
Categories:internet-exposedidentity-access
Resource Type:cloudkms.googleapis.com/CryptoKey

Cloud KMS crypto keys are evaluated for public principals in their IAM bindings, specifically allUsers and allAuthenticatedUsers.

The finding reflects whether these memberships are present on a key.

Risk

Granting public principals access lets anyone on the Internet or any Google account use permissions on the key.

  • Confidentiality loss via unauthorized decrypt
  • Integrity compromise via illicit sign
  • Availability impact from disable, rotation, or destruction

Run this check with Prowler

Run in Prowler Cloud
Run
prowler gcp --checks kms_key_not_publicly_accessible

Recommendation

Remove allUsers and allAuthenticatedUsers from key IAM. Grant access only to specific groups or service accounts with least privilege at the key scope. Enforce separation of duties between admins and users, and regularly review inherited bindings and audit logs.

Remediation

Terraform

# Replace the IAM policy on the KMS key to remove any public members
resource "google_kms_crypto_key_iam_policy" "<example_resource_name>" {
  crypto_key_id = "<example_resource_id>"
  
  policy_data = jsonencode({
    bindings = [] # Critical: empty bindings remove all IAM principals, eliminating allUsers/allAuthenticatedUsers
  })
}

Other

1In Google Cloud Console, go to Security > Key Management > Key rings
2Open the key ring, then select the affected key
3Click the Permissions tab
4Remove principals "allUsers" and "allAuthenticatedUsers" from all roles
5Click Save

Check Code

from prowler.lib.check.models import Check, Check_Report_GCP
from prowler.providers.gcp.services.kms.kms_client import kms_client


class kms_key_not_publicly_accessible(Check):
    def execute(self) -> Check_Report_GCP:
        findings = []
        for key in kms_client.crypto_keys:
            report = Check_Report_GCP(metadata=self.metadata(), resource=key)
            report.status = "PASS"
            report.status_extended = f"Key {key.name} is not exposed to Public."
            for member in key.members:
                if member == "allUsers" or member == "allAuthenticatedUsers":
                    report.status = "FAIL"
                    report.status_extended = (
                        f"Key {key.name} may be publicly accessible."
                    )
            findings.append(report)

        return findings