Skip to content

Commit

Permalink
Merge pull request #1819 from alan-turing-institute/ports_enum
Browse files Browse the repository at this point in the history
Create Enum for ports
  • Loading branch information
jemrobinson authored Apr 19, 2024
2 parents 432c07e + c83df18 commit 6fb6aa2
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 210 deletions.
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
3 changes: 2 additions & 1 deletion data_safe_haven/infrastructure/stacks/sre/hedgedoc_server.py
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

0 comments on commit 6fb6aa2

Please sign in to comment.