mirror of
https://github.com/ghndrx/prowler.git
synced 2026-02-10 14:55:00 +00:00
feat(workspaces): New check workspaces_vpc_2private_1public_subnets_nat (#2286)
Co-authored-by: Pepe Fagoaga <pepe@verica.io> Co-authored-by: n4ch04 <nachor1992@gmail.com>
This commit is contained in:
@@ -275,12 +275,14 @@ class VPC:
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
public = False
|
public = False
|
||||||
|
nat_gateway = False
|
||||||
for route in route_tables_for_subnet.get("RouteTables")[
|
for route in route_tables_for_subnet.get("RouteTables")[
|
||||||
0
|
0
|
||||||
].get("Routes"):
|
].get("Routes"):
|
||||||
if "GatewayId" in route and "igw" in route["GatewayId"]:
|
if "GatewayId" in route and "igw" in route["GatewayId"]:
|
||||||
public = True
|
public = True
|
||||||
break
|
if "NatGatewayId" in route:
|
||||||
|
nat_gateway = True
|
||||||
# Add it to to list of vpc_subnets and to the VPC object
|
# Add it to to list of vpc_subnets and to the VPC object
|
||||||
object = VpcSubnet(
|
object = VpcSubnet(
|
||||||
id=subnet["SubnetId"],
|
id=subnet["SubnetId"],
|
||||||
@@ -290,6 +292,7 @@ class VPC:
|
|||||||
region=regional_client.region,
|
region=regional_client.region,
|
||||||
availability_zone=subnet["AvailabilityZone"],
|
availability_zone=subnet["AvailabilityZone"],
|
||||||
public=public,
|
public=public,
|
||||||
|
nat_gateway=nat_gateway,
|
||||||
tags=subnet.get("Tags"),
|
tags=subnet.get("Tags"),
|
||||||
)
|
)
|
||||||
self.vpc_subnets[subnet["SubnetId"]] = object
|
self.vpc_subnets[subnet["SubnetId"]] = object
|
||||||
@@ -314,6 +317,7 @@ class VpcSubnet(BaseModel):
|
|||||||
cidr_block: str
|
cidr_block: str
|
||||||
availability_zone: str
|
availability_zone: str
|
||||||
public: bool
|
public: bool
|
||||||
|
nat_gateway: bool
|
||||||
region: str
|
region: str
|
||||||
tags: Optional[list] = []
|
tags: Optional[list] = []
|
||||||
|
|
||||||
|
|||||||
@@ -45,11 +45,13 @@ class WorkSpaces:
|
|||||||
)
|
)
|
||||||
):
|
):
|
||||||
workspace_to_append = WorkSpace(
|
workspace_to_append = WorkSpace(
|
||||||
id=workspace["WorkspaceId"], region=regional_client.region
|
id=workspace.get("WorkspaceId"),
|
||||||
|
region=regional_client.region,
|
||||||
|
subnet_id=workspace.get("SubnetId"),
|
||||||
)
|
)
|
||||||
if (
|
if (
|
||||||
"UserVolumeEncryptionEnabled" in workspace
|
"UserVolumeEncryptionEnabled" in workspace
|
||||||
and workspace["UserVolumeEncryptionEnabled"]
|
and workspace.get("UserVolumeEncryptionEnabled")
|
||||||
):
|
):
|
||||||
workspace_to_append.user_volume_encryption_enabled = True
|
workspace_to_append.user_volume_encryption_enabled = True
|
||||||
if (
|
if (
|
||||||
@@ -85,4 +87,5 @@ class WorkSpace(BaseModel):
|
|||||||
region: str
|
region: str
|
||||||
user_volume_encryption_enabled: bool = None
|
user_volume_encryption_enabled: bool = None
|
||||||
root_volume_encryption_enabled: bool = None
|
root_volume_encryption_enabled: bool = None
|
||||||
|
subnet_id: str = None
|
||||||
tags: Optional[list] = []
|
tags: Optional[list] = []
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"Provider": "aws",
|
||||||
|
"CheckID": "workspaces_vpc_2private_1public_subnets_nat",
|
||||||
|
"CheckTitle": "Ensure that the Workspaces VPC are deployed following the best practices using 1 public subnet and 2 private subnets with a NAT Gateway attached",
|
||||||
|
"CheckType": [],
|
||||||
|
"ServiceName": "workspaces",
|
||||||
|
"SubServiceName": "",
|
||||||
|
"ResourceIdTemplate": "arn:aws:workspaces:region:account-id:workspace",
|
||||||
|
"Severity": "medium",
|
||||||
|
"ResourceType": "AwsWorkspaces",
|
||||||
|
"Description": "Ensure that the Workspaces VPC are deployed following the best practices using 1 public subnet and 2 private subnets with a NAT Gateway attached",
|
||||||
|
"Risk": "Proper network segmentation is a key security best practice. Workspaces VPC should be deployed using 1 public subnet and 2 private subnets with a NAT Gateway attached",
|
||||||
|
"RelatedUrl": "https://docs.aws.amazon.com/workspaces/latest/adminguide/amazon-workspaces-vpc.html",
|
||||||
|
"Remediation": {
|
||||||
|
"Code": {
|
||||||
|
"CLI": "",
|
||||||
|
"NativeIaC": "",
|
||||||
|
"Other": "",
|
||||||
|
"Terraform": ""
|
||||||
|
},
|
||||||
|
"Recommendation": {
|
||||||
|
"Text": "Follow the documentation and deploy Workspaces VPC using 1 public subnet and 2 private subnets with a NAT Gateway attached",
|
||||||
|
"Url": "https://docs.aws.amazon.com/workspaces/latest/adminguide/amazon-workspaces-vpc.html"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Categories": [],
|
||||||
|
"DependsOn": [],
|
||||||
|
"RelatedTo": [],
|
||||||
|
"Notes": ""
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
from prowler.lib.check.models import Check, Check_Report_AWS
|
||||||
|
from prowler.providers.aws.services.vpc.vpc_client import vpc_client
|
||||||
|
from prowler.providers.aws.services.workspaces.workspaces_client import (
|
||||||
|
workspaces_client,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class workspaces_vpc_2private_1public_subnets_nat(Check):
|
||||||
|
def execute(self):
|
||||||
|
findings = []
|
||||||
|
for workspace in workspaces_client.workspaces:
|
||||||
|
report = Check_Report_AWS(self.metadata())
|
||||||
|
report.region = workspace.region
|
||||||
|
report.resource_id = workspace.id
|
||||||
|
report.resource_arn = workspace.arn
|
||||||
|
report.resource_tags = workspace.tags
|
||||||
|
report.status = "PASS"
|
||||||
|
report.status_extended = f"Workspace {workspace.id} is in a private subnet within a VPC which has 1 public subnet 2 private subnets with a NAT Gateway attached"
|
||||||
|
vpc_object = None
|
||||||
|
is_in_private_subnet = False
|
||||||
|
if workspace.subnet_id:
|
||||||
|
if vpc_client.vpcs[vpc_client.vpc_subnets[workspace.subnet_id].vpc_id]:
|
||||||
|
vpc_object = vpc_client.vpcs[
|
||||||
|
vpc_client.vpc_subnets[workspace.subnet_id].vpc_id
|
||||||
|
]
|
||||||
|
if vpc_client.vpc_subnets[workspace.subnet_id]:
|
||||||
|
if not vpc_client.vpc_subnets[workspace.subnet_id].public:
|
||||||
|
is_in_private_subnet = True
|
||||||
|
public_subnets = 0
|
||||||
|
private_subnets = 0
|
||||||
|
nat_gateway = False
|
||||||
|
if vpc_object:
|
||||||
|
for vpc_subnet in vpc_object.subnets:
|
||||||
|
if vpc_subnet.public:
|
||||||
|
public_subnets += 1
|
||||||
|
if not vpc_subnet.public:
|
||||||
|
private_subnets += 1
|
||||||
|
if vpc_subnet.nat_gateway:
|
||||||
|
nat_gateway = True
|
||||||
|
# Check NAT Gateway here
|
||||||
|
if (
|
||||||
|
public_subnets < 1
|
||||||
|
or private_subnets < 2
|
||||||
|
or not nat_gateway
|
||||||
|
or not is_in_private_subnet
|
||||||
|
):
|
||||||
|
report.status = "FAIL"
|
||||||
|
report.status_extended = f"Workspace {workspace.id} is not in a private subnet or its VPC has not 1 public subnet and 2 private subnets with a NAT Gateway attached"
|
||||||
|
|
||||||
|
findings.append(report)
|
||||||
|
return findings
|
||||||
@@ -70,6 +70,7 @@ class Test_networkfirewall_in_all_vpc:
|
|||||||
cidr_block="192.168.0.0/24",
|
cidr_block="192.168.0.0/24",
|
||||||
availability_zone="us-east-1a",
|
availability_zone="us-east-1a",
|
||||||
public=False,
|
public=False,
|
||||||
|
nat_gateway=False,
|
||||||
region=AWS_REGION,
|
region=AWS_REGION,
|
||||||
tags=[],
|
tags=[],
|
||||||
)
|
)
|
||||||
@@ -125,6 +126,7 @@ class Test_networkfirewall_in_all_vpc:
|
|||||||
cidr_block="192.168.0.0/24",
|
cidr_block="192.168.0.0/24",
|
||||||
availability_zone="us-east-1a",
|
availability_zone="us-east-1a",
|
||||||
public=False,
|
public=False,
|
||||||
|
nat_gateway=False,
|
||||||
region=AWS_REGION,
|
region=AWS_REGION,
|
||||||
tags=[],
|
tags=[],
|
||||||
)
|
)
|
||||||
@@ -190,6 +192,7 @@ class Test_networkfirewall_in_all_vpc:
|
|||||||
cidr_block="192.168.0.0/24",
|
cidr_block="192.168.0.0/24",
|
||||||
availability_zone="us-east-1a",
|
availability_zone="us-east-1a",
|
||||||
public=False,
|
public=False,
|
||||||
|
nat_gateway=False,
|
||||||
region=AWS_REGION,
|
region=AWS_REGION,
|
||||||
tags=[],
|
tags=[],
|
||||||
)
|
)
|
||||||
@@ -210,6 +213,7 @@ class Test_networkfirewall_in_all_vpc:
|
|||||||
cidr_block="192.168.0.0/24",
|
cidr_block="192.168.0.0/24",
|
||||||
availability_zone="us-east-1a",
|
availability_zone="us-east-1a",
|
||||||
public=False,
|
public=False,
|
||||||
|
nat_gateway=False,
|
||||||
region=AWS_REGION,
|
region=AWS_REGION,
|
||||||
tags=[],
|
tags=[],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -311,5 +311,6 @@ class Test_VPC_Service:
|
|||||||
assert vpc.subnets[0].cidr_block == "172.28.7.192/26"
|
assert vpc.subnets[0].cidr_block == "172.28.7.192/26"
|
||||||
assert vpc.subnets[0].availability_zone == f"{AWS_REGION}a"
|
assert vpc.subnets[0].availability_zone == f"{AWS_REGION}a"
|
||||||
assert vpc.subnets[0].public is False
|
assert vpc.subnets[0].public is False
|
||||||
|
assert vpc.subnets[0].nat_gateway is False
|
||||||
assert vpc.subnets[0].region == AWS_REGION
|
assert vpc.subnets[0].region == AWS_REGION
|
||||||
assert vpc.subnets[0].tags is None
|
assert vpc.subnets[0].tags is None
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ def mock_make_api_call(self, operation_name, kwarg):
|
|||||||
"WorkspaceId": workspace_id,
|
"WorkspaceId": workspace_id,
|
||||||
"UserVolumeEncryptionEnabled": True,
|
"UserVolumeEncryptionEnabled": True,
|
||||||
"RootVolumeEncryptionEnabled": True,
|
"RootVolumeEncryptionEnabled": True,
|
||||||
|
"SubnetId": "subnet-1234567890",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ class Test_workspaces_volume_encryption_enabled:
|
|||||||
region=AWS_REGION,
|
region=AWS_REGION,
|
||||||
user_volume_encryption_enabled=True,
|
user_volume_encryption_enabled=True,
|
||||||
root_volume_encryption_enabled=True,
|
root_volume_encryption_enabled=True,
|
||||||
|
subnet_id="subnet-12345678",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
with mock.patch(
|
with mock.patch(
|
||||||
@@ -64,6 +65,7 @@ class Test_workspaces_volume_encryption_enabled:
|
|||||||
region=AWS_REGION,
|
region=AWS_REGION,
|
||||||
user_volume_encryption_enabled=False,
|
user_volume_encryption_enabled=False,
|
||||||
root_volume_encryption_enabled=True,
|
root_volume_encryption_enabled=True,
|
||||||
|
subnet_id="subnet-12345678",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
with mock.patch(
|
with mock.patch(
|
||||||
@@ -91,6 +93,7 @@ class Test_workspaces_volume_encryption_enabled:
|
|||||||
region=AWS_REGION,
|
region=AWS_REGION,
|
||||||
user_volume_encryption_enabled=True,
|
user_volume_encryption_enabled=True,
|
||||||
root_volume_encryption_enabled=False,
|
root_volume_encryption_enabled=False,
|
||||||
|
subnet_id="subnet-12345678",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
with mock.patch(
|
with mock.patch(
|
||||||
@@ -118,6 +121,7 @@ class Test_workspaces_volume_encryption_enabled:
|
|||||||
region=AWS_REGION,
|
region=AWS_REGION,
|
||||||
user_volume_encryption_enabled=False,
|
user_volume_encryption_enabled=False,
|
||||||
root_volume_encryption_enabled=False,
|
root_volume_encryption_enabled=False,
|
||||||
|
subnet_id="subnet-12345678",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
with mock.patch(
|
with mock.patch(
|
||||||
|
|||||||
@@ -0,0 +1,462 @@
|
|||||||
|
from unittest import mock
|
||||||
|
from uuid import uuid4
|
||||||
|
|
||||||
|
from boto3 import client, session
|
||||||
|
from moto import mock_ec2
|
||||||
|
|
||||||
|
from prowler.providers.aws.lib.audit_info.models import AWS_Audit_Info
|
||||||
|
from prowler.providers.aws.services.vpc.vpc_service import VPC
|
||||||
|
from prowler.providers.aws.services.workspaces.workspaces_service import WorkSpace
|
||||||
|
|
||||||
|
AWS_REGION = "eu-west-1"
|
||||||
|
AWS_ACCOUNT_NUMBER = "123456789012"
|
||||||
|
workspace_id = str(uuid4())
|
||||||
|
|
||||||
|
|
||||||
|
class Test_workspaces_vpc_2private_1public_subnets_nat:
|
||||||
|
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
|
||||||
|
|
||||||
|
def test_no_workspaces(self):
|
||||||
|
workspaces_client = mock.MagicMock
|
||||||
|
workspaces_client.workspaces = []
|
||||||
|
vpc_client = mock.MagicMock
|
||||||
|
vpc_client.vpcs = []
|
||||||
|
with mock.patch(
|
||||||
|
"prowler.providers.aws.services.workspaces.workspaces_service.WorkSpaces",
|
||||||
|
workspaces_client,
|
||||||
|
):
|
||||||
|
with mock.patch(
|
||||||
|
"prowler.providers.aws.services.vpc.vpc_service.VPC",
|
||||||
|
vpc_client,
|
||||||
|
):
|
||||||
|
from prowler.providers.aws.services.workspaces.workspaces_vpc_2private_1public_subnets_nat.workspaces_vpc_2private_1public_subnets_nat import (
|
||||||
|
workspaces_vpc_2private_1public_subnets_nat,
|
||||||
|
)
|
||||||
|
|
||||||
|
check = workspaces_vpc_2private_1public_subnets_nat()
|
||||||
|
result = check.execute()
|
||||||
|
assert len(result) == 0
|
||||||
|
|
||||||
|
def test_workspaces_no_subnet(self):
|
||||||
|
workspaces_client = mock.MagicMock
|
||||||
|
workspaces_client = mock.MagicMock
|
||||||
|
workspaces_client.workspaces = []
|
||||||
|
workspaces_client.workspaces.append(
|
||||||
|
WorkSpace(
|
||||||
|
id=workspace_id,
|
||||||
|
region=AWS_REGION,
|
||||||
|
user_volume_encryption_enabled=True,
|
||||||
|
root_volume_encryption_enabled=True,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
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.workspaces.workspaces_vpc_2private_1public_subnets_nat.workspaces_vpc_2private_1public_subnets_nat.vpc_client",
|
||||||
|
new=VPC(current_audit_info),
|
||||||
|
):
|
||||||
|
with mock.patch(
|
||||||
|
"prowler.providers.aws.services.workspaces.workspaces_vpc_2private_1public_subnets_nat.workspaces_vpc_2private_1public_subnets_nat.workspaces_client",
|
||||||
|
new=workspaces_client,
|
||||||
|
):
|
||||||
|
from prowler.providers.aws.services.workspaces.workspaces_vpc_2private_1public_subnets_nat.workspaces_vpc_2private_1public_subnets_nat import (
|
||||||
|
workspaces_vpc_2private_1public_subnets_nat,
|
||||||
|
)
|
||||||
|
|
||||||
|
check = workspaces_vpc_2private_1public_subnets_nat()
|
||||||
|
result = check.execute()
|
||||||
|
assert len(result) == 1
|
||||||
|
assert result[0].status == "FAIL"
|
||||||
|
assert (
|
||||||
|
result[0].status_extended
|
||||||
|
== f"Workspace {workspace_id} is not in a private subnet or its VPC has not 1 public subnet and 2 private subnets with a NAT Gateway attached"
|
||||||
|
)
|
||||||
|
assert result[0].resource_id == workspace_id
|
||||||
|
assert result[0].resource_arn == ""
|
||||||
|
|
||||||
|
@mock_ec2
|
||||||
|
def test_workspaces_vpc_one_private_subnet(self):
|
||||||
|
# EC2 Client
|
||||||
|
ec2_client = client("ec2", region_name=AWS_REGION)
|
||||||
|
vpc = ec2_client.create_vpc(
|
||||||
|
CidrBlock="172.28.7.0/24", InstanceTenancy="default"
|
||||||
|
)
|
||||||
|
# VPC Private
|
||||||
|
subnet_private = ec2_client.create_subnet(
|
||||||
|
VpcId=vpc["Vpc"]["VpcId"],
|
||||||
|
CidrBlock="172.28.7.0/26",
|
||||||
|
AvailabilityZone=f"{AWS_REGION}a",
|
||||||
|
)
|
||||||
|
route_table_private = ec2_client.create_route_table(
|
||||||
|
VpcId=vpc["Vpc"]["VpcId"],
|
||||||
|
)
|
||||||
|
ec2_client.create_route(
|
||||||
|
DestinationCidrBlock="10.10.10.0",
|
||||||
|
RouteTableId=route_table_private["RouteTable"]["RouteTableId"],
|
||||||
|
)
|
||||||
|
ec2_client.associate_route_table(
|
||||||
|
RouteTableId=route_table_private["RouteTable"]["RouteTableId"],
|
||||||
|
SubnetId=subnet_private["Subnet"]["SubnetId"],
|
||||||
|
)
|
||||||
|
# Workspace Mock
|
||||||
|
workspaces_client = mock.MagicMock
|
||||||
|
workspaces_client.workspaces = []
|
||||||
|
workspaces_client.workspaces.append(
|
||||||
|
WorkSpace(
|
||||||
|
id=workspace_id,
|
||||||
|
region=AWS_REGION,
|
||||||
|
user_volume_encryption_enabled=True,
|
||||||
|
root_volume_encryption_enabled=True,
|
||||||
|
subnet_id=subnet_private["Subnet"]["SubnetId"],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
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.workspaces.workspaces_vpc_2private_1public_subnets_nat.workspaces_vpc_2private_1public_subnets_nat.vpc_client",
|
||||||
|
new=VPC(current_audit_info),
|
||||||
|
):
|
||||||
|
with mock.patch(
|
||||||
|
"prowler.providers.aws.services.workspaces.workspaces_vpc_2private_1public_subnets_nat.workspaces_vpc_2private_1public_subnets_nat.workspaces_client",
|
||||||
|
new=workspaces_client,
|
||||||
|
):
|
||||||
|
from prowler.providers.aws.services.workspaces.workspaces_vpc_2private_1public_subnets_nat.workspaces_vpc_2private_1public_subnets_nat import (
|
||||||
|
workspaces_vpc_2private_1public_subnets_nat,
|
||||||
|
)
|
||||||
|
|
||||||
|
check = workspaces_vpc_2private_1public_subnets_nat()
|
||||||
|
result = check.execute()
|
||||||
|
assert len(result) == 1
|
||||||
|
assert result[0].status == "FAIL"
|
||||||
|
assert (
|
||||||
|
result[0].status_extended
|
||||||
|
== f"Workspace {workspace_id} is not in a private subnet or its VPC has not 1 public subnet and 2 private subnets with a NAT Gateway attached"
|
||||||
|
)
|
||||||
|
assert result[0].resource_id == workspace_id
|
||||||
|
assert result[0].resource_arn == ""
|
||||||
|
|
||||||
|
@mock_ec2
|
||||||
|
def test_workspaces_vpc_two_private_subnet(self):
|
||||||
|
# EC2 Client
|
||||||
|
ec2_client = client("ec2", region_name=AWS_REGION)
|
||||||
|
vpc = ec2_client.create_vpc(
|
||||||
|
CidrBlock="172.28.7.0/24", InstanceTenancy="default"
|
||||||
|
)
|
||||||
|
# VPC Private
|
||||||
|
subnet_private = ec2_client.create_subnet(
|
||||||
|
VpcId=vpc["Vpc"]["VpcId"],
|
||||||
|
CidrBlock="172.28.7.0/26",
|
||||||
|
AvailabilityZone=f"{AWS_REGION}a",
|
||||||
|
)
|
||||||
|
route_table_private = ec2_client.create_route_table(
|
||||||
|
VpcId=vpc["Vpc"]["VpcId"],
|
||||||
|
)
|
||||||
|
ec2_client.create_route(
|
||||||
|
DestinationCidrBlock="10.10.10.0",
|
||||||
|
RouteTableId=route_table_private["RouteTable"]["RouteTableId"],
|
||||||
|
)
|
||||||
|
ec2_client.associate_route_table(
|
||||||
|
RouteTableId=route_table_private["RouteTable"]["RouteTableId"],
|
||||||
|
SubnetId=subnet_private["Subnet"]["SubnetId"],
|
||||||
|
)
|
||||||
|
# VPC Private 2
|
||||||
|
subnet_private_2 = ec2_client.create_subnet(
|
||||||
|
VpcId=vpc["Vpc"]["VpcId"],
|
||||||
|
CidrBlock="172.28.7.64/26",
|
||||||
|
AvailabilityZone=f"{AWS_REGION}a",
|
||||||
|
)
|
||||||
|
route_table_private_2 = ec2_client.create_route_table(
|
||||||
|
VpcId=vpc["Vpc"]["VpcId"],
|
||||||
|
)
|
||||||
|
ec2_client.create_route(
|
||||||
|
DestinationCidrBlock="10.10.10.0",
|
||||||
|
RouteTableId=route_table_private_2["RouteTable"]["RouteTableId"],
|
||||||
|
)
|
||||||
|
ec2_client.associate_route_table(
|
||||||
|
RouteTableId=route_table_private_2["RouteTable"]["RouteTableId"],
|
||||||
|
SubnetId=subnet_private_2["Subnet"]["SubnetId"],
|
||||||
|
)
|
||||||
|
# Workspace Mock
|
||||||
|
workspaces_client = mock.MagicMock
|
||||||
|
workspaces_client.workspaces = []
|
||||||
|
workspaces_client.workspaces.append(
|
||||||
|
WorkSpace(
|
||||||
|
id=workspace_id,
|
||||||
|
region=AWS_REGION,
|
||||||
|
user_volume_encryption_enabled=True,
|
||||||
|
root_volume_encryption_enabled=True,
|
||||||
|
subnet_id=subnet_private["Subnet"]["SubnetId"],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
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.workspaces.workspaces_vpc_2private_1public_subnets_nat.workspaces_vpc_2private_1public_subnets_nat.vpc_client",
|
||||||
|
new=VPC(current_audit_info),
|
||||||
|
):
|
||||||
|
with mock.patch(
|
||||||
|
"prowler.providers.aws.services.workspaces.workspaces_vpc_2private_1public_subnets_nat.workspaces_vpc_2private_1public_subnets_nat.workspaces_client",
|
||||||
|
new=workspaces_client,
|
||||||
|
):
|
||||||
|
from prowler.providers.aws.services.workspaces.workspaces_vpc_2private_1public_subnets_nat.workspaces_vpc_2private_1public_subnets_nat import (
|
||||||
|
workspaces_vpc_2private_1public_subnets_nat,
|
||||||
|
)
|
||||||
|
|
||||||
|
check = workspaces_vpc_2private_1public_subnets_nat()
|
||||||
|
result = check.execute()
|
||||||
|
assert len(result) == 1
|
||||||
|
assert result[0].status == "FAIL"
|
||||||
|
assert (
|
||||||
|
result[0].status_extended
|
||||||
|
== f"Workspace {workspace_id} is not in a private subnet or its VPC has not 1 public subnet and 2 private subnets with a NAT Gateway attached"
|
||||||
|
)
|
||||||
|
assert result[0].resource_id == workspace_id
|
||||||
|
assert result[0].resource_arn == ""
|
||||||
|
|
||||||
|
@mock_ec2
|
||||||
|
def test_workspaces_vpc_two_private_subnet_one_public(self):
|
||||||
|
# EC2 Client
|
||||||
|
ec2_client = client("ec2", region_name=AWS_REGION)
|
||||||
|
vpc = ec2_client.create_vpc(
|
||||||
|
CidrBlock="172.28.7.0/24", InstanceTenancy="default"
|
||||||
|
)
|
||||||
|
# VPC Private
|
||||||
|
subnet_private = ec2_client.create_subnet(
|
||||||
|
VpcId=vpc["Vpc"]["VpcId"],
|
||||||
|
CidrBlock="172.28.7.0/26",
|
||||||
|
AvailabilityZone=f"{AWS_REGION}a",
|
||||||
|
)
|
||||||
|
route_table_private = ec2_client.create_route_table(
|
||||||
|
VpcId=vpc["Vpc"]["VpcId"],
|
||||||
|
)
|
||||||
|
ec2_client.create_route(
|
||||||
|
DestinationCidrBlock="10.10.10.0",
|
||||||
|
RouteTableId=route_table_private["RouteTable"]["RouteTableId"],
|
||||||
|
)
|
||||||
|
ec2_client.associate_route_table(
|
||||||
|
RouteTableId=route_table_private["RouteTable"]["RouteTableId"],
|
||||||
|
SubnetId=subnet_private["Subnet"]["SubnetId"],
|
||||||
|
)
|
||||||
|
# VPC Private 2
|
||||||
|
subnet_private_2 = ec2_client.create_subnet(
|
||||||
|
VpcId=vpc["Vpc"]["VpcId"],
|
||||||
|
CidrBlock="172.28.7.64/26",
|
||||||
|
AvailabilityZone=f"{AWS_REGION}a",
|
||||||
|
)
|
||||||
|
route_table_private_2 = ec2_client.create_route_table(
|
||||||
|
VpcId=vpc["Vpc"]["VpcId"],
|
||||||
|
)
|
||||||
|
ec2_client.create_route(
|
||||||
|
DestinationCidrBlock="10.10.10.0",
|
||||||
|
RouteTableId=route_table_private_2["RouteTable"]["RouteTableId"],
|
||||||
|
)
|
||||||
|
ec2_client.associate_route_table(
|
||||||
|
RouteTableId=route_table_private_2["RouteTable"]["RouteTableId"],
|
||||||
|
SubnetId=subnet_private_2["Subnet"]["SubnetId"],
|
||||||
|
)
|
||||||
|
# VPC Public
|
||||||
|
subnet_public = ec2_client.create_subnet(
|
||||||
|
VpcId=vpc["Vpc"]["VpcId"],
|
||||||
|
CidrBlock="172.28.7.192/26",
|
||||||
|
AvailabilityZone=f"{AWS_REGION}a",
|
||||||
|
)
|
||||||
|
route_table_public = ec2_client.create_route_table(
|
||||||
|
VpcId=vpc["Vpc"]["VpcId"],
|
||||||
|
)
|
||||||
|
igw = ec2_client.create_internet_gateway()
|
||||||
|
ec2_client.create_route(
|
||||||
|
DestinationCidrBlock="0.0.0.0",
|
||||||
|
RouteTableId=route_table_public["RouteTable"]["RouteTableId"],
|
||||||
|
GatewayId=igw["InternetGateway"]["InternetGatewayId"],
|
||||||
|
)
|
||||||
|
ec2_client.associate_route_table(
|
||||||
|
RouteTableId=route_table_public["RouteTable"]["RouteTableId"],
|
||||||
|
SubnetId=subnet_public["Subnet"]["SubnetId"],
|
||||||
|
)
|
||||||
|
# Workspace Mock
|
||||||
|
workspaces_client = mock.MagicMock
|
||||||
|
workspaces_client.workspaces = []
|
||||||
|
workspaces_client.workspaces.append(
|
||||||
|
WorkSpace(
|
||||||
|
id=workspace_id,
|
||||||
|
region=AWS_REGION,
|
||||||
|
user_volume_encryption_enabled=True,
|
||||||
|
root_volume_encryption_enabled=True,
|
||||||
|
subnet_id=subnet_private["Subnet"]["SubnetId"],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
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.workspaces.workspaces_vpc_2private_1public_subnets_nat.workspaces_vpc_2private_1public_subnets_nat.vpc_client",
|
||||||
|
new=VPC(current_audit_info),
|
||||||
|
):
|
||||||
|
with mock.patch(
|
||||||
|
"prowler.providers.aws.services.workspaces.workspaces_vpc_2private_1public_subnets_nat.workspaces_vpc_2private_1public_subnets_nat.workspaces_client",
|
||||||
|
new=workspaces_client,
|
||||||
|
):
|
||||||
|
from prowler.providers.aws.services.workspaces.workspaces_vpc_2private_1public_subnets_nat.workspaces_vpc_2private_1public_subnets_nat import (
|
||||||
|
workspaces_vpc_2private_1public_subnets_nat,
|
||||||
|
)
|
||||||
|
|
||||||
|
check = workspaces_vpc_2private_1public_subnets_nat()
|
||||||
|
result = check.execute()
|
||||||
|
assert len(result) == 1
|
||||||
|
assert result[0].status == "FAIL"
|
||||||
|
assert (
|
||||||
|
result[0].status_extended
|
||||||
|
== f"Workspace {workspace_id} is not in a private subnet or its VPC has not 1 public subnet and 2 private subnets with a NAT Gateway attached"
|
||||||
|
)
|
||||||
|
assert result[0].resource_id == workspace_id
|
||||||
|
assert result[0].resource_arn == ""
|
||||||
|
|
||||||
|
@mock_ec2
|
||||||
|
def test_workspaces_vpc_two_private_subnet_one_public_and_nat(self):
|
||||||
|
# EC2 Client
|
||||||
|
ec2_client = client("ec2", region_name=AWS_REGION)
|
||||||
|
vpc = ec2_client.create_vpc(
|
||||||
|
CidrBlock="172.28.7.0/24", InstanceTenancy="default"
|
||||||
|
)
|
||||||
|
# VPC Private
|
||||||
|
subnet_private = ec2_client.create_subnet(
|
||||||
|
VpcId=vpc["Vpc"]["VpcId"],
|
||||||
|
CidrBlock="172.28.7.0/26",
|
||||||
|
AvailabilityZone=f"{AWS_REGION}a",
|
||||||
|
)
|
||||||
|
route_table_private = ec2_client.create_route_table(
|
||||||
|
VpcId=vpc["Vpc"]["VpcId"],
|
||||||
|
)
|
||||||
|
ec2_client.create_route(
|
||||||
|
DestinationCidrBlock="10.10.10.0",
|
||||||
|
RouteTableId=route_table_private["RouteTable"]["RouteTableId"],
|
||||||
|
)
|
||||||
|
ec2_client.associate_route_table(
|
||||||
|
RouteTableId=route_table_private["RouteTable"]["RouteTableId"],
|
||||||
|
SubnetId=subnet_private["Subnet"]["SubnetId"],
|
||||||
|
)
|
||||||
|
# VPC Private 2
|
||||||
|
subnet_private_2 = ec2_client.create_subnet(
|
||||||
|
VpcId=vpc["Vpc"]["VpcId"],
|
||||||
|
CidrBlock="172.28.7.64/26",
|
||||||
|
AvailabilityZone=f"{AWS_REGION}a",
|
||||||
|
)
|
||||||
|
route_table_private_2 = ec2_client.create_route_table(
|
||||||
|
VpcId=vpc["Vpc"]["VpcId"],
|
||||||
|
)
|
||||||
|
ec2_client.create_route(
|
||||||
|
DestinationCidrBlock="10.10.10.0",
|
||||||
|
RouteTableId=route_table_private_2["RouteTable"]["RouteTableId"],
|
||||||
|
)
|
||||||
|
ec2_client.associate_route_table(
|
||||||
|
RouteTableId=route_table_private_2["RouteTable"]["RouteTableId"],
|
||||||
|
SubnetId=subnet_private_2["Subnet"]["SubnetId"],
|
||||||
|
)
|
||||||
|
# Nat Gateway
|
||||||
|
nat_gw = ec2_client.create_nat_gateway(
|
||||||
|
SubnetId=subnet_private_2["Subnet"]["SubnetId"],
|
||||||
|
)
|
||||||
|
ec2_client.create_route(
|
||||||
|
NatGatewayId=nat_gw["NatGateway"]["NatGatewayId"],
|
||||||
|
RouteTableId=route_table_private_2["RouteTable"]["RouteTableId"],
|
||||||
|
)
|
||||||
|
# VPC Public
|
||||||
|
subnet_public = ec2_client.create_subnet(
|
||||||
|
VpcId=vpc["Vpc"]["VpcId"],
|
||||||
|
CidrBlock="172.28.7.192/26",
|
||||||
|
AvailabilityZone=f"{AWS_REGION}a",
|
||||||
|
)
|
||||||
|
route_table_public = ec2_client.create_route_table(
|
||||||
|
VpcId=vpc["Vpc"]["VpcId"],
|
||||||
|
)
|
||||||
|
igw = ec2_client.create_internet_gateway()
|
||||||
|
ec2_client.create_route(
|
||||||
|
DestinationCidrBlock="0.0.0.0",
|
||||||
|
RouteTableId=route_table_public["RouteTable"]["RouteTableId"],
|
||||||
|
GatewayId=igw["InternetGateway"]["InternetGatewayId"],
|
||||||
|
)
|
||||||
|
ec2_client.associate_route_table(
|
||||||
|
RouteTableId=route_table_public["RouteTable"]["RouteTableId"],
|
||||||
|
SubnetId=subnet_public["Subnet"]["SubnetId"],
|
||||||
|
)
|
||||||
|
# Workspace Mock
|
||||||
|
workspaces_client = mock.MagicMock
|
||||||
|
workspaces_client.workspaces = []
|
||||||
|
workspaces_client.workspaces.append(
|
||||||
|
WorkSpace(
|
||||||
|
id=workspace_id,
|
||||||
|
region=AWS_REGION,
|
||||||
|
user_volume_encryption_enabled=True,
|
||||||
|
root_volume_encryption_enabled=True,
|
||||||
|
subnet_id=subnet_private["Subnet"]["SubnetId"],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
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.workspaces.workspaces_vpc_2private_1public_subnets_nat.workspaces_vpc_2private_1public_subnets_nat.vpc_client",
|
||||||
|
new=VPC(current_audit_info),
|
||||||
|
):
|
||||||
|
with mock.patch(
|
||||||
|
"prowler.providers.aws.services.workspaces.workspaces_vpc_2private_1public_subnets_nat.workspaces_vpc_2private_1public_subnets_nat.workspaces_client",
|
||||||
|
new=workspaces_client,
|
||||||
|
):
|
||||||
|
from prowler.providers.aws.services.workspaces.workspaces_vpc_2private_1public_subnets_nat.workspaces_vpc_2private_1public_subnets_nat import (
|
||||||
|
workspaces_vpc_2private_1public_subnets_nat,
|
||||||
|
)
|
||||||
|
|
||||||
|
check = workspaces_vpc_2private_1public_subnets_nat()
|
||||||
|
result = check.execute()
|
||||||
|
assert len(result) == 1
|
||||||
|
assert result[0].status == "PASS"
|
||||||
|
assert (
|
||||||
|
result[0].status_extended
|
||||||
|
== f"Workspace {workspace_id} is in a private subnet within a VPC which has 1 public subnet 2 private subnets with a NAT Gateway attached"
|
||||||
|
)
|
||||||
|
assert result[0].resource_id == workspace_id
|
||||||
|
assert result[0].resource_arn == ""
|
||||||
Reference in New Issue
Block a user