Back to Checks
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 CloudRun
prowler gcp --checks kms_key_not_publicly_accessibleRecommendation
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