mirror of
https://github.com/ghndrx/prowler.git
synced 2026-02-10 23:05:05 +00:00
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:
@@ -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": ""
|
||||
}
|
||||
@@ -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
|
||||
@@ -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"
|
||||
)
|
||||
Reference in New Issue
Block a user