mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-11-10 11:51:29 +00:00
feat(gcp): split kms_key_rotation_enabled into enabled and max-90-days checks (#11516)
This commit is contained in:
1 parent
e710ebff1c
commit
9a50dffaa0
13 files changed
+841
-499
No files matched your search
@@ -17,6 +17,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
|
||||
- External multi-provider compliance frameworks can be registered via the `prowler.compliance.universal` entry point group [(#11490)](https://github.com/prowler-cloud/prowler/pull/11490)
|
||||
- AWS AI Security Framework support in the CLI dashboard [(#11475)](https://github.com/prowler-cloud/prowler/pull/11475)
|
||||
- `entra_service_principal_privileged_role_no_owners` check for M365 provider, failing when a service principal with a permanent Tier 0 directory role has owners on the service principal or its parent app registration [(#11070)](https://github.com/prowler-cloud/prowler/issues/11070)
|
||||
- `kms_key_rotation_max_90_days` check for GCP provider, verifying KMS customer-managed keys are rotated every 90 days or less in line with the CIS Benchmark [(#11516)](https://github.com/prowler-cloud/prowler/pull/11516)
|
||||
- `exchange_mailbox_primary_smtp_uses_custom_domain` check for M365 provider [(#11215)](https://github.com/prowler-cloud/prowler/pull/11215)
|
||||
|
||||
### 🐞 Fixed
|
||||
@@ -24,6 +25,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
|
||||
- `load_and_validate_config_file` now unwraps namespaced config for every built-in and external provider, and no longer leaks the full file as the provider's config when the file is namespaced [(#10700)](https://github.com/prowler-cloud/prowler/pull/10700)
|
||||
- `entra_users_mfa_capable` no longer flags pre-provisioned users with future `employeeHireDate`; future-hire date comparisons now tolerate naive datetimes [(#11511)](https://github.com/prowler-cloud/prowler/pull/11511)
|
||||
- M365 Admin Center group enumeration now follows Microsoft Graph pagination so group-scoped checks include groups beyond the first page [(#11510)](https://github.com/prowler-cloud/prowler/pull/11510)
|
||||
- GCP `kms_key_rotation_enabled` check now only verifies that automatic key rotation is enabled (any interval) instead of enforcing a 90-day period, resolving the mismatch between the check and its documentation; the CIS, Prowler ThreatScore, and CCC requirements that mandate a 90-day maximum were remapped to the new `kms_key_rotation_max_90_days` check [(#11516)](https://github.com/prowler-cloud/prowler/pull/11516)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -889,7 +889,7 @@
|
||||
}
|
||||
],
|
||||
"Checks": [
|
||||
"kms_key_rotation_enabled"
|
||||
"kms_key_rotation_max_90_days"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -150,7 +150,7 @@
|
||||
"Id": "1.10",
|
||||
"Description": "Google Cloud Key Management Service stores cryptographic keys in a hierarchical structure designed for useful and elegant access control management. The format for the rotation schedule depends on the client library that is used. For the gcloud command-line tool, the next rotation time must be in `ISO` or `RFC3339` format, and the rotation period must be in the form `INTEGERUNIT`, where units can be one of seconds (s), minutes (m), hours (h) or days (d).",
|
||||
"Checks": [
|
||||
"kms_key_rotation_enabled"
|
||||
"kms_key_rotation_max_90_days"
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
|
||||
@@ -201,7 +201,7 @@
|
||||
"Id": "1.10",
|
||||
"Description": "Ensure KMS Encryption Keys Are Rotated Within a Period of 90 Days",
|
||||
"Checks": [
|
||||
"kms_key_rotation_enabled"
|
||||
"kms_key_rotation_max_90_days"
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
|
||||
@@ -201,7 +201,7 @@
|
||||
"Id": "1.10",
|
||||
"Description": "Ensure KMS Encryption Keys Are Rotated Within a Period of 90 Days",
|
||||
"Checks": [
|
||||
"kms_key_rotation_enabled"
|
||||
"kms_key_rotation_max_90_days"
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
"Id": "1.2.4",
|
||||
"Description": "Ensure KMS Encryption Keys Are Rotated Within a Period of 90 Days",
|
||||
"Checks": [
|
||||
"kms_key_rotation_enabled"
|
||||
"kms_key_rotation_max_90_days"
|
||||
],
|
||||
"Attributes": [
|
||||
{
|
||||
|
||||
+9
-7
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"Provider": "gcp",
|
||||
"CheckID": "kms_key_rotation_enabled",
|
||||
"CheckTitle": "KMS key is rotated at least annually",
|
||||
"CheckTitle": "KMS key has automatic rotation enabled",
|
||||
"CheckType": [],
|
||||
"ServiceName": "kms",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "low",
|
||||
"ResourceType": "cloudkms.googleapis.com/CryptoKey",
|
||||
"Description": "Google Cloud KMS customer-managed keys have **automatic rotation** enabled or a rotation interval `365` days.\n\nThe evaluation reviews each key's rotation settings to confirm periodic creation of new key versions.",
|
||||
"Description": "Google Cloud KMS customer-managed keys have **automatic rotation** enabled, regardless of the rotation interval.\n\nThe evaluation reviews each key's rotation settings to confirm that a rotation period is configured so new key versions are created periodically.",
|
||||
"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.",
|
||||
"RelatedUrl": "",
|
||||
"AdditionalURLs": [
|
||||
@@ -17,13 +17,13 @@
|
||||
],
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "gcloud kms keys update <KEY_NAME> --keyring=<KEY_RING> --location=<LOCATION> --rotation-period=365d --next-rotation-time=<RFC3339_TIME>",
|
||||
"CLI": "gcloud kms keys update <KEY_NAME> --keyring=<KEY_RING> --location=<LOCATION> --rotation-period=<PERIOD> --next-rotation-time=<RFC3339_TIME>",
|
||||
"NativeIaC": "",
|
||||
"Other": "1. In Google Cloud Console, go to Security > Key Management > Key rings\n2. Open the key ring and select the key\n3. Click Edit rotation schedule (or Set rotation schedule)\n4. Set Rotation period to 365 days or less\n5. Set Next rotation date/time\n6. Click Save",
|
||||
"Terraform": "```hcl\nresource \"google_kms_crypto_key\" \"<example_resource_name>\" {\n name = \"<example_resource_name>\"\n key_ring = \"<example_resource_id>\"\n purpose = \"ENCRYPT_DECRYPT\"\n\n rotation_period = \"31536000s\" # Critical: sets automatic rotation to 365 days (<= 365 ensures PASS)\n}\n```"
|
||||
"Other": "1. In Google Cloud Console, go to Security > Key Management > Key rings\n2. Open the key ring and select the key\n3. Click Edit rotation schedule (or Set rotation schedule)\n4. Set a Rotation period\n5. Set Next rotation date/time\n6. Click Save",
|
||||
"Terraform": "```hcl\nresource \"google_kms_crypto_key\" \"<example_resource_name>\" {\n name = \"<example_resource_name>\"\n key_ring = \"<example_resource_id>\"\n purpose = \"ENCRYPT_DECRYPT\"\n\n rotation_period = \"7776000s\" # Critical: enables automatic rotation (any period ensures PASS)\n}\n```"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Enable **auto-rotation** for customer-managed keys with an interval `365` days.\n\nAdopt 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.",
|
||||
"Text": "Enable **auto-rotation** for customer-managed keys by configuring a rotation period.\n\nAdopt 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.",
|
||||
"Url": "https://hub.prowler.com/check/kms_key_rotation_enabled"
|
||||
}
|
||||
},
|
||||
@@ -31,6 +31,8 @@
|
||||
"encryption"
|
||||
],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"RelatedTo": [
|
||||
"kms_key_rotation_max_90_days"
|
||||
],
|
||||
"Notes": ""
|
||||
}
|
||||
+6
-28
@@ -1,5 +1,3 @@
|
||||
import datetime
|
||||
|
||||
from prowler.lib.check.models import Check, Check_Report_GCP
|
||||
from prowler.providers.gcp.services.kms.kms_client import kms_client
|
||||
|
||||
@@ -9,36 +7,16 @@ class kms_key_rotation_enabled(Check):
|
||||
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."
|
||||
report.status_extended = (
|
||||
f"Key {key.name} has automatic rotation enabled."
|
||||
)
|
||||
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."
|
||||
report.status_extended = (
|
||||
f"Key {key.name} does not have automatic rotation enabled."
|
||||
)
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
Whitespace-only changes.
+38
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"Provider": "gcp",
|
||||
"CheckID": "kms_key_rotation_max_90_days",
|
||||
"CheckTitle": "KMS key is rotated every 90 days or less",
|
||||
"CheckType": [],
|
||||
"ServiceName": "kms",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "low",
|
||||
"ResourceType": "cloudkms.googleapis.com/CryptoKey",
|
||||
"Description": "Google Cloud KMS customer-managed keys are rotated with an interval of `90` days or less, in line with the CIS Benchmark.\n\nThe 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.",
|
||||
"RelatedUrl": "",
|
||||
"AdditionalURLs": [
|
||||
"https://www.trendmicro.com/trendaivisiononecloudriskmanagement/knowledge-base/gcp/CloudKMS/rotate-kms-encryption-keys.html",
|
||||
"https://cloud.google.com/iam/docs/manage-access-service-accounts"
|
||||
],
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "gcloud kms keys update <KEY_NAME> --keyring=<KEY_RING> --location=<LOCATION> --rotation-period=90d --next-rotation-time=<RFC3339_TIME>",
|
||||
"NativeIaC": "",
|
||||
"Other": "1. In Google Cloud Console, go to Security > Key Management > Key rings\n2. Open the key ring and select the key\n3. Click Edit rotation schedule (or Set rotation schedule)\n4. Set Rotation period to 90 days or less\n5. Set Next rotation date/time\n6. Click Save",
|
||||
"Terraform": "```hcl\nresource \"google_kms_crypto_key\" \"<example_resource_name>\" {\n name = \"<example_resource_name>\"\n key_ring = \"<example_resource_id>\"\n purpose = \"ENCRYPT_DECRYPT\"\n\n rotation_period = \"7776000s\" # Critical: sets automatic rotation to 90 days (<= 90 ensures PASS)\n}\n```"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Enable **auto-rotation** for customer-managed keys with an interval of `90` days or less.\n\nAdopt 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.",
|
||||
"Url": "https://hub.prowler.com/check/kms_key_rotation_max_90_days"
|
||||
}
|
||||
},
|
||||
"Categories": [
|
||||
"encryption"
|
||||
],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [
|
||||
"kms_key_rotation_enabled"
|
||||
],
|
||||
"Notes": ""
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
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
|
||||
Reference in new issue
Block a user