Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(elb): add new check elb_ssl_https_listeners_use_acm_certificates #5424

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
8 changes: 6 additions & 2 deletions prowler/providers/aws/services/elb/elb_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ def _describe_load_balancers(self, regional_client):
Listener(
protocol=listener["Listener"]["Protocol"],
policies=listener["PolicyNames"],
certificate_arn=listener["Listener"][
"SSLCertificateId"
],
)
)

Expand Down Expand Up @@ -70,7 +73,7 @@ def _describe_load_balancer_attributes(self, load_balancer):

except Exception as error:
logger.error(
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
f"{load_balancer.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)

def _describe_tags(self, load_balancer):
Expand All @@ -86,12 +89,13 @@ def _describe_tags(self, load_balancer):

except Exception as error:
logger.error(
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
f"{load_balancer.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)


class Listener(BaseModel):
protocol: str
certificate_arn: str
policies: list[str]


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"Provider": "aws",
"CheckID": "elb_ssl_listeners_use_acm_certificate",
"CheckTitle": "Check if Classic Load Balancers with SSL/HTTPS listeners use a certificate provided by AWS Certificate Manager (ACM).",
"CheckType": [
"Software and Configuration Checks/Vulnerabilities/NIST 800-53 Controls (USA)"
],
"ServiceName": "elasticloadbalancing",
"SubServiceName": "",
"ResourceIdTemplate": "arn:aws:elasticloadbalancing:{region}:{account-id}:loadbalancer/{loadbalancer-name}",
"Severity": "medium",
"ResourceType": "AwsElasticLoadBalancingLoadBalancer",
"Description": "This control checks whether the Classic Load Balancer uses HTTPS/SSL certificates provided by AWS Certificate Manager (ACM). The control fails if the Classic Load Balancer does not use a certificate provided by ACM.",
"Risk": "If Classic Load Balancers are not using ACM certificates, it increases the risk of using self-signed or expired certificates, which can impact secure communication and lead to compliance issues.",
"RelatedUrl": "https://docs.aws.amazon.com/config/latest/developerguide/elb-acm-certificate-required.html",
"Remediation": {
"Code": {
"CLI": "aws elb set-load-balancer-listener-ssl-certificate --load-balancer-name <load-balancer-name> --load-balancer-port <port> --ssl-certificate-id <certificate-id>",
"NativeIaC": "",
"Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/elb-controls.html#elb-2",
"Terraform": ""
},
"Recommendation": {
"Text": "Use AWS Certificate Manager (ACM) to manage SSL/TLS certificates for your Classic Load Balancer to ensure secure encryption of data in transit.",
"Url": "https://repost.aws/es/knowledge-center/associate-acm-certificate-alb-nlb"
}
},
"Categories": [
"encryption"
],
"DependsOn": [],
"RelatedTo": [],
"Notes": ""
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.acm.acm_client import acm_client
from prowler.providers.aws.services.elb.elb_client import elb_client


class elb_ssl_listeners_use_acm_certificate(Check):
def execute(self):
findings = []
secure_protocols = ["SSL", "HTTPS"]
for lb_arn, lb in elb_client.loadbalancers.items():
report = Check_Report_AWS(self.metadata())
report.region = lb.region
report.resource_id = lb.name
report.resource_arn = lb_arn
report.resource_tags = lb.tags
report.status = "PASS"
report.status_extended = f"ELB {lb.name} HTTPS/SSL listeners are using certificates managed by ACM."
for listener in lb.listeners:
if (
listener.protocol in secure_protocols
and acm_client.certificates[listener.certificate_arn].type
!= "AMAZON_ISSUED"
):
report.status = "FAIL"
report.status_extended = f"ELB {lb.name} has HTTPS/SSL listeners that are using certificates not managed by ACM."
break

findings.append(report)

return findings
25 changes: 22 additions & 3 deletions tests/providers/aws/services/elb/elb_service_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,27 @@ def test__get_session__(self):
def test_describe_load_balancers(self):
elb = client("elb", region_name=AWS_REGION_US_EAST_1)
ec2 = resource("ec2", region_name=AWS_REGION_US_EAST_1)

acm = client("acm", region_name=AWS_REGION_US_EAST_1)
certificate = acm.request_certificate(DomainName="www.example.com")
security_group = ec2.create_security_group(
GroupName="sg01", Description="Test security group sg01"
)

dns_name = elb.create_load_balancer(
LoadBalancerName="my-lb",
Listeners=[
{"Protocol": "tcp", "LoadBalancerPort": 80, "InstancePort": 8080},
{"Protocol": "http", "LoadBalancerPort": 81, "InstancePort": 9000},
{
"Protocol": "tcp",
"LoadBalancerPort": 80,
"InstancePort": 8080,
"SSLCertificateId": certificate["CertificateArn"],
},
{
"Protocol": "http",
"LoadBalancerPort": 81,
"InstancePort": 9000,
"SSLCertificateId": certificate["CertificateArn"],
},
],
AvailabilityZones=[AWS_REGION_US_EAST_1_AZA],
Scheme="internal",
Expand All @@ -68,8 +79,16 @@ def test_describe_load_balancers(self):
assert len(elb.loadbalancers[elb_arn].listeners) == 2
assert elb.loadbalancers[elb_arn].listeners[0].protocol == "TCP"
assert elb.loadbalancers[elb_arn].listeners[0].policies == []
assert (
elb.loadbalancers[elb_arn].listeners[0].certificate_arn
== certificate["CertificateArn"]
)
assert elb.loadbalancers[elb_arn].listeners[1].protocol == "HTTP"
assert elb.loadbalancers[elb_arn].listeners[1].policies == []
assert (
elb.loadbalancers[elb_arn].listeners[0].certificate_arn
== certificate["CertificateArn"]
)
assert len(elb.loadbalancers[elb_arn].availability_zones) == 1
assert AWS_REGION_US_EAST_1_AZA in elb.loadbalancers[elb_arn].availability_zones

Expand Down
Loading
Loading