Back to Checks
gcp

KMS key is rotated every 90 days or less

kms_key_rotation_max_90_days
Service: kmsSeverity: low
OfficialBuilt-inVerified
Categories:encryption
Resource Type:cloudkms.googleapis.com/CryptoKey

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 Cloud
Run
prowler gcp --checks kms_key_rotation_max_90_days

Recommendation

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

1In Google Cloud Console, go to Security > Key Management > Key rings
2Open the key ring and select the key
3Click Edit rotation schedule (or Set rotation schedule)
4Set Rotation period to 90 days or less
5Set Next rotation date/time
6Click Save

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