feat(ACM): Add check and service for ACM (#1365)

This commit is contained in:
Sergio Garcia
2022-10-20 17:17:12 +02:00
committed by GitHub
parent 5c78e6b171
commit bd6eb723dd
14 changed files with 536 additions and 110 deletions

View File

@@ -0,0 +1,35 @@
{
"Provider": "aws",
"CheckID": "acm_certificates_transparency_logs_enabled",
"CheckTitle": "Check if ACM certificates have Certificate Transparency logging enabled",
"CheckType": ["Logging and Monitoring"],
"ServiceName": "acm",
"SubServiceName": "",
"ResourceIdTemplate": "arn:partition:acm:region:account-id:certificate/resource-id",
"Severity": "medium",
"ResourceType": "AwsCertificateManagerCertificate",
"Description": "Check if ACM certificates have Certificate Transparency logging enabled",
"Risk": "Domain owners can search the log to identify unexpected certificates, whether issued by mistake or malice. Domain owners can also identify Certificate Authorities (CAs) that are improperly issuing certificates.",
"RelatedUrl": "https://aws.amazon.com/blogs/security/how-to-get-ready-for-certificate-transparency/",
"Remediation": {
"Code": {
"CLI": "",
"NativeIaC": "",
"Other": "",
"Terraform": ""
},
"Recommendation": {
"Text": "Make sure you are logging information about Lambda operations. Create a lifecycle and use cases for each trail.",
"Url": "https://aws.amazon.com/blogs/security/how-to-get-ready-for-certificate-transparency/"
}
},
"Categories": [],
"Tags": {
"Tag1Key": "value",
"Tag2Key": "value"
},
"DependsOn": [],
"RelatedTo": [],
"Notes": "",
"Compliance": []
}

View File

@@ -0,0 +1,30 @@
from lib.check.models import Check, Check_Report
from providers.aws.services.acm.acm_client import acm_client
class acm_certificates_transparency_logs_enabled(Check):
def execute(self):
findings = []
for certificate in acm_client.certificates:
report = Check_Report(self.metadata)
report.region = certificate.region
if certificate.type == "IMPORTED":
report.status = "PASS"
report.status_extended = (
f"ACM Certificate for {certificate.name} is imported."
)
report.resource_id = certificate.name
report.resource_arn = certificate.arn
else:
if not certificate.transparency_logging:
report.status = "FAIL"
report.status_extended = f"ACM Certificate for {certificate.name} has Certificate Transparency logging disabled."
report.resource_id = certificate.name
report.resource_arn = certificate.arn
else:
report.status = "PASS"
report.status_extended = f"ACM Certificate for {certificate.name} has Certificate Transparency logging enabled."
report.resource_id = certificate.name
report.resource_arn = certificate.arn
findings.append(report)
return findings

View File

@@ -0,0 +1,131 @@
from unittest import mock
from boto3 import client
from moto import mock_acm
AWS_REGION = "us-east-1"
class Test_acm_certificates_transparency_logs_enabled:
@mock_acm
def test_acm_certificate_with_logging(self):
# Generate ACM Client
acm_client = client("acm", region_name=AWS_REGION)
# Request ACM certificate
certificate = acm_client.request_certificate(
DomainName="test.com",
Options={"CertificateTransparencyLoggingPreference": "ENABLED"},
)
from providers.aws.lib.audit_info.audit_info import current_audit_info
from providers.aws.services.acm.acm_service import ACM
current_audit_info.audited_partition = "aws"
with mock.patch(
"providers.aws.services.acm.acm_certificates_transparency_logs_enabled.acm_certificates_transparency_logs_enabled.acm_client",
new=ACM(current_audit_info),
):
# Test Check
from providers.aws.services.acm.acm_certificates_transparency_logs_enabled.acm_certificates_transparency_logs_enabled import (
acm_certificates_transparency_logs_enabled,
)
check = acm_certificates_transparency_logs_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== "ACM Certificate for test.com has Certificate Transparency logging enabled."
)
assert result[0].resource_id == "test.com"
assert result[0].resource_arn == certificate["CertificateArn"]
@mock_acm
def test_acm_certificate_without_logging(self):
# Generate ACM Client
acm_client = client("acm", region_name=AWS_REGION)
# Request ACM certificate
certificate = acm_client.request_certificate(
DomainName="test.com",
Options={"CertificateTransparencyLoggingPreference": "ENABLED"},
)
from providers.aws.lib.audit_info.audit_info import current_audit_info
from providers.aws.services.acm.acm_service import ACM
current_audit_info.audited_partition = "aws"
with mock.patch(
"providers.aws.services.acm.acm_certificates_transparency_logs_enabled.acm_certificates_transparency_logs_enabled.acm_client",
new=ACM(current_audit_info),
) as service_client:
# Test Check
from providers.aws.services.acm.acm_certificates_transparency_logs_enabled.acm_certificates_transparency_logs_enabled import (
acm_certificates_transparency_logs_enabled,
)
service_client.certificates[0].transparency_logging = False
check = acm_certificates_transparency_logs_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== "ACM Certificate for test.com has Certificate Transparency logging disabled."
)
assert result[0].resource_id == "test.com"
assert result[0].resource_arn == certificate["CertificateArn"]
@mock_acm
def test_acm_default_certificate(self):
# Generate ACM Client
acm_client = client("acm", region_name=AWS_REGION)
# Request ACM certificate
certificate = acm_client.request_certificate(
DomainName="test.com",
)
from providers.aws.lib.audit_info.audit_info import current_audit_info
from providers.aws.services.acm.acm_service import ACM
current_audit_info.audited_partition = "aws"
with mock.patch(
"providers.aws.services.acm.acm_certificates_transparency_logs_enabled.acm_certificates_transparency_logs_enabled.acm_client",
new=ACM(current_audit_info),
):
# Test Check
from providers.aws.services.acm.acm_certificates_transparency_logs_enabled.acm_certificates_transparency_logs_enabled import (
acm_certificates_transparency_logs_enabled,
)
check = acm_certificates_transparency_logs_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== "ACM Certificate for test.com has Certificate Transparency logging enabled."
)
assert result[0].resource_id == "test.com"
assert result[0].resource_arn == certificate["CertificateArn"]
@mock_acm
def test_bad_response(self):
mock_client = mock.MagicMock()
with mock.patch(
"providers.aws.services.acm.acm_certificates_transparency_logs_enabled.acm_certificates_transparency_logs_enabled.acm_client",
new=mock_client,
):
# Test Check
from providers.aws.services.acm.acm_certificates_transparency_logs_enabled.acm_certificates_transparency_logs_enabled import (
acm_certificates_transparency_logs_enabled,
)
check = acm_certificates_transparency_logs_enabled()
result = check.execute()
assert len(result) == 0