From c3ff8c368c2052c495edbae35b445fbc8c2391e5 Mon Sep 17 00:00:00 2001 From: MarioRgzLpz Date: Fri, 26 Jul 2024 09:53:25 +0200 Subject: [PATCH 01/14] chore(acm): Add RSA key length check --- .../__init__.py | 0 ..._certificates_rsa_key_length.metadata.json | 32 +++++++++++++++++++ .../acm_certificates_rsa_key_length.py | 24 ++++++++++++++ .../providers/aws/services/acm/acm_service.py | 2 ++ 4 files changed, 58 insertions(+) create mode 100644 prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/__init__.py create mode 100644 prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.metadata.json create mode 100644 prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.py diff --git a/prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/__init__.py b/prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.metadata.json b/prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.metadata.json new file mode 100644 index 00000000000..3b83b3e65b9 --- /dev/null +++ b/prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.metadata.json @@ -0,0 +1,32 @@ +{ + "Provider": "aws", + "CheckID": "acm_certificates_rsa_key_length", + "CheckTitle": "Check if ACM Certificates use a secure RSA key size", + "CheckType": [ + "Data Protection" + ], + "ServiceName": "acm", + "SubServiceName": "", + "ResourceIdTemplate": "arn:partition:acm:region:account-id:certificate/resource-id", + "Severity": "high", + "ResourceType": "AwsCertificateManagerCertificate", + "Description": "Check if ACM Certificates use a secure RSA key size", + "Risk": "Certificates with weak RSA keys can be compromised.", + "RelatedUrl": "https://docs.aws.amazon.com/es_es/acm/latest/userguide/acm-certificate.html", + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "", + "Terraform": "" + }, + "Recommendation": { + "Text": "Ensure that all ACM certificates use RSA keys of at least 2048 bits. If any certificates use smaller keys, regenerate them with a secure key size and update any systems that rely on these certificates.", + "Url": "https://docs.aws.amazon.com/es_es/acm/latest/userguide/acm-certificate.html" + } + }, + "Categories": [], + "DependsOn": [], + "RelatedTo": [], + "Notes": "" +} diff --git a/prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.py b/prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.py new file mode 100644 index 00000000000..be82dfe0651 --- /dev/null +++ b/prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.py @@ -0,0 +1,24 @@ +from prowler.lib.check.models import Check, Check_Report_AWS +from prowler.providers.aws.services.acm.acm_client import acm_client + + +class acm_certificates_rsa_key_length(Check): + def execute(self): + findings = [] + for certificate in acm_client.certificates: + report = Check_Report_AWS(self.metadata()) + report.region = certificate.region + report.resource_id = certificate.id + report.resource_details = certificate.name + report.resource_arn = certificate.arn + report.resource_tags = certificate.tags + + report.status = "PASS" + report.status_extended = f"ACM Certificate {certificate.id} for {certificate.name} meet minimum key size requirements." + + if certificate.key_algorithm == "RSA_1024": + report.status = "FAIL" + report.status_extended = f"ACM Certificate {certificate.id} for {certificate.name} uses RSA_1024 which is not secure enough." + findings.append(report) + + return findings diff --git a/prowler/providers/aws/services/acm/acm_service.py b/prowler/providers/aws/services/acm/acm_service.py index 7ded45a7965..131909c28d5 100644 --- a/prowler/providers/aws/services/acm/acm_service.py +++ b/prowler/providers/aws/services/acm/acm_service.py @@ -49,6 +49,7 @@ def __list_certificates__(self, regional_client): name=certificate["DomainName"], id=certificate["CertificateArn"].split("/")[-1], type=certificate["Type"], + key_algorithm=certificate["KeyAlgorithm"], expiration_days=certificate_expiration_time, in_use=certificate.get("InUse", False), transparency_logging=False, @@ -98,6 +99,7 @@ class Certificate(BaseModel): name: str id: str type: str + key_algorithm: str tags: Optional[list] = [] expiration_days: int in_use: bool From 52a4224da9b033c22154c21c0cddbd8acc634912 Mon Sep 17 00:00:00 2001 From: MarioRgzLpz Date: Fri, 26 Jul 2024 09:57:19 +0200 Subject: [PATCH 02/14] test(acm): Add RSA key length check tests --- .../acm_certificates_rsa_key_length_test.py | 117 ++++++++++++++++++ .../aws/services/acm/acm_service_test.py | 2 + 2 files changed, 119 insertions(+) create mode 100644 tests/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length_test.py diff --git a/tests/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length_test.py b/tests/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length_test.py new file mode 100644 index 00000000000..e1199ffa7ca --- /dev/null +++ b/tests/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length_test.py @@ -0,0 +1,117 @@ +import uuid +from unittest import mock + +from prowler.providers.aws.services.acm.acm_service import Certificate + +AWS_REGION = "us-east-1" +AWS_ACCOUNT_NUMBER = "123456789012" + + +class Test_acm_certificates_rsa_key_length: + def test_no_acm_certificates(self): + acm_client = mock.MagicMock + acm_client.certificates = [] + + with mock.patch( + "prowler.providers.aws.services.acm.acm_service.ACM", + new=acm_client, + ): + # Test Check + from prowler.providers.aws.services.acm.acm_certificates_rsa_key_length.acm_certificates_rsa_key_length import ( + acm_certificates_rsa_key_length, + ) + + check = acm_certificates_rsa_key_length() + result = check.execute() + + assert len(result) == 0 + + def test_acm_certificate_valid_key_length(self): + certificate_id = str(uuid.uuid4()) + certificate_arn = f"arn:aws:acm:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:certificate/{certificate_id}" + certificate_name = "test-certificate.com" + certificate_type = "AMAZON_ISSUED" + certificate_key_algorithm = "RSA_2048" + + acm_client = mock.MagicMock + acm_client.certificates = [ + Certificate( + arn=certificate_arn, + id=certificate_id, + name=certificate_name, + type=certificate_type, + key_algorithm=certificate_key_algorithm, + expiration_days=365, + transparency_logging=True, + in_use=True, + region=AWS_REGION, + ) + ] + + with mock.patch( + "prowler.providers.aws.services.acm.acm_service.ACM", + new=acm_client, + ): + # Test Check + from prowler.providers.aws.services.acm.acm_certificates_rsa_key_length.acm_certificates_rsa_key_length import ( + acm_certificates_rsa_key_length, + ) + + check = acm_certificates_rsa_key_length() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"ACM Certificate {certificate_id} for {certificate_name} meet minimum key size requirements." + ) + assert result[0].resource_id == certificate_id + assert result[0].resource_arn == certificate_arn + assert result[0].region == AWS_REGION + assert result[0].resource_tags == [] + + def test_acm_certificate_short_RSA_key(self): + certificate_id = str(uuid.uuid4()) + certificate_arn = f"arn:aws:acm:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:certificate/{certificate_id}" + certificate_name = "test-certificate.com" + certificate_type = "AMAZON_ISSUED" + certificate_key_algorithm = "RSA_1024" + + acm_client = mock.MagicMock + acm_client.certificates = [ + Certificate( + arn=certificate_arn, + id=certificate_id, + name=certificate_name, + type=certificate_type, + key_algorithm=certificate_key_algorithm, + expiration_days=365, + transparency_logging=False, + in_use=True, + region=AWS_REGION, + ) + ] + + with mock.patch( + "prowler.providers.aws.services.acm.acm_service.ACM", + new=acm_client, + ): + # Test Check + from prowler.providers.aws.services.acm.acm_certificates_rsa_key_length.acm_certificates_rsa_key_length import ( + acm_certificates_rsa_key_length, + ) + + check = acm_certificates_rsa_key_length() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"ACM Certificate {certificate_id} for {certificate_name} uses RSA_1024 which is not secure enough." + ) + assert result[0].resource_id == certificate_id + assert result[0].resource_arn == certificate_arn + assert result[0].region == AWS_REGION + assert result[0].resource_tags == [] diff --git a/tests/providers/aws/services/acm/acm_service_test.py b/tests/providers/aws/services/acm/acm_service_test.py index 1ba8f6f9285..5f7fd182a34 100644 --- a/tests/providers/aws/services/acm/acm_service_test.py +++ b/tests/providers/aws/services/acm/acm_service_test.py @@ -18,6 +18,7 @@ certificate_arn = f"arn:aws:acm:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:certificate/{str(uuid.uuid4())}" certificate_name = "test-certificate.com" certificate_type = "AMAZON_ISSUED" +certificate_key_algorithm = "RSA_4096" def mock_make_api_call(self, operation_name, kwargs): @@ -142,6 +143,7 @@ def test__list_and_describe_certificates__(self): assert acm.certificates[0].arn == certificate_arn assert acm.certificates[0].name == certificate_name assert acm.certificates[0].type == certificate_type + assert acm.certificates[0].key_algorithm == certificate_key_algorithm assert acm.certificates[0].expiration_days == 365 assert acm.certificates[0].transparency_logging is False assert acm.certificates[0].region == AWS_REGION_US_EAST_1 From 8ea0807d9ce1da91c64fe22b4c5ed5e5e483dcda Mon Sep 17 00:00:00 2001 From: MarioRgzLpz Date: Fri, 26 Jul 2024 13:32:23 +0200 Subject: [PATCH 03/14] test(acm): Add the new atributte key_algorithm to old tests --- .../acm_certificates_expiration_check_test.py | 10 ++++++++++ .../acm_certificates_transparency_logs_enabled_test.py | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/tests/providers/aws/services/acm/acm_certificates_expiration_check/acm_certificates_expiration_check_test.py b/tests/providers/aws/services/acm/acm_certificates_expiration_check/acm_certificates_expiration_check_test.py index b8e9c1b7b42..157d4366c2f 100644 --- a/tests/providers/aws/services/acm/acm_certificates_expiration_check/acm_certificates_expiration_check_test.py +++ b/tests/providers/aws/services/acm/acm_certificates_expiration_check/acm_certificates_expiration_check_test.py @@ -32,6 +32,7 @@ def test_acm_certificate_expirated(self): certificate_arn = f"arn:aws:acm:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:certificate/{certificate_id}" certificate_name = "test-certificate.com" certificate_type = "AMAZON_ISSUED" + certificate_key_algorithm = "RSA_2048" expiration_days = 5 in_use = True @@ -42,6 +43,7 @@ def test_acm_certificate_expirated(self): id=certificate_id, name=certificate_name, type=certificate_type, + key_algorithm=certificate_key_algorithm, expiration_days=expiration_days, in_use=in_use, transparency_logging=True, @@ -80,6 +82,7 @@ def test_acm_certificate_expirated_long_time(self): certificate_arn = f"arn:aws:acm:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:certificate/{certificate_id}" certificate_name = "test-certificate.com" certificate_type = "AMAZON_ISSUED" + certificate_key_algorithm = "RSA_2048" expiration_days = -400 in_use = True @@ -90,6 +93,7 @@ def test_acm_certificate_expirated_long_time(self): id=certificate_id, name=certificate_name, type=certificate_type, + key_algorithm=certificate_key_algorithm, expiration_days=expiration_days, in_use=in_use, transparency_logging=True, @@ -127,6 +131,7 @@ def test_acm_certificate_not_expirated(self): certificate_arn = f"arn:aws:acm:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:certificate/{certificate_id}" certificate_name = "test-certificate.com" certificate_type = "AMAZON_ISSUED" + certificate_key_algorithm = "RSA_2048" expiration_days = 365 in_use = True @@ -137,6 +142,7 @@ def test_acm_certificate_not_expirated(self): id=certificate_id, name=certificate_name, type=certificate_type, + key_algorithm=certificate_key_algorithm, expiration_days=expiration_days, in_use=in_use, transparency_logging=True, @@ -173,6 +179,7 @@ def test_acm_certificate_not_in_use(self): certificate_arn = f"arn:aws:acm:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:certificate/{certificate_id}" certificate_name = "test-certificate.com" certificate_type = "AMAZON_ISSUED" + certificate_key_algorithm = "RSA_2048" expiration_days = 365 in_use = False @@ -183,6 +190,7 @@ def test_acm_certificate_not_in_use(self): id=certificate_id, name=certificate_name, type=certificate_type, + key_algorithm=certificate_key_algorithm, expiration_days=expiration_days, in_use=in_use, transparency_logging=True, @@ -212,6 +220,7 @@ def test_acm_certificate_not_in_use_expired_scan_unused_services(self): certificate_arn = f"arn:aws:acm:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:certificate/{certificate_id}" certificate_name = "test-certificate.com" certificate_type = "AMAZON_ISSUED" + certificate_key_algorithm = "RSA_2048" expiration_days = -400 in_use = False @@ -222,6 +231,7 @@ def test_acm_certificate_not_in_use_expired_scan_unused_services(self): id=certificate_id, name=certificate_name, type=certificate_type, + key_algorithm=certificate_key_algorithm, expiration_days=expiration_days, in_use=in_use, transparency_logging=True, diff --git a/tests/providers/aws/services/acm/acm_certificates_transparency_logs_enabled/acm_certificates_transparency_logs_enabled_test.py b/tests/providers/aws/services/acm/acm_certificates_transparency_logs_enabled/acm_certificates_transparency_logs_enabled_test.py index 829ebb20c4b..7e801ab7068 100644 --- a/tests/providers/aws/services/acm/acm_certificates_transparency_logs_enabled/acm_certificates_transparency_logs_enabled_test.py +++ b/tests/providers/aws/services/acm/acm_certificates_transparency_logs_enabled/acm_certificates_transparency_logs_enabled_test.py @@ -31,6 +31,7 @@ def test_acm_certificate_with_logging(self): certificate_arn = f"arn:aws:acm:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:certificate/{certificate_id}" certificate_name = "test-certificate.com" certificate_type = "AMAZON_ISSUED" + certificate_key_algorithm = "RSA_2048" acm_client = mock.MagicMock acm_client.certificates = [ @@ -39,6 +40,7 @@ def test_acm_certificate_with_logging(self): id=certificate_id, name=certificate_name, type=certificate_type, + key_algorithm=certificate_key_algorithm, expiration_days=365, transparency_logging=True, in_use=True, @@ -74,6 +76,7 @@ def test_acm_certificate_without_logging(self): certificate_arn = f"arn:aws:acm:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:certificate/{certificate_id}" certificate_name = "test-certificate.com" certificate_type = "AMAZON_ISSUED" + certificate_key_algorithm = "RSA_2048" acm_client = mock.MagicMock acm_client.certificates = [ @@ -82,6 +85,7 @@ def test_acm_certificate_without_logging(self): id=certificate_id, name=certificate_name, type=certificate_type, + key_algorithm=certificate_key_algorithm, expiration_days=365, transparency_logging=False, in_use=True, @@ -116,6 +120,7 @@ def test_acm_certificate_imported(self): certificate_id = str(uuid.uuid4()) certificate_arn = f"arn:aws:acm:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:certificate/{certificate_id}" certificate_name = "test-certificate.com" + certificate_key_algorithm = "RSA_2048" certificate_type = "IMPORTED" acm_client = mock.MagicMock @@ -125,6 +130,7 @@ def test_acm_certificate_imported(self): id=certificate_id, name=certificate_name, type=certificate_type, + key_algorithm=certificate_key_algorithm, expiration_days=365, transparency_logging=True, in_use=True, From 4d9d8f394557bbe2a554c2ffc8a6046d9baa44e9 Mon Sep 17 00:00:00 2001 From: MarioRgzLpz Date: Fri, 26 Jul 2024 14:11:54 +0200 Subject: [PATCH 04/14] feat(acm): Add a list of insecure algorithms instead of verifying only RSA_1024 --- .../acm_certificates_rsa_key_length.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.py b/prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.py index be82dfe0651..c86ef7bf6b9 100644 --- a/prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.py +++ b/prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.py @@ -3,6 +3,8 @@ class acm_certificates_rsa_key_length(Check): + insecure_algorithms = ["RSA_1024"] + def execute(self): findings = [] for certificate in acm_client.certificates: @@ -16,7 +18,7 @@ def execute(self): report.status = "PASS" report.status_extended = f"ACM Certificate {certificate.id} for {certificate.name} meet minimum key size requirements." - if certificate.key_algorithm == "RSA_1024": + if certificate.key_algorithm in self.insecure_algorithms: report.status = "FAIL" report.status_extended = f"ACM Certificate {certificate.id} for {certificate.name} uses RSA_1024 which is not secure enough." findings.append(report) From 74786c73ecbc14a150b29733ea9fcda4c57d48ec Mon Sep 17 00:00:00 2001 From: MarioRgzLpz Date: Mon, 29 Jul 2024 09:51:49 +0200 Subject: [PATCH 05/14] fix(acm): Change the URLs for the SecurityHub ones --- .../acm_certificates_rsa_key_length.metadata.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.metadata.json b/prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.metadata.json index 3b83b3e65b9..aaaf3151a7b 100644 --- a/prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.metadata.json +++ b/prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.metadata.json @@ -12,7 +12,7 @@ "ResourceType": "AwsCertificateManagerCertificate", "Description": "Check if ACM Certificates use a secure RSA key size", "Risk": "Certificates with weak RSA keys can be compromised.", - "RelatedUrl": "https://docs.aws.amazon.com/es_es/acm/latest/userguide/acm-certificate.html", + "RelatedUrl": "https://docs.aws.amazon.com/securityhub/latest/userguide/acm-controls.html#acm-2", "Remediation": { "Code": { "CLI": "", @@ -22,7 +22,7 @@ }, "Recommendation": { "Text": "Ensure that all ACM certificates use RSA keys of at least 2048 bits. If any certificates use smaller keys, regenerate them with a secure key size and update any systems that rely on these certificates.", - "Url": "https://docs.aws.amazon.com/es_es/acm/latest/userguide/acm-certificate.html" + "Url": "https://docs.aws.amazon.com/securityhub/latest/userguide/acm-controls.html#acm-2" } }, "Categories": [], From c8d395423885ae65bdaa552e8eb18f8b8d8c9fba Mon Sep 17 00:00:00 2001 From: MarioRgzLpz Date: Mon, 29 Jul 2024 10:09:58 +0200 Subject: [PATCH 06/14] feat(acm): Make the insecure algorithm a configurable list by default being RSA_1024 --- prowler/config/config.yaml | 5 +++++ .../acm_certificates_rsa_key_length.py | 9 ++++----- tests/config/config_test.py | 3 +++ tests/config/fixtures/config.yaml | 5 +++++ .../acm_certificates_rsa_key_length_test.py | 6 +++++- 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/prowler/config/config.yaml b/prowler/config/config.yaml index 90dd925aaa3..963352da91f 100644 --- a/prowler/config/config.yaml +++ b/prowler/config/config.yaml @@ -271,6 +271,11 @@ aws: # AWS ACM Configuration # aws.acm_certificates_expiration_check days_to_expire_threshold: 7 + # aws.acm_certificates_rsa_key_length + insecure_algorithms: + [ + "RSA_1024", + ] # Azure Configuration azure: diff --git a/prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.py b/prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.py index c86ef7bf6b9..debb5ce3617 100644 --- a/prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.py +++ b/prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.py @@ -3,8 +3,6 @@ class acm_certificates_rsa_key_length(Check): - insecure_algorithms = ["RSA_1024"] - def execute(self): findings = [] for certificate in acm_client.certificates: @@ -17,10 +15,11 @@ def execute(self): report.status = "PASS" report.status_extended = f"ACM Certificate {certificate.id} for {certificate.name} meet minimum key size requirements." - - if certificate.key_algorithm in self.insecure_algorithms: + if certificate.key_algorithm in acm_client.audit_config.get( + "insecure_algorithms", ["RSA_1024"] + ): report.status = "FAIL" - report.status_extended = f"ACM Certificate {certificate.id} for {certificate.name} uses RSA_1024 which is not secure enough." + report.status_extended = f"ACM Certificate {certificate.id} for {certificate.name} uses a not secure key length." findings.append(report) return findings diff --git a/tests/config/config_test.py b/tests/config/config_test.py index 09a2f61c31e..7d992eaa9e9 100644 --- a/tests/config/config_test.py +++ b/tests/config/config_test.py @@ -255,6 +255,9 @@ def mock_prowler_get_latest_release(_, **kwargs): ], "check_rds_instance_replicas": False, "days_to_expire_threshold": 7, + "insecure_algorithms": [ + "RSA_1024", + ], } config_azure = { diff --git a/tests/config/fixtures/config.yaml b/tests/config/fixtures/config.yaml index 90dd925aaa3..963352da91f 100644 --- a/tests/config/fixtures/config.yaml +++ b/tests/config/fixtures/config.yaml @@ -271,6 +271,11 @@ aws: # AWS ACM Configuration # aws.acm_certificates_expiration_check days_to_expire_threshold: 7 + # aws.acm_certificates_rsa_key_length + insecure_algorithms: + [ + "RSA_1024", + ] # Azure Configuration azure: diff --git a/tests/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length_test.py b/tests/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length_test.py index e1199ffa7ca..ad3af35aa34 100644 --- a/tests/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length_test.py +++ b/tests/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length_test.py @@ -48,6 +48,8 @@ def test_acm_certificate_valid_key_length(self): ) ] + acm_client.audit_config = {"insecure_algorithm": ["RSA_1024"]} + with mock.patch( "prowler.providers.aws.services.acm.acm_service.ACM", new=acm_client, @@ -93,6 +95,8 @@ def test_acm_certificate_short_RSA_key(self): ) ] + acm_client.audit_config = {"insecure_algorithm": ["RSA_1024"]} + with mock.patch( "prowler.providers.aws.services.acm.acm_service.ACM", new=acm_client, @@ -109,7 +113,7 @@ def test_acm_certificate_short_RSA_key(self): assert result[0].status == "FAIL" assert ( result[0].status_extended - == f"ACM Certificate {certificate_id} for {certificate_name} uses RSA_1024 which is not secure enough." + == f"ACM Certificate {certificate_id} for {certificate_name} uses a not secure key length." ) assert result[0].resource_id == certificate_id assert result[0].resource_arn == certificate_arn From e1da46b8f31213fbee1820718d0e74b17eee32c6 Mon Sep 17 00:00:00 2001 From: MarioRgzLpz Date: Mon, 29 Jul 2024 11:01:50 +0200 Subject: [PATCH 07/14] refactor(acm): I change the check name to a more suitable one --- .../__init__.py | 0 ...ficates_insecure_algorithms.metadata.json} | 2 +- .../acm_certificates_insecure_algorithms.py} | 2 +- ..._certificates_insecure_algorithms_test.py} | 24 +++++++++---------- 4 files changed, 14 insertions(+), 14 deletions(-) rename prowler/providers/aws/services/acm/{acm_certificates_rsa_key_length => acm_certificates_insecure_algorithms}/__init__.py (100%) rename prowler/providers/aws/services/acm/{acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.metadata.json => acm_certificates_insecure_algorithms/acm_certificates_insecure_algorithms.metadata.json} (95%) rename prowler/providers/aws/services/acm/{acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.py => acm_certificates_insecure_algorithms/acm_certificates_insecure_algorithms.py} (95%) rename tests/providers/aws/services/acm/{acm_certificates_rsa_key_length/acm_certificates_rsa_key_length_test.py => acm_certificates_insecure_algorithms/acm_certificates_insecure_algorithms_test.py} (84%) diff --git a/prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/__init__.py b/prowler/providers/aws/services/acm/acm_certificates_insecure_algorithms/__init__.py similarity index 100% rename from prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/__init__.py rename to prowler/providers/aws/services/acm/acm_certificates_insecure_algorithms/__init__.py diff --git a/prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.metadata.json b/prowler/providers/aws/services/acm/acm_certificates_insecure_algorithms/acm_certificates_insecure_algorithms.metadata.json similarity index 95% rename from prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.metadata.json rename to prowler/providers/aws/services/acm/acm_certificates_insecure_algorithms/acm_certificates_insecure_algorithms.metadata.json index aaaf3151a7b..58f06d39b42 100644 --- a/prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.metadata.json +++ b/prowler/providers/aws/services/acm/acm_certificates_insecure_algorithms/acm_certificates_insecure_algorithms.metadata.json @@ -1,6 +1,6 @@ { "Provider": "aws", - "CheckID": "acm_certificates_rsa_key_length", + "CheckID": "acm_certificates_insecure_algorithms", "CheckTitle": "Check if ACM Certificates use a secure RSA key size", "CheckType": [ "Data Protection" diff --git a/prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.py b/prowler/providers/aws/services/acm/acm_certificates_insecure_algorithms/acm_certificates_insecure_algorithms.py similarity index 95% rename from prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.py rename to prowler/providers/aws/services/acm/acm_certificates_insecure_algorithms/acm_certificates_insecure_algorithms.py index debb5ce3617..0b2d564e1cf 100644 --- a/prowler/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length.py +++ b/prowler/providers/aws/services/acm/acm_certificates_insecure_algorithms/acm_certificates_insecure_algorithms.py @@ -2,7 +2,7 @@ from prowler.providers.aws.services.acm.acm_client import acm_client -class acm_certificates_rsa_key_length(Check): +class acm_certificates_insecure_algorithms(Check): def execute(self): findings = [] for certificate in acm_client.certificates: diff --git a/tests/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length_test.py b/tests/providers/aws/services/acm/acm_certificates_insecure_algorithms/acm_certificates_insecure_algorithms_test.py similarity index 84% rename from tests/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length_test.py rename to tests/providers/aws/services/acm/acm_certificates_insecure_algorithms/acm_certificates_insecure_algorithms_test.py index ad3af35aa34..873f9dc6fd4 100644 --- a/tests/providers/aws/services/acm/acm_certificates_rsa_key_length/acm_certificates_rsa_key_length_test.py +++ b/tests/providers/aws/services/acm/acm_certificates_insecure_algorithms/acm_certificates_insecure_algorithms_test.py @@ -7,7 +7,7 @@ AWS_ACCOUNT_NUMBER = "123456789012" -class Test_acm_certificates_rsa_key_length: +class Test_acm_certificates_insecure_algorithms: def test_no_acm_certificates(self): acm_client = mock.MagicMock acm_client.certificates = [] @@ -17,16 +17,16 @@ def test_no_acm_certificates(self): new=acm_client, ): # Test Check - from prowler.providers.aws.services.acm.acm_certificates_rsa_key_length.acm_certificates_rsa_key_length import ( - acm_certificates_rsa_key_length, + from prowler.providers.aws.services.acm.acm_certificates_insecure_algorithms.acm_certificates_insecure_algorithms import ( + acm_certificates_insecure_algorithms, ) - check = acm_certificates_rsa_key_length() + check = acm_certificates_insecure_algorithms() result = check.execute() assert len(result) == 0 - def test_acm_certificate_valid_key_length(self): + def test_acm_certificate_secure_algorithm(self): certificate_id = str(uuid.uuid4()) certificate_arn = f"arn:aws:acm:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:certificate/{certificate_id}" certificate_name = "test-certificate.com" @@ -55,11 +55,11 @@ def test_acm_certificate_valid_key_length(self): new=acm_client, ): # Test Check - from prowler.providers.aws.services.acm.acm_certificates_rsa_key_length.acm_certificates_rsa_key_length import ( - acm_certificates_rsa_key_length, + from prowler.providers.aws.services.acm.acm_certificates_insecure_algorithms.acm_certificates_insecure_algorithms import ( + acm_certificates_insecure_algorithms, ) - check = acm_certificates_rsa_key_length() + check = acm_certificates_insecure_algorithms() result = check.execute() assert len(result) == 1 @@ -73,7 +73,7 @@ def test_acm_certificate_valid_key_length(self): assert result[0].region == AWS_REGION assert result[0].resource_tags == [] - def test_acm_certificate_short_RSA_key(self): + def test_acm_certificate_insecure_algorithm(self): certificate_id = str(uuid.uuid4()) certificate_arn = f"arn:aws:acm:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:certificate/{certificate_id}" certificate_name = "test-certificate.com" @@ -102,11 +102,11 @@ def test_acm_certificate_short_RSA_key(self): new=acm_client, ): # Test Check - from prowler.providers.aws.services.acm.acm_certificates_rsa_key_length.acm_certificates_rsa_key_length import ( - acm_certificates_rsa_key_length, + from prowler.providers.aws.services.acm.acm_certificates_insecure_algorithms.acm_certificates_insecure_algorithms import ( + acm_certificates_insecure_algorithms, ) - check = acm_certificates_rsa_key_length() + check = acm_certificates_insecure_algorithms() result = check.execute() assert len(result) == 1 From 49dae857e68d063de1b9877cfb25e44c89c96554 Mon Sep 17 00:00:00 2001 From: MarioRgzLpz Date: Mon, 29 Jul 2024 11:17:22 +0200 Subject: [PATCH 08/14] fix(acm): Add the eks_rquire_log_types in config_test to resolve merge conflicts --- tests/config/config_test.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/config/config_test.py b/tests/config/config_test.py index 7d992eaa9e9..7216dd90c43 100644 --- a/tests/config/config_test.py +++ b/tests/config/config_test.py @@ -258,6 +258,13 @@ def mock_prowler_get_latest_release(_, **kwargs): "insecure_algorithms": [ "RSA_1024", ], + "eks_required_log_types": [ + "api", + "audit", + "authenticator", + "controllerManager", + "scheduler", + ], } config_azure = { From 42829a32f6544e8222dc9f63de5c149bd706fc67 Mon Sep 17 00:00:00 2001 From: MarioRgzLpz Date: Tue, 30 Jul 2024 09:12:15 +0200 Subject: [PATCH 09/14] refactor(acm): I change the name of the check and some texts like the description to make more sense with the check. --- ...ificates_insecure_algorithms.metadata.json | 32 ------------------- .../__init__.py | 0 ...s_with_secure_key_algorithms.metadata.json | 32 +++++++++++++++++++ ...ertificates_with_secure_key_algorithms.py} | 6 ++-- ...icates_with_secure_key_algorithms_test.py} | 24 +++++++------- 5 files changed, 47 insertions(+), 47 deletions(-) delete mode 100644 prowler/providers/aws/services/acm/acm_certificates_insecure_algorithms/acm_certificates_insecure_algorithms.metadata.json rename prowler/providers/aws/services/acm/{acm_certificates_insecure_algorithms => acm_certificates_with_secure_key_algorithms}/__init__.py (100%) create mode 100644 prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.metadata.json rename prowler/providers/aws/services/acm/{acm_certificates_insecure_algorithms/acm_certificates_insecure_algorithms.py => acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.py} (83%) rename tests/providers/aws/services/acm/{acm_certificates_insecure_algorithms/acm_certificates_insecure_algorithms_test.py => acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms_test.py} (82%) diff --git a/prowler/providers/aws/services/acm/acm_certificates_insecure_algorithms/acm_certificates_insecure_algorithms.metadata.json b/prowler/providers/aws/services/acm/acm_certificates_insecure_algorithms/acm_certificates_insecure_algorithms.metadata.json deleted file mode 100644 index 58f06d39b42..00000000000 --- a/prowler/providers/aws/services/acm/acm_certificates_insecure_algorithms/acm_certificates_insecure_algorithms.metadata.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "Provider": "aws", - "CheckID": "acm_certificates_insecure_algorithms", - "CheckTitle": "Check if ACM Certificates use a secure RSA key size", - "CheckType": [ - "Data Protection" - ], - "ServiceName": "acm", - "SubServiceName": "", - "ResourceIdTemplate": "arn:partition:acm:region:account-id:certificate/resource-id", - "Severity": "high", - "ResourceType": "AwsCertificateManagerCertificate", - "Description": "Check if ACM Certificates use a secure RSA key size", - "Risk": "Certificates with weak RSA keys can be compromised.", - "RelatedUrl": "https://docs.aws.amazon.com/securityhub/latest/userguide/acm-controls.html#acm-2", - "Remediation": { - "Code": { - "CLI": "", - "NativeIaC": "", - "Other": "", - "Terraform": "" - }, - "Recommendation": { - "Text": "Ensure that all ACM certificates use RSA keys of at least 2048 bits. If any certificates use smaller keys, regenerate them with a secure key size and update any systems that rely on these certificates.", - "Url": "https://docs.aws.amazon.com/securityhub/latest/userguide/acm-controls.html#acm-2" - } - }, - "Categories": [], - "DependsOn": [], - "RelatedTo": [], - "Notes": "" -} diff --git a/prowler/providers/aws/services/acm/acm_certificates_insecure_algorithms/__init__.py b/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/__init__.py similarity index 100% rename from prowler/providers/aws/services/acm/acm_certificates_insecure_algorithms/__init__.py rename to prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/__init__.py diff --git a/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.metadata.json b/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.metadata.json new file mode 100644 index 00000000000..eeb67444c22 --- /dev/null +++ b/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.metadata.json @@ -0,0 +1,32 @@ +{ + "Provider": "aws", + "CheckID": "acm_certificates_with_secure_key_algorithms", + "CheckTitle": "Check if ACM Certificates use a secure key algorithm", + "CheckType": [ + "Data Protection" + ], + "ServiceName": "acm", + "SubServiceName": "", + "ResourceIdTemplate": "arn:partition:acm:region:account-id:certificate/resource-id", + "Severity": "high", + "ResourceType": "AwsCertificateManagerCertificate", + "Description": "Check if ACM Certificates use a secure key algorithm (RSA 2048 bits or more, or ECDSA 256 bits or more). For example certificates that use RSA_1024 can be compromised.", + "Risk": "Certificates with weak RSA or ECDSA keys can be compromised.", + "RelatedUrl": "https://docs.aws.amazon.com/acm/latest/userguide/acm-certificate.html", + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "", + "Terraform": "" + }, + "Recommendation": { + "Text": "Ensure that all ACM certificates use a secure key algorithm. If any certificates use smaller keys, regenerate them with a secure key size and update any systems that rely on these certificates.", + "Url": "https://docs.aws.amazon.com/acm/latest/userguide/gs.html" + } + }, + "Categories": [], + "DependsOn": [], + "RelatedTo": [], + "Notes": "" +} diff --git a/prowler/providers/aws/services/acm/acm_certificates_insecure_algorithms/acm_certificates_insecure_algorithms.py b/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.py similarity index 83% rename from prowler/providers/aws/services/acm/acm_certificates_insecure_algorithms/acm_certificates_insecure_algorithms.py rename to prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.py index 0b2d564e1cf..e7f77b3bb1b 100644 --- a/prowler/providers/aws/services/acm/acm_certificates_insecure_algorithms/acm_certificates_insecure_algorithms.py +++ b/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.py @@ -2,7 +2,7 @@ from prowler.providers.aws.services.acm.acm_client import acm_client -class acm_certificates_insecure_algorithms(Check): +class acm_certificates_with_secure_key_algorithms(Check): def execute(self): findings = [] for certificate in acm_client.certificates: @@ -14,12 +14,12 @@ def execute(self): report.resource_tags = certificate.tags report.status = "PASS" - report.status_extended = f"ACM Certificate {certificate.id} for {certificate.name} meet minimum key size requirements." + report.status_extended = f"ACM Certificate {certificate.id} for {certificate.name} uses a secure key algorithm." if certificate.key_algorithm in acm_client.audit_config.get( "insecure_algorithms", ["RSA_1024"] ): report.status = "FAIL" - report.status_extended = f"ACM Certificate {certificate.id} for {certificate.name} uses a not secure key length." + report.status_extended = f"ACM Certificate {certificate.id} for {certificate.name} does not use a secure key algorithm." findings.append(report) return findings diff --git a/tests/providers/aws/services/acm/acm_certificates_insecure_algorithms/acm_certificates_insecure_algorithms_test.py b/tests/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms_test.py similarity index 82% rename from tests/providers/aws/services/acm/acm_certificates_insecure_algorithms/acm_certificates_insecure_algorithms_test.py rename to tests/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms_test.py index 873f9dc6fd4..aa10d95293e 100644 --- a/tests/providers/aws/services/acm/acm_certificates_insecure_algorithms/acm_certificates_insecure_algorithms_test.py +++ b/tests/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms_test.py @@ -7,7 +7,7 @@ AWS_ACCOUNT_NUMBER = "123456789012" -class Test_acm_certificates_insecure_algorithms: +class Test_acm_certificates_with_secure_key_algorithms: def test_no_acm_certificates(self): acm_client = mock.MagicMock acm_client.certificates = [] @@ -17,11 +17,11 @@ def test_no_acm_certificates(self): new=acm_client, ): # Test Check - from prowler.providers.aws.services.acm.acm_certificates_insecure_algorithms.acm_certificates_insecure_algorithms import ( - acm_certificates_insecure_algorithms, + from prowler.providers.aws.services.acm.acm_certificates_with_secure_key_algorithms.acm_certificates_with_secure_key_algorithms import ( + acm_certificates_with_secure_key_algorithms, ) - check = acm_certificates_insecure_algorithms() + check = acm_certificates_with_secure_key_algorithms() result = check.execute() assert len(result) == 0 @@ -55,18 +55,18 @@ def test_acm_certificate_secure_algorithm(self): new=acm_client, ): # Test Check - from prowler.providers.aws.services.acm.acm_certificates_insecure_algorithms.acm_certificates_insecure_algorithms import ( - acm_certificates_insecure_algorithms, + from prowler.providers.aws.services.acm.acm_certificates_with_secure_key_algorithms.acm_certificates_with_secure_key_algorithms import ( + acm_certificates_with_secure_key_algorithms, ) - check = acm_certificates_insecure_algorithms() + check = acm_certificates_with_secure_key_algorithms() result = check.execute() assert len(result) == 1 assert result[0].status == "PASS" assert ( result[0].status_extended - == f"ACM Certificate {certificate_id} for {certificate_name} meet minimum key size requirements." + == f"ACM Certificate {certificate_id} for {certificate_name} uses a secure key algorithm." ) assert result[0].resource_id == certificate_id assert result[0].resource_arn == certificate_arn @@ -102,18 +102,18 @@ def test_acm_certificate_insecure_algorithm(self): new=acm_client, ): # Test Check - from prowler.providers.aws.services.acm.acm_certificates_insecure_algorithms.acm_certificates_insecure_algorithms import ( - acm_certificates_insecure_algorithms, + from prowler.providers.aws.services.acm.acm_certificates_with_secure_key_algorithms.acm_certificates_with_secure_key_algorithms import ( + acm_certificates_with_secure_key_algorithms, ) - check = acm_certificates_insecure_algorithms() + check = acm_certificates_with_secure_key_algorithms() result = check.execute() assert len(result) == 1 assert result[0].status == "FAIL" assert ( result[0].status_extended - == f"ACM Certificate {certificate_id} for {certificate_name} uses a not secure key length." + == f"ACM Certificate {certificate_id} for {certificate_name} does not use a secure key algorithm." ) assert result[0].resource_id == certificate_id assert result[0].resource_arn == certificate_arn From ca090d8c3a9e17147073ff28f91211594c7f4515 Mon Sep 17 00:00:00 2001 From: MarioRgzLpz Date: Wed, 31 Jul 2024 09:10:27 +0200 Subject: [PATCH 10/14] chore(acm): Change the recommendation url to the SecurityHub one --- .../acm_certificates_with_secure_key_algorithms.metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.metadata.json b/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.metadata.json index eeb67444c22..a2642f11c78 100644 --- a/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.metadata.json +++ b/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.metadata.json @@ -22,7 +22,7 @@ }, "Recommendation": { "Text": "Ensure that all ACM certificates use a secure key algorithm. If any certificates use smaller keys, regenerate them with a secure key size and update any systems that rely on these certificates.", - "Url": "https://docs.aws.amazon.com/acm/latest/userguide/gs.html" + "Url": "https://docs.aws.amazon.com/securityhub/latest/userguide/acm-controls.html#acm-2" } }, "Categories": [], From ee0817443ddba0154459187c16aab5bdb652f9d6 Mon Sep 17 00:00:00 2001 From: MarioRgzLpz Date: Wed, 31 Jul 2024 11:11:42 +0200 Subject: [PATCH 11/14] chore(acm): Change insecure_algorithm to insecure_key_algorithm in the config, add some details in the description and risk in the metadata and rename the service methods to comply with Python convention --- prowler/config/config.yaml | 2 +- ...ificates_with_secure_key_algorithms.metadata.json | 4 ++-- prowler/providers/aws/services/acm/acm_service.py | 12 ++++++------ tests/config/config_test.py | 2 +- tests/config/fixtures/config.yaml | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/prowler/config/config.yaml b/prowler/config/config.yaml index 377cf317a08..afe8aaf8478 100644 --- a/prowler/config/config.yaml +++ b/prowler/config/config.yaml @@ -272,7 +272,7 @@ aws: # aws.acm_certificates_expiration_check days_to_expire_threshold: 7 # aws.acm_certificates_rsa_key_length - insecure_algorithms: + insecure_key_algorithms: [ "RSA_1024", ] diff --git a/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.metadata.json b/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.metadata.json index a2642f11c78..0eb2fbcb23c 100644 --- a/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.metadata.json +++ b/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.metadata.json @@ -10,8 +10,8 @@ "ResourceIdTemplate": "arn:partition:acm:region:account-id:certificate/resource-id", "Severity": "high", "ResourceType": "AwsCertificateManagerCertificate", - "Description": "Check if ACM Certificates use a secure key algorithm (RSA 2048 bits or more, or ECDSA 256 bits or more). For example certificates that use RSA_1024 can be compromised.", - "Risk": "Certificates with weak RSA or ECDSA keys can be compromised.", + "Description": "Check if ACM Certificates use a secure key algorithm (RSA 2048 bits or more, or ECDSA 256 bits or more). For example certificates that use RSA_1024 can be compromised because the encryption could be broken in no more than 2^80 guesses making it vulnerable to a factorization attack.", + "Risk": "Certificates with weak RSA or ECDSA keys can be compromised because the length of the key defines the security of the encryption. The number of bits in the key determines the number of guesses an attacker would have to make in order to decrypt the data. The more bits in the key, the more secure the encryption.", "RelatedUrl": "https://docs.aws.amazon.com/acm/latest/userguide/acm-certificate.html", "Remediation": { "Code": { diff --git a/prowler/providers/aws/services/acm/acm_service.py b/prowler/providers/aws/services/acm/acm_service.py index 131909c28d5..ca49f3b0ce0 100644 --- a/prowler/providers/aws/services/acm/acm_service.py +++ b/prowler/providers/aws/services/acm/acm_service.py @@ -14,11 +14,11 @@ def __init__(self, provider): # Call AWSService's __init__ super().__init__(__class__.__name__, provider) self.certificates = [] - self.__threading_call__(self.__list_certificates__) - self.__describe_certificates__() - self.__list_tags_for_certificate__() + self.__threading_call__(self._list_certificates) + self._describe_certificates() + self._list_tags_for_certificate() - def __list_certificates__(self, regional_client): + def _list_certificates(self, regional_client): logger.info("ACM - Listing Certificates...") try: list_certificates_paginator = regional_client.get_paginator( @@ -61,7 +61,7 @@ def __list_certificates__(self, regional_client): f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" ) - def __describe_certificates__(self): + def _describe_certificates(self): logger.info("ACM - Describing Certificates...") try: for certificate in self.certificates: @@ -79,7 +79,7 @@ def __describe_certificates__(self): f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" ) - def __list_tags_for_certificate__(self): + def _list_tags_for_certificate(self): logger.info("ACM - List Tags...") try: for certificate in self.certificates: diff --git a/tests/config/config_test.py b/tests/config/config_test.py index 59dcfcd7901..5f42b3f4bc4 100644 --- a/tests/config/config_test.py +++ b/tests/config/config_test.py @@ -262,7 +262,7 @@ def mock_prowler_get_latest_release(_, **kwargs): ], "check_rds_instance_replicas": False, "days_to_expire_threshold": 7, - "insecure_algorithms": [ + "insecure_key_algorithms": [ "RSA_1024", ], "eks_required_log_types": [ diff --git a/tests/config/fixtures/config.yaml b/tests/config/fixtures/config.yaml index 372da17bf0a..20511c41ffd 100644 --- a/tests/config/fixtures/config.yaml +++ b/tests/config/fixtures/config.yaml @@ -272,7 +272,7 @@ aws: # aws.acm_certificates_expiration_check days_to_expire_threshold: 7 # aws.acm_certificates_rsa_key_length - insecure_algorithms: + insecure_key_algorithms: [ "RSA_1024", ] From 9546adfdd83e2aa85adda89a1983dc50e28b2ee0 Mon Sep 17 00:00:00 2001 From: MarioRgzLpz Date: Mon, 5 Aug 2024 09:22:37 +0200 Subject: [PATCH 12/14] chore(acm): Change method _list_certificates so it returns all key algorithms including ECDSA and all key size RSA --- prowler/providers/aws/services/acm/acm_service.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/prowler/providers/aws/services/acm/acm_service.py b/prowler/providers/aws/services/acm/acm_service.py index ca49f3b0ce0..d858464a304 100644 --- a/prowler/providers/aws/services/acm/acm_service.py +++ b/prowler/providers/aws/services/acm/acm_service.py @@ -21,10 +21,21 @@ def __init__(self, provider): def _list_certificates(self, regional_client): logger.info("ACM - Listing Certificates...") try: + includes = { + "keyTypes": [ + "RSA_1024", + "RSA_2048", + "RSA_3072", + "RSA_4096", + "EC_prime256v1", + "EC_secp384r1", + "EC_secp521r1", + ] + } list_certificates_paginator = regional_client.get_paginator( "list_certificates" ) - for page in list_certificates_paginator.paginate(): + for page in list_certificates_paginator.paginate(Includes=includes): for certificate in page["CertificateSummaryList"]: if not self.audit_resources or ( is_resource_filtered( From 9697ead77d7a540a63f68b8bad1cdcc867b85ff4 Mon Sep 17 00:00:00 2001 From: MarioRgzLpz Date: Mon, 5 Aug 2024 09:29:46 +0200 Subject: [PATCH 13/14] chore(acm): Added logic for checking only in use certificates and swapped KeyAlgorithm_Size to KeyAlgorithm-Size as this is the format in which certificates are returned --- prowler/config/config.yaml | 2 +- ...certificates_with_secure_key_algorithms.py | 29 ++++++++++--------- tests/config/config_test.py | 2 +- tests/config/fixtures/config.yaml | 2 +- ...ficates_with_secure_key_algorithms_test.py | 4 +-- .../aws/services/acm/acm_service_test.py | 8 ++--- 6 files changed, 24 insertions(+), 23 deletions(-) diff --git a/prowler/config/config.yaml b/prowler/config/config.yaml index afe8aaf8478..b52aec73694 100644 --- a/prowler/config/config.yaml +++ b/prowler/config/config.yaml @@ -274,7 +274,7 @@ aws: # aws.acm_certificates_rsa_key_length insecure_key_algorithms: [ - "RSA_1024", + "RSA-1024", ] # AWS EKS Configuration diff --git a/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.py b/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.py index e7f77b3bb1b..f0f4a5ce867 100644 --- a/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.py +++ b/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.py @@ -6,20 +6,21 @@ class acm_certificates_with_secure_key_algorithms(Check): def execute(self): findings = [] for certificate in acm_client.certificates: - report = Check_Report_AWS(self.metadata()) - report.region = certificate.region - report.resource_id = certificate.id - report.resource_details = certificate.name - report.resource_arn = certificate.arn - report.resource_tags = certificate.tags + if certificate.in_use or acm_client.provider.scan_unused_services: + report = Check_Report_AWS(self.metadata()) + report.region = certificate.region + report.resource_id = certificate.id + report.resource_details = certificate.name + report.resource_arn = certificate.arn + report.resource_tags = certificate.tags - report.status = "PASS" - report.status_extended = f"ACM Certificate {certificate.id} for {certificate.name} uses a secure key algorithm." - if certificate.key_algorithm in acm_client.audit_config.get( - "insecure_algorithms", ["RSA_1024"] - ): - report.status = "FAIL" - report.status_extended = f"ACM Certificate {certificate.id} for {certificate.name} does not use a secure key algorithm." - findings.append(report) + report.status = "PASS" + report.status_extended = f"ACM Certificate {certificate.id} for {certificate.name} uses a secure key algorithm." + if certificate.key_algorithm in acm_client.audit_config.get( + "insecure_algorithms", ["RSA-1024"] + ): + report.status = "FAIL" + report.status_extended = f"ACM Certificate {certificate.id} for {certificate.name} does not use a secure key algorithm." + findings.append(report) return findings diff --git a/tests/config/config_test.py b/tests/config/config_test.py index 5f42b3f4bc4..4397e8104e6 100644 --- a/tests/config/config_test.py +++ b/tests/config/config_test.py @@ -263,7 +263,7 @@ def mock_prowler_get_latest_release(_, **kwargs): "check_rds_instance_replicas": False, "days_to_expire_threshold": 7, "insecure_key_algorithms": [ - "RSA_1024", + "RSA-1024", ], "eks_required_log_types": [ "api", diff --git a/tests/config/fixtures/config.yaml b/tests/config/fixtures/config.yaml index 20511c41ffd..bbd21d2ab25 100644 --- a/tests/config/fixtures/config.yaml +++ b/tests/config/fixtures/config.yaml @@ -274,7 +274,7 @@ aws: # aws.acm_certificates_rsa_key_length insecure_key_algorithms: [ - "RSA_1024", + "RSA-1024", ] # AWS EKS Configuration diff --git a/tests/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms_test.py b/tests/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms_test.py index aa10d95293e..69ce385d572 100644 --- a/tests/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms_test.py +++ b/tests/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms_test.py @@ -31,7 +31,7 @@ def test_acm_certificate_secure_algorithm(self): certificate_arn = f"arn:aws:acm:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:certificate/{certificate_id}" certificate_name = "test-certificate.com" certificate_type = "AMAZON_ISSUED" - certificate_key_algorithm = "RSA_2048" + certificate_key_algorithm = "RSA-2048" acm_client = mock.MagicMock acm_client.certificates = [ @@ -78,7 +78,7 @@ def test_acm_certificate_insecure_algorithm(self): certificate_arn = f"arn:aws:acm:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:certificate/{certificate_id}" certificate_name = "test-certificate.com" certificate_type = "AMAZON_ISSUED" - certificate_key_algorithm = "RSA_1024" + certificate_key_algorithm = "RSA-1024" acm_client = mock.MagicMock acm_client.certificates = [ diff --git a/tests/providers/aws/services/acm/acm_service_test.py b/tests/providers/aws/services/acm/acm_service_test.py index 5f7fd182a34..32eef4993a0 100644 --- a/tests/providers/aws/services/acm/acm_service_test.py +++ b/tests/providers/aws/services/acm/acm_service_test.py @@ -18,7 +18,7 @@ certificate_arn = f"arn:aws:acm:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:certificate/{str(uuid.uuid4())}" certificate_name = "test-certificate.com" certificate_type = "AMAZON_ISSUED" -certificate_key_algorithm = "RSA_4096" +certificate_key_algorithm = "RSA-4096" def mock_make_api_call(self, operation_name, kwargs): @@ -41,7 +41,7 @@ def mock_make_api_call(self, operation_name, kwargs): "HasAdditionalSubjectAlternativeNames": False, "Status": "ISSUED", "Type": certificate_type, - "KeyAlgorithm": "RSA_4096", + "KeyAlgorithm": "RSA-4096", "KeyUsages": ["DIGITAL_SIGNATURE"], "ExtendedKeyUsages": ["TLS_WEB_SERVER_AUTHENTICATION"], "InUse": True, @@ -128,7 +128,7 @@ def test_audited_account(self): # Test ACM List Certificates # @mock_acm - def test__list_and_describe_certificates__(self): + def test_list_and_describe_certificates(self): # Generate ACM Client # acm_client = client("acm", region_name=AWS_REGION) # Request ACM certificate @@ -150,7 +150,7 @@ def test__list_and_describe_certificates__(self): # Test ACM List Tags # @mock_acm - def test__list_tags_for_certificate__(self): + def test_list_tags_for_certificate(self): # Generate ACM Client # acm_client = client("acm", region_name=AWS_REGION) # Request ACM certificate From cf645a7e6ae8fd5d8fc3bc56bfda363336a62e08 Mon Sep 17 00:00:00 2001 From: MarioRgzLpz Date: Wed, 7 Aug 2024 09:35:00 +0200 Subject: [PATCH 14/14] chore(acm): Add the key algorithm in the status extended and fix the audit_config key format in the tests --- ..._certificates_with_secure_key_algorithms.metadata.json | 2 +- .../acm_certificates_with_secure_key_algorithms.py | 4 ++-- .../acm_certificates_with_secure_key_algorithms_test.py | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.metadata.json b/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.metadata.json index 0eb2fbcb23c..c4a315b15ed 100644 --- a/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.metadata.json +++ b/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.metadata.json @@ -10,7 +10,7 @@ "ResourceIdTemplate": "arn:partition:acm:region:account-id:certificate/resource-id", "Severity": "high", "ResourceType": "AwsCertificateManagerCertificate", - "Description": "Check if ACM Certificates use a secure key algorithm (RSA 2048 bits or more, or ECDSA 256 bits or more). For example certificates that use RSA_1024 can be compromised because the encryption could be broken in no more than 2^80 guesses making it vulnerable to a factorization attack.", + "Description": "Check if ACM Certificates use a secure key algorithm (RSA 2048 bits or more, or ECDSA 256 bits or more). For example certificates that use RSA-1024 can be compromised because the encryption could be broken in no more than 2^80 guesses making it vulnerable to a factorization attack.", "Risk": "Certificates with weak RSA or ECDSA keys can be compromised because the length of the key defines the security of the encryption. The number of bits in the key determines the number of guesses an attacker would have to make in order to decrypt the data. The more bits in the key, the more secure the encryption.", "RelatedUrl": "https://docs.aws.amazon.com/acm/latest/userguide/acm-certificate.html", "Remediation": { diff --git a/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.py b/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.py index f0f4a5ce867..eb91295774d 100644 --- a/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.py +++ b/prowler/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms.py @@ -15,12 +15,12 @@ def execute(self): report.resource_tags = certificate.tags report.status = "PASS" - report.status_extended = f"ACM Certificate {certificate.id} for {certificate.name} uses a secure key algorithm." + report.status_extended = f"ACM Certificate {certificate.id} for {certificate.name} uses a secure key algorithm ({certificate.key_algorithm})." if certificate.key_algorithm in acm_client.audit_config.get( "insecure_algorithms", ["RSA-1024"] ): report.status = "FAIL" - report.status_extended = f"ACM Certificate {certificate.id} for {certificate.name} does not use a secure key algorithm." + report.status_extended = f"ACM Certificate {certificate.id} for {certificate.name} does not use a secure key algorithm ({certificate.key_algorithm})." findings.append(report) return findings diff --git a/tests/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms_test.py b/tests/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms_test.py index 69ce385d572..0862893fb72 100644 --- a/tests/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms_test.py +++ b/tests/providers/aws/services/acm/acm_certificates_with_secure_key_algorithms/acm_certificates_with_secure_key_algorithms_test.py @@ -48,7 +48,7 @@ def test_acm_certificate_secure_algorithm(self): ) ] - acm_client.audit_config = {"insecure_algorithm": ["RSA_1024"]} + acm_client.audit_config = {"insecure_algorithm": ["RSA-1024"]} with mock.patch( "prowler.providers.aws.services.acm.acm_service.ACM", @@ -66,7 +66,7 @@ def test_acm_certificate_secure_algorithm(self): assert result[0].status == "PASS" assert ( result[0].status_extended - == f"ACM Certificate {certificate_id} for {certificate_name} uses a secure key algorithm." + == f"ACM Certificate {certificate_id} for {certificate_name} uses a secure key algorithm ({certificate_key_algorithm})." ) assert result[0].resource_id == certificate_id assert result[0].resource_arn == certificate_arn @@ -95,7 +95,7 @@ def test_acm_certificate_insecure_algorithm(self): ) ] - acm_client.audit_config = {"insecure_algorithm": ["RSA_1024"]} + acm_client.audit_config = {"insecure_algorithm": ["RSA-1024"]} with mock.patch( "prowler.providers.aws.services.acm.acm_service.ACM", @@ -113,7 +113,7 @@ def test_acm_certificate_insecure_algorithm(self): assert result[0].status == "FAIL" assert ( result[0].status_extended - == f"ACM Certificate {certificate_id} for {certificate_name} does not use a secure key algorithm." + == f"ACM Certificate {certificate_id} for {certificate_name} does not use a secure key algorithm ({certificate_key_algorithm})." ) assert result[0].resource_id == certificate_id assert result[0].resource_arn == certificate_arn