Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create Enum for ports #1819

Merged
merged 5 commits into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion data_safe_haven/infrastructure/common/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .enums import FirewallPriorities, NetworkingPriorities
from .enums import FirewallPriorities, NetworkingPriorities, Ports
from .ip_ranges import SREDnsIpRanges, SREIpRanges
from .transformations import (
get_available_ips_from_subnet,
Expand Down Expand Up @@ -26,6 +26,7 @@
"get_name_from_vnet",
"get_subscription_id_from_rg",
"NetworkingPriorities",
"Ports",
"SREDnsIpRanges",
"SREIpRanges",
]
49 changes: 30 additions & 19 deletions data_safe_haven/infrastructure/common/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,39 +21,50 @@ class FirewallPriorities(int, Enum):
class NetworkingPriorities(int, Enum):
"""Priorities for network security group rules."""

# Azure services: 0 - 999
AZURE_CLOUD = 100
AZURE_GATEWAY_MANAGER = 200
AZURE_LOAD_BALANCER = 300
AZURE_PLATFORM_DNS = 400
# SHM connections: 1000-1399
# Azure services: 100 - 999
AZURE_GATEWAY_MANAGER = 100
AZURE_LOAD_BALANCER = 200
AZURE_PLATFORM_DNS = 300
# SHM connections: 1000-1299
INTERNAL_SELF = 1000
INTERNAL_SHM_BASTION = 1100
INTERNAL_SHM_LDAP_TCP = 1200
INTERNAL_SHM_LDAP_UDP = 1250
INTERNAL_SHM_MONITORING_TOOLS = 1300
INTERNAL_SHM_UPDATE_SERVERS = 1400
INTERNAL_SHM_MONITORING_TOOLS = 1100
INTERNAL_SHM_UPDATE_SERVERS = 1200
# DNS connections: 1400-1499
INTERNAL_SRE_DNS_SERVERS = 1499
INTERNAL_SRE_DNS_SERVERS = 1400
# SRE connections: 1500-2999
INTERNAL_SRE_APPLICATION_GATEWAY = 1500
INTERNAL_SRE_DATA_CONFIGURATION = 1600
INTERNAL_SRE_DATA_PRIVATE = 1700
INTERNAL_SRE_GUACAMOLE_CONTAINERS = 1800
INTERNAL_SRE_GUACAMOLE_CONTAINERS_SUPPORT = 1900
INTERNAL_SRE_IDENTITY_CONTAINERS = 1950
INTERNAL_SRE_USER_SERVICES_CONTAINERS = 2000
INTERNAL_SRE_USER_SERVICES_CONTAINERS_SUPPORT = 2100
INTERNAL_SRE_USER_SERVICES_DATABASES = 2200
INTERNAL_SRE_USER_SERVICES_SOFTWARE_REPOSITORIES = 2300
INTERNAL_SRE_WORKSPACES = 2400
INTERNAL_SRE_IDENTITY_CONTAINERS = 2000
INTERNAL_SRE_USER_SERVICES_CONTAINERS = 2100
INTERNAL_SRE_USER_SERVICES_CONTAINERS_SUPPORT = 2200
INTERNAL_SRE_USER_SERVICES_DATABASES = 2300
INTERNAL_SRE_USER_SERVICES_SOFTWARE_REPOSITORIES = 2400
INTERNAL_SRE_WORKSPACES = 2500
INTERNAL_SRE_ANY = 2999
# Authorised external IPs: 3000-3499
AUTHORISED_EXTERNAL_ADMIN_IPS = 3000
AUTHORISED_EXTERNAL_USER_IPS = 3100
AUTHORISED_EXTERNAL_SSL_LABS_IPS = 3200
# Wider internet: 3500-3999
EXTERNAL_LINUX_UPDATES = 3600
EXTERNAL_INTERNET = 3999
# Deny all other: 4096
ALL_OTHER = 4096


