diff --git a/prowler/providers/aws/services/autoscaling/autoscaling_group_elb_health_check_enabled/__init__.py b/prowler/providers/aws/services/autoscaling/autoscaling_group_elb_health_check_enabled/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/aws/services/autoscaling/autoscaling_group_elb_health_check_enabled/autoscaling_group_elb_health_check_enabled.metadata.json b/prowler/providers/aws/services/autoscaling/autoscaling_group_elb_health_check_enabled/autoscaling_group_elb_health_check_enabled.metadata.json new file mode 100644 index 0000000000..3538daa3fc --- /dev/null +++ b/prowler/providers/aws/services/autoscaling/autoscaling_group_elb_health_check_enabled/autoscaling_group_elb_health_check_enabled.metadata.json @@ -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 --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": "" +} diff --git a/prowler/providers/aws/services/autoscaling/autoscaling_group_elb_health_check_enabled/autoscaling_group_elb_health_check_enabled.py b/prowler/providers/aws/services/autoscaling/autoscaling_group_elb_health_check_enabled/autoscaling_group_elb_health_check_enabled.py new file mode 100644 index 0000000000..02a18f29d6 --- /dev/null +++ b/prowler/providers/aws/services/autoscaling/autoscaling_group_elb_health_check_enabled/autoscaling_group_elb_health_check_enabled.py @@ -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 diff --git a/prowler/providers/aws/services/autoscaling/autoscaling_service.py b/prowler/providers/aws/services/autoscaling/autoscaling_service.py index 93a84340e1..f9b2a1511e 100644 --- a/prowler/providers/aws/services/autoscaling/autoscaling_service.py +++ b/prowler/providers/aws/services/autoscaling/autoscaling_service.py @@ -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): diff --git a/tests/providers/aws/services/autoscaling/autoscaling_group_elb_health_check_enabled/autoscaling_group_elb_health_check_enabled_test.py b/tests/providers/aws/services/autoscaling/autoscaling_group_elb_health_check_enabled/autoscaling_group_elb_health_check_enabled_test.py new file mode 100644 index 0000000000..df72d88660 --- /dev/null +++ b/tests/providers/aws/services/autoscaling/autoscaling_group_elb_health_check_enabled/autoscaling_group_elb_health_check_enabled_test.py @@ -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 diff --git a/tests/providers/aws/services/autoscaling/autoscaling_service_test.py b/tests/providers/aws/services/autoscaling/autoscaling_service_test.py index a891dd033e..3e5f124227 100644 --- a/tests/providers/aws/services/autoscaling/autoscaling_service_test.py +++ b/tests/providers/aws/services/autoscaling/autoscaling_service_test.py @@ -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