feat(vpc): add check vpc_subnet_no_public_ip_by_default (#2472)

Co-authored-by: Sergio Garcia <38561120+sergargar@users.noreply.github.com>
This commit is contained in:
Sebastian Nyberg
2023-06-12 10:44:10 +03:00
committed by GitHub
parent 9212d24685
commit 49b2a559ae
4 changed files with 181 additions and 0 deletions

View File

@@ -0,0 +1,32 @@
{
"Provider": "aws",
"CheckID": "vpc_subnet_no_public_ip_by_default",
"CheckTitle": "Ensure VPC subnets do not assign public IP by default",
"CheckType": [
"Infrastructure Security"
],
"ServiceName": "vpc",
"SubServiceName": "subnet",
"ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id",
"Severity": "medium",
"ResourceType": "AwsEc2Subnet",
"Description": "Ensure VPC subnets do not assign public IP by default",
"Risk": "VPC subnet is a part of the VPC having its own rules for traffic. Assigning the Public IP to the subnet automatically (on launch) can accidentally expose the instances within this subnet to internet and should be edited to 'No' post creation of the Subnet.",
"RelatedUrl": "https://docs.aws.amazon.com/config/latest/developerguide/subnet-auto-assign-public-ip-disabled.html",
"Remediation": {
"Code": {
"CLI": "",
"NativeIaC": "",
"Other": "",
"Terraform": "https://docs.bridgecrew.io/docs/ensure-vpc-subnets-do-not-assign-public-ip-by-default#terraform"
},
"Recommendation": {
"Text": "VPC subnets should not allow automatic public IP assignment",
"Url": "https://docs.aws.amazon.com/config/latest/developerguide/subnet-auto-assign-public-ip-disabled.html"
}
},
"Categories": [],
"DependsOn": [],
"RelatedTo": [],
"Notes": ""
}

View File

@@ -0,0 +1,27 @@
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.vpc.vpc_client import vpc_client
class vpc_subnet_no_public_ip_by_default(Check):
def execute(self):
findings = []
for vpc in vpc_client.vpcs.values():
for subnet in vpc.subnets:
report = Check_Report_AWS(self.metadata())
report.region = subnet.region
report.resource_tags = subnet.tags
report.resource_id = subnet.id
if subnet.mapPublicIpOnLaunch:
report.status = "FAIL"
report.status_extended = (
f"VPC subnet {subnet.id} assigns public IP by default"
)
else:
report.status = "PASS"
report.status_extended = (
f"VPC subnet {subnet.id} does NOT assign public IP by default"
)
findings.append(report)
return findings

View File

@@ -0,0 +1,122 @@
from unittest import mock
from boto3 import client, session
from moto import mock_ec2
from prowler.providers.aws.lib.audit_info.models import AWS_Audit_Info
AWS_REGION = "us-east-1"
AWS_ACCOUNT_NUMBER = "123456789012"
class Test_vpc_subnet_separate_private_public:
def set_mocked_audit_info(self):
audit_info = AWS_Audit_Info(
session_config=None,
original_session=None,
audit_session=session.Session(
profile_name=None,
botocore_session=None,
),
audited_account=AWS_ACCOUNT_NUMBER,
audited_user_id=None,
audited_partition="aws",
audited_identity_arn=None,
profile=None,
profile_region=None,
credentials=None,
assumed_role_info=None,
audited_regions=["us-east-1", "eu-west-1"],
organizations_metadata=None,
audit_resources=None,
)
return audit_info
@mock_ec2
def test_vpc_with_map_ip_on_launch(self):
ec2_client = client("ec2", region_name=AWS_REGION)
vpc = ec2_client.create_vpc(
CidrBlock="172.28.7.0/24", InstanceTenancy="default"
)
subnet_private = ec2_client.create_subnet(
VpcId=vpc["Vpc"]["VpcId"],
CidrBlock="172.28.7.192/26",
AvailabilityZone=f"{AWS_REGION}a",
)
ec2_client.modify_subnet_attribute(
SubnetId=subnet_private["Subnet"]["SubnetId"],
MapPublicIpOnLaunch={"Value": True},
)
from prowler.providers.aws.services.vpc.vpc_service import VPC
current_audit_info = self.set_mocked_audit_info()
with mock.patch(
"prowler.providers.aws.lib.audit_info.audit_info.current_audit_info",
new=current_audit_info,
):
with mock.patch(
"prowler.providers.aws.services.vpc.vpc_subnet_separate_private_public.vpc_subnet_separate_private_public.vpc_client",
new=VPC(current_audit_info),
):
from prowler.providers.aws.services.vpc.vpc_subnet_no_public_ip_by_default.vpc_subnet_no_public_ip_by_default import (
vpc_subnet_no_public_ip_by_default,
)
check = vpc_subnet_no_public_ip_by_default()
results = check.execute()
for result in results:
if result.resource_id == subnet_private["Subnet"]["SubnetId"]:
assert result.status == "FAIL"
assert (
result.status_extended
== f"VPC subnet {subnet_private['Subnet']['SubnetId']} assigns public IP by default"
)
@mock_ec2
def test_vpc_without_map_ip_on_launch(self):
ec2_client = client("ec2", region_name=AWS_REGION)
vpc = ec2_client.create_vpc(
CidrBlock="172.28.7.0/24", InstanceTenancy="default"
)
subnet_private = ec2_client.create_subnet(
VpcId=vpc["Vpc"]["VpcId"],
CidrBlock="172.28.7.192/26",
AvailabilityZone=f"{AWS_REGION}a",
)
ec2_client.modify_subnet_attribute(
SubnetId=subnet_private["Subnet"]["SubnetId"],
MapPublicIpOnLaunch={"Value": False},
)
from prowler.providers.aws.services.vpc.vpc_service import VPC
current_audit_info = self.set_mocked_audit_info()
with mock.patch(
"prowler.providers.aws.lib.audit_info.audit_info.current_audit_info",
new=current_audit_info,
):
with mock.patch(
"prowler.providers.aws.services.vpc.vpc_subnet_separate_private_public.vpc_subnet_separate_private_public.vpc_client",
new=VPC(current_audit_info),
):
from prowler.providers.aws.services.vpc.vpc_subnet_no_public_ip_by_default.vpc_subnet_no_public_ip_by_default import (
vpc_subnet_no_public_ip_by_default,
)
check = vpc_subnet_no_public_ip_by_default()
results = check.execute()
for result in results:
if result.resource_id == subnet_private["Subnet"]["SubnetId"]:
assert result.status == "PASS"
assert (
result.status_extended
== f"VPC subnet {subnet_private['Subnet']['SubnetId']} does NOT assign public IP by default"
)