@verify(UNIQUE)
class Ports(str, Enum):
DNS = "53"
HTTP = "80"
HTTPS = "443"
LDAP_APRICOT = "1389"
LINUX_UPDATE = "8000"
MSSQL = "1433"
NEXUS = "8081"
NTP = "123"
POSTGRESQL = "5432"
RDP = "3389"
SSH = "22"
SQUID = "3128"
3 changes: 2 additions & 1 deletion data_safe_haven/infrastructure/stacks/shm/firewall.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from data_safe_haven.infrastructure.common import (
FirewallPriorities,
Ports,
SREIpRanges,
get_id_from_subnet,
)
Expand Down Expand Up @@ -313,7 +314,7 @@ def __init__(
network.AzureFirewallNetworkRuleArgs(
description="Allow external NTP requests",
destination_addresses=ntp_ip_addresses,
destination_ports=["123"],
destination_ports=[Ports.NTP],
name="AllowExternalNTP",
protocols=[network.AzureFirewallNetworkRuleProtocol.UDP],
source_addresses=["*"],
Expand Down
157 changes: 3 additions & 154 deletions data_safe_haven/infrastructure/stacks/shm/networking.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from data_safe_haven.external import AzureIPv4Range
from data_safe_haven.functions import ordered_private_dns_zones
from data_safe_haven.infrastructure.common import NetworkingPriorities
from data_safe_haven.infrastructure.common import NetworkingPriorities, Ports


class SHMNetworkingProps:
Expand All @@ -22,8 +22,6 @@ def __init__(
) -> None:
# Virtual network and subnet IP ranges
self.vnet_iprange = AzureIPv4Range("10.0.0.0", "10.0.255.255")
# Bastion subnet must be at least /26 in size (64 addresses)
self.subnet_bastion_iprange = self.vnet_iprange.next_subnet(64)
# Firewall subnet must be at least /26 in size (64 addresses)
self.subnet_firewall_iprange = self.vnet_iprange.next_subnet(64)
# Monitoring subnet needs 2 IP addresses for automation and 13 for log analytics
Expand Down Expand Up @@ -61,137 +59,6 @@ def __init__(
)

# Define NSGs
nsg_bastion = network.NetworkSecurityGroup(
f"{self._name}_nsg_bastion",
network_security_group_name=f"{stack_name}-nsg-bastion",
resource_group_name=resource_group.name,
security_rules=[
# Inbound
network.SecurityRuleArgs(
access=network.SecurityRuleAccess.ALLOW,
description="Allow inbound https connections from admins connecting from approved IP addresses.",
destination_address_prefix="*", # required by https://learn.microsoft.com/en-us/azure/bastion/bastion-nsg
destination_port_ranges=["443"],
direction=network.SecurityRuleDirection.INBOUND,
name="AllowAdminHttpsInbound",
priority=NetworkingPriorities.AUTHORISED_EXTERNAL_ADMIN_IPS,
protocol=network.SecurityRuleProtocol.TCP,
source_address_prefixes=props.admin_ip_addresses,
source_port_range="*",
),
network.SecurityRuleArgs(
access=network.SecurityRuleAccess.ALLOW,
description="Allow inbound gateway management service traffic.",
destination_address_prefix="*", # required by https://learn.microsoft.com/en-us/azure/bastion/bastion-nsg
destination_port_ranges=["443"],
direction=network.SecurityRuleDirection.INBOUND,
name="AllowGatewayManagerServiceInbound",
priority=NetworkingPriorities.AZURE_GATEWAY_MANAGER,
protocol=network.SecurityRuleProtocol.TCP,
source_address_prefix="GatewayManager", # required by https://learn.microsoft.com/en-us/azure/bastion/bastion-nsg
source_port_range="*",
),
network.SecurityRuleArgs(
access=network.SecurityRuleAccess.ALLOW,
description="Allow inbound load balancer service traffic.",
destination_address_prefix="*", # required by https://learn.microsoft.com/en-us/azure/bastion/bastion-nsg
destination_port_ranges=["443"],
direction=network.SecurityRuleDirection.INBOUND,
name="AllowLoadBalancerServiceInbound",
priority=NetworkingPriorities.AZURE_LOAD_BALANCER,
protocol=network.SecurityRuleProtocol.TCP,
source_address_prefix="AzureLoadBalancer", # required by https://learn.microsoft.com/en-us/azure/bastion/bastion-nsg
source_port_range="*",
),
network.SecurityRuleArgs(
access=network.SecurityRuleAccess.ALLOW,
description="Allow inbound internal bastion host communication.",
destination_address_prefix="VirtualNetwork", # required by https://learn.microsoft.com/en-us/azure/bastion/bastion-nsg
destination_port_ranges=["5701", "8080"],
direction=network.SecurityRuleDirection.INBOUND,
name="AllowBastionHostInbound",
priority=NetworkingPriorities.INTERNAL_SELF,
protocol=network.SecurityRuleProtocol.ASTERISK,
source_address_prefix="VirtualNetwork", # required by https://learn.microsoft.com/en-us/azure/bastion/bastion-nsg
source_port_range="*",
),
network.SecurityRuleArgs(
access=network.SecurityRuleAccess.DENY,
description="Deny all other inbound traffic.",
destination_address_prefix="*",
destination_port_range="*",
direction=network.SecurityRuleDirection.INBOUND,
name="DenyAllOtherInbound",
priority=NetworkingPriorities.ALL_OTHER,
protocol=network.SecurityRuleProtocol.ASTERISK,
source_address_prefix="*",
source_port_range="*",
),
# Outbound
network.SecurityRuleArgs(
access=network.SecurityRuleAccess.ALLOW,
description="Allow outbound connections to DSH VMs.",
destination_address_prefix="VirtualNetwork", # required by https://learn.microsoft.com/en-us/azure/bastion/bastion-nsg
destination_port_ranges=["22", "3389"],
direction=network.SecurityRuleDirection.OUTBOUND,
name="AllowRdpOutbound",
priority=NetworkingPriorities.INTERNAL_SHM_BASTION,
protocol=network.SecurityRuleProtocol.ASTERISK,
source_address_prefix="*", # required by https://learn.microsoft.com/en-us/azure/bastion/bastion-nsg
source_port_range="*",
),
network.SecurityRuleArgs(
access=network.SecurityRuleAccess.ALLOW,
description="Allow outbound connections to Azure public endpoints.",
destination_address_prefix="AzureCloud", # required by https://learn.microsoft.com/en-us/azure/bastion/bastion-nsg
destination_port_ranges=["443"],
direction=network.SecurityRuleDirection.OUTBOUND,
name="AllowAzureCloudOutbound",
priority=NetworkingPriorities.AZURE_CLOUD,
protocol=network.SecurityRuleProtocol.TCP,
source_address_prefix="*", # required by https://learn.microsoft.com/en-us/azure/bastion/bastion-nsg
source_port_range="*",
),
network.SecurityRuleArgs(
access=network.SecurityRuleAccess.ALLOW,
description="Allow outbound internal bastion host communication.",
destination_address_prefix="VirtualNetwork", # required by https://learn.microsoft.com/en-us/azure/bastion/bastion-nsg
destination_port_ranges=["5701", "8080"],
direction=network.SecurityRuleDirection.OUTBOUND,
name="AllowBastionHostOutbound",
priority=NetworkingPriorities.INTERNAL_SELF,
protocol=network.SecurityRuleProtocol.ASTERISK,
source_address_prefix="VirtualNetwork", # required by https://learn.microsoft.com/en-us/azure/bastion/bastion-nsg
source_port_range="*",
),
network.SecurityRuleArgs(
access=network.SecurityRuleAccess.ALLOW,
description="Allow outbound connections for session and certificate validation.",
destination_address_prefix="Internet",
destination_port_ranges=["80"],
direction=network.SecurityRuleDirection.OUTBOUND,
name="AllowCertificateValidationOutbound",
priority=NetworkingPriorities.EXTERNAL_INTERNET,
protocol=network.SecurityRuleProtocol.ASTERISK,
source_address_prefix="*", # required by https://learn.microsoft.com/en-us/azure/bastion/bastion-nsg
source_port_range="*",
),
network.SecurityRuleArgs(
access=network.SecurityRuleAccess.DENY,
description="Deny all other outbound traffic.",
destination_address_prefix="*",
destination_port_range="*",
direction=network.SecurityRuleDirection.OUTBOUND,
name="DenyAllOtherOutbound",
priority=NetworkingPriorities.ALL_OTHER,
protocol=network.SecurityRuleProtocol.ASTERISK,
source_address_prefix="*",
source_port_range="*",
),
],
opts=child_opts,
tags=child_tags,
)
nsg_monitoring = network.NetworkSecurityGroup(
f"{self._name}_nsg_monitoring",
network_security_group_name=f"{stack_name}-nsg-monitoring",
Expand Down Expand Up @@ -235,7 +102,7 @@ def __init__(
access=network.SecurityRuleAccess.ALLOW,
description="Allow outbound connections to local monitoring tools.",
destination_address_prefix=str(props.subnet_monitoring_iprange),
destination_port_ranges=["443"],
destination_port_ranges=[Ports.HTTPS],
direction=network.SecurityRuleDirection.OUTBOUND,
name="AllowMonitoringToolsOutbound",
priority=NetworkingPriorities.INTERNAL_SHM_MONITORING_TOOLS,
Expand All @@ -247,7 +114,7 @@ def __init__(
access=network.SecurityRuleAccess.ALLOW,
description="Allow outbound connections to Linux update servers.",
destination_address_prefix="Internet",
destination_port_ranges=["80", "443"],
destination_port_ranges=[Ports.HTTP, Ports.HTTPS],
direction=network.SecurityRuleDirection.OUTBOUND,
name="AllowLinuxUpdatesOutbound",
priority=NetworkingPriorities.EXTERNAL_LINUX_UPDATES,
Expand Down Expand Up @@ -290,7 +157,6 @@ def __init__(

# Define the virtual network and its subnets
subnet_firewall_name = "AzureFirewallSubnet" # this name is forced by https://docs.microsoft.com/en-us/azure/firewall/tutorial-firewall-deploy-portal
subnet_bastion_name = "AzureBastionSubnet" # this name is forced by https://learn.microsoft.com/en-us/azure/bastion/configuration-settings#subnet
subnet_monitoring_name = "MonitoringSubnet"
subnet_update_servers_name = "UpdateServersSubnet"
virtual_network = network.VirtualNetwork(
Expand All @@ -300,15 +166,6 @@ def __init__(
),
resource_group_name=resource_group.name,
subnets=[ # Note that we define subnets inline to avoid creation order issues
# Bastion subnet
network.SubnetArgs(
address_prefix=str(props.subnet_bastion_iprange),
name=subnet_bastion_name,
network_security_group=network.NetworkSecurityGroupArgs(
id=nsg_bastion.id
),
route_table=None, # the bastion subnet must NOT be attached to the route table
),
# AzureFirewall subnet
network.SubnetArgs(
address_prefix=str(props.subnet_firewall_iprange),
Expand Down Expand Up @@ -427,11 +284,6 @@ def __init__(
self.private_dns_zone_base_id = private_zone_ids[0]
self.resource_group_name = Output.from_input(resource_group.name)
self.route_table = route_table
self.subnet_bastion = network.get_subnet_output(
subnet_name=subnet_bastion_name,
resource_group_name=resource_group.name,
virtual_network_name=virtual_network.name,
)
self.subnet_firewall = network.get_subnet_output(
subnet_name=subnet_firewall_name,
resource_group_name=resource_group.name,
Expand All @@ -454,9 +306,6 @@ def __init__(
"fqdn_nameservers": self.dns_zone.name_servers,
"private_dns_zone_base_id": self.private_dns_zone_base_id,
"resource_group_name": resource_group.name,
"subnet_bastion_prefix": self.subnet_bastion.apply(
lambda s: str(s.address_prefix) if s.address_prefix else ""
),
"subnet_monitoring_prefix": self.subnet_monitoring.apply(
lambda s: str(s.address_prefix) if s.address_prefix else ""
),
Expand Down
5 changes: 3 additions & 2 deletions data_safe_haven/infrastructure/stacks/sre/dns_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
)
from data_safe_haven.infrastructure.common import (
NetworkingPriorities,
Ports,
SREDnsIpRanges,
SREIpRanges,
get_ip_address_from_container_group,
Expand Down Expand Up @@ -107,7 +108,7 @@ def __init__(
access=network.SecurityRuleAccess.ALLOW,
description="Allow inbound connections from attached.",
destination_address_prefix=props.ip_range_prefix,
destination_port_ranges=["53"],
destination_port_ranges=[Ports.DNS],
direction=network.SecurityRuleDirection.INBOUND,
name="AllowSREInbound",
priority=NetworkingPriorities.INTERNAL_SRE_ANY,
Expand All @@ -132,7 +133,7 @@ def __init__(
access=network.SecurityRuleAccess.ALLOW,
description="Allow outbound DNS traffic over the internet.",
destination_address_prefix="Internet",
destination_port_ranges=["53"],
destination_port_ranges=[Ports.DNS],
direction=network.SecurityRuleDirection.OUTBOUND,
name="AllowDnsInternetOutbound",
priority=NetworkingPriorities.EXTERNAL_INTERNET,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from data_safe_haven.functions import b64encode
from data_safe_haven.infrastructure.common import (
Ports,
get_ip_address_from_container_group,
)
from data_safe_haven.infrastructure.components import (
Expand Down Expand Up @@ -188,7 +189,7 @@ def __init__(
),
containerinstance.EnvironmentVariableArgs(
name="CMD_DB_PORT",
value="5432",
value=Ports.POSTGRESQL,
),
containerinstance.EnvironmentVariableArgs(
name="CMD_DB_USERNAME",
Expand Down
Loading