KMS key is rotated every 90 days or less
Google Cloud KMS customer-managed keys are rotated with an interval of 90 days or less, in line with the CIS Benchmark.
The evaluation reviews each key's rotation settings to confirm that both the rotation period and the next rotation time stay within 90 days.
Risk
Without timely rotation, a stolen key can decrypt an expanding volume of data, eroding confidentiality. Prolonged key lifetimes widen windows for misuse, impact integrity of protected workloads, and make emergency rollover harder, risking availability disruptions.
Run this check with Prowler
Run in Prowler Cloudprowler gcp --checks kms_key_rotation_max_90_daysRecommendation
Enable auto-rotation for customer-managed keys with an interval of 90 days or less.
Adopt a key lifecycle policy: enforce least privilege on key usage, apply separation of duties between key admins and users, monitor key access, and rehearse emergency rotation to minimize blast radius.
Remediation
CLI
gcloud kms keys update <KEY_NAME> --keyring=<KEY_RING> --location=<LOCATION> --rotation-period=90d --next-rotation-time=<RFC3339_TIME>Terraform
resource "google_kms_crypto_key" "<example_resource_name>" {
name = "<example_resource_name>"
key_ring = "<example_resource_id>"
purpose = "ENCRYPT_DECRYPT"
rotation_period = "7776000s" # Critical: sets automatic rotation to 90 days (<= 90 ensures PASS)
}Other
Check Code
import datetime
from prowler.lib.check.models import Check, Check_Report_GCP
from prowler.providers.gcp.services.kms.kms_client import kms_client
class kms_key_rotation_max_90_days(Check):
def execute(self) -> Check_Report_GCP:
findings = []
for key in kms_client.crypto_keys:
report = Check_Report_GCP(metadata=self.metadata(), resource=key)
now = datetime.datetime.now()
condition_next_rotation_time = False
if key.next_rotation_time:
try:
next_rotation_time = datetime.datetime.strptime(
key.next_rotation_time, "%Y-%m-%dT%H:%M:%S.%fZ"
)
except ValueError:
next_rotation_time = datetime.datetime.strptime(
key.next_rotation_time, "%Y-%m-%dT%H:%M:%SZ"
)
condition_next_rotation_time = (
abs((next_rotation_time - now).days) <= 90
)
condition_rotation_period = False
if key.rotation_period:
condition_rotation_period = (
int(key.rotation_period[:-1]) // (24 * 3600) <= 90
)
if condition_rotation_period and condition_next_rotation_time:
report.status = "PASS"
report.status_extended = f"Key {key.name} is rotated every 90 days or less and the next rotation time is in less than 90 days."
else:
report.status = "FAIL"
if condition_rotation_period:
report.status_extended = f"Key {key.name} is rotated every 90 days or less but the next rotation time is in more than 90 days."
elif condition_next_rotation_time:
report.status_extended = f"Key {key.name} is not rotated every 90 days or less but the next rotation time is in less than 90 days."
else:
report.status_extended = f"Key {key.name} is not rotated every 90 days or less and the next rotation time is in more than 90 days."
findings.append(report)
return findings