diff --git a/prowler/providers/aws/services/kms/kms_cmk_not_deleted_unintentionally/kms_cmk_not_deleted_unintentionally_fixer.py b/prowler/providers/aws/services/kms/kms_cmk_not_deleted_unintentionally/kms_cmk_not_deleted_unintentionally_fixer.py new file mode 100644 index 0000000000..fafcc50563 --- /dev/null +++ b/prowler/providers/aws/services/kms/kms_cmk_not_deleted_unintentionally/kms_cmk_not_deleted_unintentionally_fixer.py @@ -0,0 +1,39 @@ +from prowler.lib.logger import logger +from prowler.providers.aws.services.kms.kms_client import kms_client + + +def fixer(resource_id: str, region: str) -> bool: + """ + Cancel the scheduled deletion of a KMS key. + Specifically, this fixer calls the 'cancel_key_deletion' method to restore the KMS key's availability if it is marked for deletion. + Requires the kms:CancelKeyDeletion permission. + + Permissions: + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": "kms:CancelKeyDeletion", + "Resource": "*" + } + ] + } + + Args: + resource_id (str): The ID of the KMS key to cancel the deletion for. + region (str): AWS region where the KMS key exists. + + Returns: + bool: True if the operation is successful (deletion cancellation is completed), False otherwise. + """ + try: + regional_client = kms_client.regional_clients[region] + regional_client.cancel_key_deletion(KeyId=resource_id) + except Exception as error: + logger.error( + f"{region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + return False + else: + return True diff --git a/tests/providers/aws/services/kms/kms_cmk_not_deleted_unintentionally/kms_cmk_not_deleted_unintentionally_fixer_test.py b/tests/providers/aws/services/kms/kms_cmk_not_deleted_unintentionally/kms_cmk_not_deleted_unintentionally_fixer_test.py new file mode 100644 index 0000000000..47ff98d8f4 --- /dev/null +++ b/tests/providers/aws/services/kms/kms_cmk_not_deleted_unintentionally/kms_cmk_not_deleted_unintentionally_fixer_test.py @@ -0,0 +1,77 @@ +from unittest import mock + +from boto3 import client +from moto import mock_aws + +from tests.providers.aws.utils import AWS_REGION_US_EAST_1, set_mocked_aws_provider + + +class Test_kms_cmk_not_deleted_unintentionally_fixer: + @mock_aws + def test_kms_cmk_deleted_unintentionally(self): + from prowler.providers.aws.services.kms.kms_service import KMS + + kms_client = client("kms", region_name=AWS_REGION_US_EAST_1) + key = kms_client.create_key()["KeyMetadata"] + kms_client.schedule_key_deletion(KeyId=key["KeyId"]) + + aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1]) + + with mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), mock.patch( + "prowler.providers.aws.services.kms.kms_cmk_not_deleted_unintentionally.kms_cmk_not_deleted_unintentionally_fixer.kms_client", + new=KMS(aws_provider), + ): + from prowler.providers.aws.services.kms.kms_cmk_not_deleted_unintentionally.kms_cmk_not_deleted_unintentionally_fixer import ( + fixer, + ) + + assert fixer(key["KeyId"], AWS_REGION_US_EAST_1) + + @mock_aws + def test_kms_cmk_enabled(self): + from prowler.providers.aws.services.kms.kms_service import KMS + + kms_client = client("kms", region_name=AWS_REGION_US_EAST_1) + key = kms_client.create_key()["KeyMetadata"] + kms_client.enable_key(KeyId=key["KeyId"]) + + aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1]) + + with mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), mock.patch( + "prowler.providers.aws.services.kms.kms_cmk_not_deleted_unintentionally.kms_cmk_not_deleted_unintentionally_fixer.kms_client", + new=KMS(aws_provider), + ): + from prowler.providers.aws.services.kms.kms_cmk_not_deleted_unintentionally.kms_cmk_not_deleted_unintentionally_fixer import ( + fixer, + ) + + assert fixer(key["KeyId"], AWS_REGION_US_EAST_1) + + @mock_aws + def test_kms_cmk_deleted_unintentionally_error(self): + from prowler.providers.aws.services.kms.kms_service import KMS + + kms_client = client("kms", region_name=AWS_REGION_US_EAST_1) + key = kms_client.create_key()["KeyMetadata"] + kms_client.schedule_key_deletion(KeyId=key["KeyId"]) + + aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1]) + + with mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), mock.patch( + "prowler.providers.aws.services.kms.kms_cmk_not_deleted_unintentionally.kms_cmk_not_deleted_unintentionally_fixer.kms_client", + new=KMS(aws_provider), + ): + from prowler.providers.aws.services.kms.kms_cmk_not_deleted_unintentionally.kms_cmk_not_deleted_unintentionally_fixer import ( + fixer, + ) + + assert not fixer("KeyIdNonExisting", AWS_REGION_US_EAST_1)