feat(autoscaling): add new check autoscaling_group_elb_health_check_enabled (#5330)

Co-authored-by: Sergio <sergio@prowler.com>
This commit is contained in:
Daniel Barranquero
2024-10-09 20:56:18 +02:00
committed by GitHub
parent d45750b042
commit 4181ca56be
6 changed files with 520 additions and 0 deletions
@@ -0,0 +1,32 @@
{
"Provider": "aws",
"CheckID": "autoscaling_group_elb_health_check_enabled",
"CheckTitle": "Check if Auto Scaling groups associated with a load balancer use ELB health checks.",
"CheckType": [
"Software and Configuration Checks/AWS Security Best Practices"
],
"ServiceName": "autoscaling",
"SubServiceName": "",
"ResourceIdTemplate": "arn:aws:autoscaling:region:account-id:autoScalingGroup/autoScalingGroupName",
"Severity": "low",
"ResourceType": "AwsAutoScalingAutoScalingGroup",
"Description": "This control checks whether an Amazon EC2 Auto Scaling group that is associated with a load balancer uses Elastic Load Balancing (ELB) health checks. The control fails if the Auto Scaling group doesn't use ELB health checks.",
"Risk": "If ELB health checks are not enabled, the Auto Scaling group might not be able to accurately determine the health of instances, which could impact the availability and reliability of the applications running on these instances.",
"RelatedUrl": "https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-add-elb-healthcheck.html#as-add-elb-healthcheck-console",
"Remediation": {
"Code": {
"CLI": "aws autoscaling update-auto-scaling-group --auto-scaling-group-name <auto-scaling-group-name> --health-check-type ELB",
"NativeIaC": "",
"Other": "https://docs.aws.amazon.com/securityhub/latest/userguide/autoscaling-controls.html#autoscaling-1",
"Terraform": ""
},
"Recommendation": {
"Text": "Configure your Auto Scaling groups to use ELB health checks to improve the monitoring and availability of your applications.",
"Url": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/aws/AutoScaling/auto-scaling-group-health-check.html"
}
},
"Categories": [],
"DependsOn": [],
"RelatedTo": [],
"Notes": ""
}
@@ -0,0 +1,27 @@
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.autoscaling.autoscaling_client import (
autoscaling_client,
)
class autoscaling_group_elb_health_check_enabled(Check):
def execute(self):
findings = []
for group in autoscaling_client.groups:
if group.load_balancers and group.target_groups:
report = Check_Report_AWS(self.metadata())
report.region = group.region
report.resource_id = group.name
report.resource_arn = group.arn
report.resource_tags = group.tags
report.status = "FAIL"
report.status_extended = f"Autoscaling group {group.name} is associated with a load balancer but does not have ELB health checks enabled, instead it has {group.health_check_type} health checks."
if "ELB" in group.health_check_type:
report.status = "PASS"
report.status_extended = (
f"Autoscaling group {group.name} has ELB health checks enabled."
)
findings.append(report)
return findings
@@ -64,6 +64,9 @@ class AutoScaling(AWSService):
region=regional_client.region,
availability_zones=group.get("AvailabilityZones"),
tags=group.get("Tags"),
health_check_type=group.get("HealthCheckType", ""),
load_balancers=group.get("LoadBalancerNames", []),
target_groups=group.get("TargetGroupARNs", []),
)
)
@@ -130,6 +133,9 @@ class Group(BaseModel):
region: str
availability_zones: list
tags: list = []
health_check_type: str
load_balancers: list = []
target_groups: list = []
class ScalableTarget(BaseModel):
@@ -0,0 +1,427 @@
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_autoscaling_group_elb_health_check_enabled:
@mock_aws
def test_no_autoscaling(self):
autoscaling_client = client("autoscaling", region_name=AWS_REGION_US_EAST_1)
autoscaling_client.groups = []
from prowler.providers.aws.services.autoscaling.autoscaling_service import (
AutoScaling,
)
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.autoscaling.autoscaling_group_elb_health_check_enabled.autoscaling_group_elb_health_check_enabled.autoscaling_client",
new=AutoScaling(aws_provider),
):
# Test Check
from prowler.providers.aws.services.autoscaling.autoscaling_group_elb_health_check_enabled.autoscaling_group_elb_health_check_enabled import (
autoscaling_group_elb_health_check_enabled,
)
check = autoscaling_group_elb_health_check_enabled()
result = check.execute()
assert len(result) == 0
@mock_aws
def test_groups_with_elb_enabled(self):
autoscaling_client = client("autoscaling", region_name=AWS_REGION_US_EAST_1)
autoscaling_client.create_launch_configuration(
LaunchConfigurationName="test",
ImageId="ami-12c6146b",
InstanceType="t1.micro",
KeyName="the_keys",
SecurityGroups=["default", "default2"],
)
ec2_client = client("ec2", region_name=AWS_REGION_US_EAST_1)
vpc_id = ec2_client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]["VpcId"]
elastic_load_balancer = client("elbv2", region_name=AWS_REGION_US_EAST_1)
target_group = elastic_load_balancer.create_target_group(
Name="my-target-group",
Protocol="HTTP",
Port=80,
VpcId=vpc_id,
HealthCheckProtocol="HTTP",
HealthCheckPort="80",
HealthCheckPath="/",
HealthCheckIntervalSeconds=30,
HealthCheckTimeoutSeconds=5,
HealthyThresholdCount=5,
UnhealthyThresholdCount=2,
Matcher={"HttpCode": "200"},
)
autoscaling_group_name = "my-autoscaling-group"
autoscaling_client.create_auto_scaling_group(
AutoScalingGroupName=autoscaling_group_name,
LaunchConfigurationName="test",
MinSize=0,
MaxSize=0,
DesiredCapacity=0,
AvailabilityZones=["us-east-1a", "us-east-1b"],
HealthCheckType="ELB",
LoadBalancerNames=["my-load-balancer"],
TargetGroupARNs=[target_group["TargetGroups"][0]["TargetGroupArn"]],
)
autoscaling_group_arn = autoscaling_client.describe_auto_scaling_groups(
AutoScalingGroupNames=[autoscaling_group_name]
)["AutoScalingGroups"][0]["AutoScalingGroupARN"]
from prowler.providers.aws.services.autoscaling.autoscaling_service import (
AutoScaling,
)
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.autoscaling.autoscaling_group_elb_health_check_enabled.autoscaling_group_elb_health_check_enabled.autoscaling_client",
new=AutoScaling(aws_provider),
):
# Test Check
from prowler.providers.aws.services.autoscaling.autoscaling_group_elb_health_check_enabled.autoscaling_group_elb_health_check_enabled import (
autoscaling_group_elb_health_check_enabled,
)
check = autoscaling_group_elb_health_check_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== f"Autoscaling group {autoscaling_group_name} has ELB health checks enabled."
)
assert result[0].resource_id == autoscaling_group_name
assert result[0].resource_arn == autoscaling_group_arn
assert result[0].region == AWS_REGION_US_EAST_1
assert result[0].resource_tags == []
@mock_aws
def test_groups_with_ec2_enabled(self):
autoscaling_client = client("autoscaling", region_name=AWS_REGION_US_EAST_1)
autoscaling_client.create_launch_configuration(
LaunchConfigurationName="test",
ImageId="ami-12c6146b",
InstanceType="t1.micro",
KeyName="the_keys",
SecurityGroups=["default", "default2"],
)
ec2_client = client("ec2", region_name=AWS_REGION_US_EAST_1)
vpc_id = ec2_client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]["VpcId"]
elastic_load_balancer = client("elbv2", region_name=AWS_REGION_US_EAST_1)
target_group = elastic_load_balancer.create_target_group(
Name="my-target-group",
Protocol="HTTP",
Port=80,
VpcId=vpc_id,
HealthCheckProtocol="HTTP",
HealthCheckPort="80",
HealthCheckPath="/",
HealthCheckIntervalSeconds=30,
HealthCheckTimeoutSeconds=5,
HealthyThresholdCount=5,
UnhealthyThresholdCount=2,
Matcher={"HttpCode": "200"},
)
autoscaling_group_name = "my-autoscaling-group"
autoscaling_client.create_auto_scaling_group(
AutoScalingGroupName=autoscaling_group_name,
LaunchConfigurationName="test",
MinSize=0,
MaxSize=0,
DesiredCapacity=0,
AvailabilityZones=["us-east-1a"],
HealthCheckType="EC2",
LoadBalancerNames=["my-load-balancer"],
TargetGroupARNs=[target_group["TargetGroups"][0]["TargetGroupArn"]],
)
autoscaling_group_arn = autoscaling_client.describe_auto_scaling_groups(
AutoScalingGroupNames=[autoscaling_group_name]
)["AutoScalingGroups"][0]["AutoScalingGroupARN"]
from prowler.providers.aws.services.autoscaling.autoscaling_service import (
AutoScaling,
)
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.autoscaling.autoscaling_group_elb_health_check_enabled.autoscaling_group_elb_health_check_enabled.autoscaling_client",
new=AutoScaling(aws_provider),
):
# Test Check
from prowler.providers.aws.services.autoscaling.autoscaling_group_elb_health_check_enabled.autoscaling_group_elb_health_check_enabled import (
autoscaling_group_elb_health_check_enabled,
)
check = autoscaling_group_elb_health_check_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== f"Autoscaling group {autoscaling_group_name} is associated with a load balancer but does not have ELB health checks enabled, instead it has EC2 health checks."
)
assert result[0].resource_id == autoscaling_group_name
assert result[0].resource_tags == []
assert result[0].resource_arn == autoscaling_group_arn
@mock_aws
def test_groups_with_elb_and_ec2_enabled(self):
autoscaling_client = client("autoscaling", region_name=AWS_REGION_US_EAST_1)
autoscaling_client.create_launch_configuration(
LaunchConfigurationName="test",
ImageId="ami-12c6146b",
InstanceType="t1.micro",
KeyName="the_keys",
SecurityGroups=["default", "default2"],
)
ec2_client = client("ec2", region_name=AWS_REGION_US_EAST_1)
vpc_id = ec2_client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]["VpcId"]
elastic_load_balancer = client("elbv2", region_name=AWS_REGION_US_EAST_1)
target_group = elastic_load_balancer.create_target_group(
Name="my-target-group",
Protocol="HTTP",
Port=80,
VpcId=vpc_id,
HealthCheckProtocol="HTTP",
HealthCheckPort="80",
HealthCheckPath="/",
HealthCheckIntervalSeconds=30,
HealthCheckTimeoutSeconds=5,
HealthyThresholdCount=5,
UnhealthyThresholdCount=2,
Matcher={"HttpCode": "200"},
)
autoscaling_group_name = "my-autoscaling-group"
autoscaling_client.create_auto_scaling_group(
AutoScalingGroupName=autoscaling_group_name,
LaunchConfigurationName="test",
MinSize=0,
MaxSize=0,
DesiredCapacity=0,
AvailabilityZones=["us-east-1a"],
HealthCheckType="EC2,ELB",
LoadBalancerNames=["my-load-balancer"],
TargetGroupARNs=[target_group["TargetGroups"][0]["TargetGroupArn"]],
)
autoscaling_group_arn = autoscaling_client.describe_auto_scaling_groups(
AutoScalingGroupNames=[autoscaling_group_name]
)["AutoScalingGroups"][0]["AutoScalingGroupARN"]
from prowler.providers.aws.services.autoscaling.autoscaling_service import (
AutoScaling,
)
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.autoscaling.autoscaling_group_elb_health_check_enabled.autoscaling_group_elb_health_check_enabled.autoscaling_client",
new=AutoScaling(aws_provider),
):
# Test Check
from prowler.providers.aws.services.autoscaling.autoscaling_group_elb_health_check_enabled.autoscaling_group_elb_health_check_enabled import (
autoscaling_group_elb_health_check_enabled,
)
check = autoscaling_group_elb_health_check_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== f"Autoscaling group {autoscaling_group_name} has ELB health checks enabled."
)
assert result[0].resource_id == autoscaling_group_name
assert result[0].resource_tags == []
assert result[0].resource_arn == autoscaling_group_arn
@mock_aws
def test_groups_without_load_balancer_names(self):
autoscaling_client = client("autoscaling", region_name=AWS_REGION_US_EAST_1)
autoscaling_client.create_launch_configuration(
LaunchConfigurationName="test",
ImageId="ami-12c6146b",
InstanceType="t1.micro",
KeyName="the_keys",
SecurityGroups=["default", "default2"],
)
ec2_client = client("ec2", region_name=AWS_REGION_US_EAST_1)
vpc_id = ec2_client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]["VpcId"]
elastic_load_balancer = client("elbv2", region_name=AWS_REGION_US_EAST_1)
target_group = elastic_load_balancer.create_target_group(
Name="my-target-group",
Protocol="HTTP",
Port=80,
VpcId=vpc_id,
HealthCheckProtocol="HTTP",
HealthCheckPort="80",
HealthCheckPath="/",
HealthCheckIntervalSeconds=30,
HealthCheckTimeoutSeconds=5,
HealthyThresholdCount=5,
UnhealthyThresholdCount=2,
Matcher={"HttpCode": "200"},
)
autoscaling_group_name = "my-autoscaling-group"
autoscaling_client.create_auto_scaling_group(
AutoScalingGroupName=autoscaling_group_name,
LaunchConfigurationName="test",
MinSize=0,
MaxSize=0,
DesiredCapacity=0,
AvailabilityZones=["us-east-1a"],
HealthCheckType="EC2,ELB",
TargetGroupARNs=[target_group["TargetGroups"][0]["TargetGroupArn"]],
)
from prowler.providers.aws.services.autoscaling.autoscaling_service import (
AutoScaling,
)
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.autoscaling.autoscaling_group_elb_health_check_enabled.autoscaling_group_elb_health_check_enabled.autoscaling_client",
new=AutoScaling(aws_provider),
):
# Test Check
from prowler.providers.aws.services.autoscaling.autoscaling_group_elb_health_check_enabled.autoscaling_group_elb_health_check_enabled import (
autoscaling_group_elb_health_check_enabled,
)
check = autoscaling_group_elb_health_check_enabled()
result = check.execute()
assert len(result) == 0
@mock_aws
def test_groups_without_target_groups(self):
autoscaling_client = client("autoscaling", region_name=AWS_REGION_US_EAST_1)
autoscaling_client.create_launch_configuration(
LaunchConfigurationName="test",
ImageId="ami-12c6146b",
InstanceType="t1.micro",
KeyName="the_keys",
SecurityGroups=["default", "default2"],
)
autoscaling_group_name = "my-autoscaling-group"
autoscaling_client.create_auto_scaling_group(
AutoScalingGroupName=autoscaling_group_name,
LaunchConfigurationName="test",
MinSize=0,
MaxSize=0,
DesiredCapacity=0,
AvailabilityZones=["us-east-1a"],
HealthCheckType="EC2,ELB",
LoadBalancerNames=["my-load-balancer"],
)
from prowler.providers.aws.services.autoscaling.autoscaling_service import (
AutoScaling,
)
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.autoscaling.autoscaling_group_elb_health_check_enabled.autoscaling_group_elb_health_check_enabled.autoscaling_client",
new=AutoScaling(aws_provider),
):
# Test Check
from prowler.providers.aws.services.autoscaling.autoscaling_group_elb_health_check_enabled.autoscaling_group_elb_health_check_enabled import (
autoscaling_group_elb_health_check_enabled,
)
check = autoscaling_group_elb_health_check_enabled()
result = check.execute()
assert len(result) == 0
@mock_aws
def test_groups_without_target_groups_and_load_balancer_names(self):
autoscaling_client = client("autoscaling", region_name=AWS_REGION_US_EAST_1)
autoscaling_client.create_launch_configuration(
LaunchConfigurationName="test",
ImageId="ami-12c6146b",
InstanceType="t1.micro",
KeyName="the_keys",
SecurityGroups=["default", "default2"],
)
autoscaling_group_name = "my-autoscaling-group"
autoscaling_client.create_auto_scaling_group(
AutoScalingGroupName=autoscaling_group_name,
LaunchConfigurationName="test",
MinSize=0,
MaxSize=0,
DesiredCapacity=0,
AvailabilityZones=["us-east-1a"],
HealthCheckType="EC2,ELB",
)
from prowler.providers.aws.services.autoscaling.autoscaling_service import (
AutoScaling,
)
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.autoscaling.autoscaling_group_elb_health_check_enabled.autoscaling_group_elb_health_check_enabled.autoscaling_client",
new=AutoScaling(aws_provider),
):
# Test Check
from prowler.providers.aws.services.autoscaling.autoscaling_group_elb_health_check_enabled.autoscaling_group_elb_health_check_enabled import (
autoscaling_group_elb_health_check_enabled,
)
check = autoscaling_group_elb_health_check_enabled()
result = check.execute()
assert len(result) == 0
@@ -97,6 +97,26 @@ class Test_AutoScaling_Service:
KeyName="the_keys",
SecurityGroups=["default", "default2"],
)
ec2_client = client("ec2", region_name=AWS_REGION_US_EAST_1)
vpc_id = ec2_client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]["VpcId"]
elastic_load_balancer = client("elbv2", region_name=AWS_REGION_US_EAST_1)
target_group = elastic_load_balancer.create_target_group(
Name="my-target-group",
Protocol="HTTP",
Port=80,
VpcId=vpc_id,
HealthCheckProtocol="HTTP",
HealthCheckPort="80",
HealthCheckPath="/",
HealthCheckIntervalSeconds=30,
HealthCheckTimeoutSeconds=5,
HealthyThresholdCount=5,
UnhealthyThresholdCount=2,
Matcher={"HttpCode": "200"},
)
_ = autoscaling_client.create_auto_scaling_group(
AutoScalingGroupName="my-autoscaling-group",
LaunchConfigurationName="test",
@@ -110,6 +130,9 @@ class Test_AutoScaling_Service:
"Value": "value_test",
},
],
HealthCheckType="ELB",
LoadBalancerNames=["my-load-balancer"],
TargetGroupARNs=[target_group["TargetGroups"][0]["TargetGroupArn"]],
)
# AutoScaling client for this test class
@@ -130,6 +153,11 @@ class Test_AutoScaling_Service:
"Value": "value_test",
}
]
assert autoscaling.groups[0].health_check_type == "ELB"
assert autoscaling.groups[0].load_balancers == ["my-load-balancer"]
assert autoscaling.groups[0].target_groups == [
target_group["TargetGroups"][0]["TargetGroupArn"]
]
# Test Application AutoScaling Describe Scalable Targets
@mock_aws