diff --git a/data_safe_haven/infrastructure/common/__init__.py b/data_safe_haven/infrastructure/common/__init__.py index a8c8f4e650..ffc414932d 100644 --- a/data_safe_haven/infrastructure/common/__init__.py +++ b/data_safe_haven/infrastructure/common/__init__.py @@ -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, @@ -26,6 +26,7 @@ "get_name_from_vnet", "get_subscription_id_from_rg", "NetworkingPriorities", + "Ports", "SREDnsIpRanges", "SREIpRanges", ] diff --git a/data_safe_haven/infrastructure/common/enums.py b/data_safe_haven/infrastructure/common/enums.py index 8d0373e656..f8fcc5ea54 100644 --- a/data_safe_haven/infrastructure/common/enums.py +++ b/data_safe_haven/infrastructure/common/enums.py @@ -21,35 +21,30 @@ 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 @@ -57,3 +52,19 @@ class NetworkingPriorities(int, Enum): 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" diff --git a/data_safe_haven/infrastructure/stacks/shm/firewall.py b/data_safe_haven/infrastructure/stacks/shm/firewall.py index 55e712b55a..817711c7c3 100644 --- a/data_safe_haven/infrastructure/stacks/shm/firewall.py +++ b/data_safe_haven/infrastructure/stacks/shm/firewall.py @@ -7,6 +7,7 @@ from data_safe_haven.infrastructure.common import ( FirewallPriorities, + Ports, SREIpRanges, get_id_from_subnet, ) @@ -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=["*"], diff --git a/data_safe_haven/infrastructure/stacks/shm/networking.py b/data_safe_haven/infrastructure/stacks/shm/networking.py index b950b35b52..874ea81cda 100644 --- a/data_safe_haven/infrastructure/stacks/shm/networking.py +++ b/data_safe_haven/infrastructure/stacks/shm/networking.py @@ -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: @@ -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 @@ -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", @@ -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, @@ -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, @@ -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( @@ -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), @@ -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, @@ -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 "" ), diff --git a/data_safe_haven/infrastructure/stacks/sre/dns_server.py b/data_safe_haven/infrastructure/stacks/sre/dns_server.py index 19f5f73908..30c807c0c0 100644 --- a/data_safe_haven/infrastructure/stacks/sre/dns_server.py +++ b/data_safe_haven/infrastructure/stacks/sre/dns_server.py @@ -13,6 +13,7 @@ ) from data_safe_haven.infrastructure.common import ( NetworkingPriorities, + Ports, SREDnsIpRanges, SREIpRanges, get_ip_address_from_container_group, @@ -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, @@ -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, diff --git a/data_safe_haven/infrastructure/stacks/sre/hedgedoc_server.py b/data_safe_haven/infrastructure/stacks/sre/hedgedoc_server.py index 5fa8cb239f..e9171466af 100644 --- a/data_safe_haven/infrastructure/stacks/sre/hedgedoc_server.py +++ b/data_safe_haven/infrastructure/stacks/sre/hedgedoc_server.py @@ -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 ( @@ -188,7 +189,7 @@ def __init__( ), containerinstance.EnvironmentVariableArgs( name="CMD_DB_PORT", - value="5432", + value=Ports.POSTGRESQL, ), containerinstance.EnvironmentVariableArgs( name="CMD_DB_USERNAME", diff --git a/data_safe_haven/infrastructure/stacks/sre/networking.py b/data_safe_haven/infrastructure/stacks/sre/networking.py index 49ac113875..661f39ac46 100644 --- a/data_safe_haven/infrastructure/stacks/sre/networking.py +++ b/data_safe_haven/infrastructure/stacks/sre/networking.py @@ -8,6 +8,7 @@ from data_safe_haven.functions import alphanumeric, ordered_private_dns_zones from data_safe_haven.infrastructure.common import ( NetworkingPriorities, + Ports, SREDnsIpRanges, SREIpRanges, get_id_from_vnet, @@ -206,7 +207,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow inbound connections from users over the internet.", destination_address_prefix=subnet_application_gateway_prefix, - destination_port_ranges=["80", "443"], + destination_port_ranges=[Ports.HTTP, Ports.HTTPS], direction=network.SecurityRuleDirection.INBOUND, name="AllowUsersInternetInbound", priority=NetworkingPriorities.AUTHORISED_EXTERNAL_USER_IPS, @@ -218,7 +219,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow inbound connections from from ssllabs.com for SSL quality reporting.", destination_address_prefix=subnet_application_gateway_prefix, - destination_port_ranges=["443"], + destination_port_ranges=[Ports.HTTPS], direction=network.SecurityRuleDirection.INBOUND, name="AllowSslLabsInternetInbound", priority=NetworkingPriorities.AUTHORISED_EXTERNAL_SSL_LABS_IPS, @@ -243,7 +244,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow outbound connections to DNS servers.", destination_address_prefix=dns_servers_prefix, - destination_port_ranges=["53"], + destination_port_ranges=[Ports.DNS], direction=network.SecurityRuleDirection.OUTBOUND, name="AllowDNSServersOutbound", priority=NetworkingPriorities.INTERNAL_SRE_DNS_SERVERS, @@ -255,7 +256,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow outbound connections to the Guacamole remote desktop gateway.", destination_address_prefix=subnet_guacamole_containers_prefix, - destination_port_ranges=["80"], + destination_port_ranges=[Ports.HTTP], direction=network.SecurityRuleDirection.OUTBOUND, name="AllowGuacamoleContainersOutbound", priority=NetworkingPriorities.INTERNAL_SRE_GUACAMOLE_CONTAINERS, @@ -433,7 +434,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow inbound connections from the Application Gateway.", destination_address_prefix=subnet_guacamole_containers_prefix, - destination_port_ranges=["80"], + destination_port_ranges=[Ports.HTTP], direction=network.SecurityRuleDirection.INBOUND, name="AllowApplicationGatewayInbound", priority=NetworkingPriorities.INTERNAL_SRE_APPLICATION_GATEWAY, @@ -470,7 +471,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow outbound connections to DNS servers.", destination_address_prefix=dns_servers_prefix, - destination_port_ranges=["53"], + destination_port_ranges=[Ports.DNS], direction=network.SecurityRuleDirection.OUTBOUND, name="AllowDNSServersOutbound", priority=NetworkingPriorities.INTERNAL_SRE_DNS_SERVERS, @@ -494,7 +495,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow outbound connections to Guacamole support services.", destination_address_prefix=subnet_guacamole_containers_support_prefix, - destination_port_ranges=["5432"], + destination_port_ranges=[Ports.POSTGRESQL], direction=network.SecurityRuleDirection.OUTBOUND, name="AllowGuacamoleContainersSupportOutbound", priority=NetworkingPriorities.INTERNAL_SRE_GUACAMOLE_CONTAINERS_SUPPORT, @@ -506,7 +507,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow LDAP client requests over TCP.", destination_address_prefix=subnet_identity_containers_prefix, - destination_port_ranges=["1389"], + destination_port_ranges=[Ports.LDAP_APRICOT], direction=network.SecurityRuleDirection.OUTBOUND, name="AllowIdentityServersOutbound", priority=NetworkingPriorities.INTERNAL_SRE_IDENTITY_CONTAINERS, @@ -518,7 +519,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow outbound connections to SRE workspaces.", destination_address_prefix=subnet_workspaces_prefix, - destination_port_ranges=["22", "3389"], + destination_port_ranges=[Ports.SSH, Ports.RDP], direction=network.SecurityRuleDirection.OUTBOUND, name="AllowWorkspacesOutbound", priority=NetworkingPriorities.INTERNAL_SRE_WORKSPACES, @@ -530,7 +531,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow outbound OAuth connections over the internet.", destination_address_prefix="Internet", - destination_port_ranges=["80", "443"], + destination_port_ranges=[Ports.HTTP, Ports.HTTPS], direction=network.SecurityRuleDirection.OUTBOUND, name="AllowOAuthInternetOutbound", priority=NetworkingPriorities.EXTERNAL_INTERNET, @@ -623,7 +624,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow LDAP client requests from Guacamole over TCP.", destination_address_prefix=subnet_identity_containers_prefix, - destination_port_ranges=["1389"], + destination_port_ranges=[Ports.LDAP_APRICOT], direction=network.SecurityRuleDirection.INBOUND, name="AllowGuacamoleLDAPClientTCPInbound", priority=NetworkingPriorities.INTERNAL_SRE_GUACAMOLE_CONTAINERS, @@ -635,7 +636,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow LDAP client requests from user services over TCP.", destination_address_prefix=subnet_identity_containers_prefix, - destination_port_ranges=["1389"], + destination_port_ranges=[Ports.LDAP_APRICOT], direction=network.SecurityRuleDirection.INBOUND, name="AllowUserServicesLDAPClientTCPInbound", priority=NetworkingPriorities.INTERNAL_SRE_USER_SERVICES_CONTAINERS, @@ -647,7 +648,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow LDAP client requests from workspaces over TCP.", destination_address_prefix=subnet_identity_containers_prefix, - destination_port_ranges=["1389"], + destination_port_ranges=[Ports.LDAP_APRICOT], direction=network.SecurityRuleDirection.INBOUND, name="AllowWorkspaceLDAPClientTCPInbound", priority=NetworkingPriorities.INTERNAL_SRE_WORKSPACES, @@ -670,7 +671,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow inbound connections from SRE workspaces.", destination_address_prefix=subnet_user_services_containers_prefix, - destination_port_ranges=["22", "80", "443"], + destination_port_ranges=[Ports.SSH, Ports.HTTP, Ports.HTTPS], direction=network.SecurityRuleDirection.INBOUND, name="AllowWorkspacesInbound", priority=NetworkingPriorities.INTERNAL_SRE_WORKSPACES, @@ -707,7 +708,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow outbound connections to DNS servers.", destination_address_prefix=dns_servers_prefix, - destination_port_ranges=["53"], + destination_port_ranges=[Ports.DNS], direction=network.SecurityRuleDirection.OUTBOUND, name="AllowDNSServersOutbound", priority=NetworkingPriorities.INTERNAL_SRE_DNS_SERVERS, @@ -731,7 +732,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow LDAP client requests over TCP.", destination_address_prefix=subnet_identity_containers_prefix, - destination_port_ranges=["1389"], + destination_port_ranges=[Ports.LDAP_APRICOT], direction=network.SecurityRuleDirection.OUTBOUND, name="AllowIdentityServersOutbound", priority=NetworkingPriorities.INTERNAL_SRE_IDENTITY_CONTAINERS, @@ -743,7 +744,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow outbound connections to container support services.", destination_address_prefix=subnet_user_services_containers_support_prefix, - destination_port_ranges=["5432"], + destination_port_ranges=[Ports.POSTGRESQL], direction=network.SecurityRuleDirection.OUTBOUND, name="AllowUserServicesContainersSupportOutbound", priority=NetworkingPriorities.INTERNAL_SRE_USER_SERVICES_CONTAINERS_SUPPORT, @@ -777,7 +778,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow inbound connections from user services containers.", destination_address_prefix=subnet_user_services_containers_support_prefix, - destination_port_ranges=["5432"], + destination_port_ranges=[Ports.POSTGRESQL], direction=network.SecurityRuleDirection.INBOUND, name="AllowUserServicesContainersInbound", priority=NetworkingPriorities.INTERNAL_SRE_USER_SERVICES_CONTAINERS, @@ -836,7 +837,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow inbound connections from SRE workspaces.", destination_address_prefix=subnet_user_services_databases_prefix, - destination_port_ranges=["1433", "5432"], + destination_port_ranges=[Ports.MSSQL, Ports.POSTGRESQL], direction=network.SecurityRuleDirection.INBOUND, name="AllowWorkspacesInbound", priority=NetworkingPriorities.INTERNAL_SRE_WORKSPACES, @@ -873,7 +874,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow outbound connections to DNS servers.", destination_address_prefix=dns_servers_prefix, - destination_port_ranges=["53"], + destination_port_ranges=[Ports.DNS], direction=network.SecurityRuleDirection.OUTBOUND, name="AllowDNSServersOutbound", priority=NetworkingPriorities.INTERNAL_SRE_DNS_SERVERS, @@ -919,7 +920,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow inbound connections from SRE workspaces.", destination_address_prefix=subnet_user_services_software_repositories_prefix, - destination_port_ranges=["80", "443", "3128"], + destination_port_ranges=[Ports.HTTP, Ports.HTTPS, Ports.SQUID], direction=network.SecurityRuleDirection.INBOUND, name="AllowWorkspacesInbound", priority=NetworkingPriorities.INTERNAL_SRE_WORKSPACES, @@ -956,7 +957,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow outbound connections to DNS servers.", destination_address_prefix=dns_servers_prefix, - destination_port_ranges=["53"], + destination_port_ranges=[Ports.DNS], direction=network.SecurityRuleDirection.OUTBOUND, name="AllowDNSServersOutbound", priority=NetworkingPriorities.INTERNAL_SRE_DNS_SERVERS, @@ -980,7 +981,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow outbound connections to external repositories over the internet.", destination_address_prefix="Internet", - destination_port_ranges=["80", "443"], + destination_port_ranges=[Ports.HTTP, Ports.HTTPS], direction=network.SecurityRuleDirection.OUTBOUND, name="AllowPackagesInternetOutbound", priority=NetworkingPriorities.EXTERNAL_INTERNET, @@ -1014,7 +1015,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow inbound connections from Guacamole remote desktop gateway.", destination_address_prefix=subnet_workspaces_prefix, - destination_port_ranges=["22", "3389"], + destination_port_ranges=[Ports.SSH, Ports.RDP], direction=network.SecurityRuleDirection.INBOUND, name="AllowGuacamoleContainersInbound", priority=NetworkingPriorities.INTERNAL_SRE_GUACAMOLE_CONTAINERS, @@ -1051,7 +1052,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow LDAP client requests over TCP.", destination_address_prefix=subnet_identity_containers_prefix, - destination_port_ranges=["1389"], + destination_port_ranges=[Ports.LDAP_APRICOT], direction=network.SecurityRuleDirection.OUTBOUND, name="AllowIdentityServersOutbound", priority=NetworkingPriorities.INTERNAL_SRE_IDENTITY_CONTAINERS, @@ -1063,7 +1064,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow outbound connections to SHM monitoring tools.", destination_address_prefix=str(props.shm_subnet_monitoring_prefix), - destination_port_ranges=["443"], + destination_port_ranges=[Ports.HTTPS], direction=network.SecurityRuleDirection.OUTBOUND, name="AllowMonitoringToolsOutbound", priority=NetworkingPriorities.INTERNAL_SHM_MONITORING_TOOLS, @@ -1075,7 +1076,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow outbound connections to Linux update servers.", destination_address_prefix=props.shm_subnet_update_servers_prefix, - destination_port_ranges=["8000"], + destination_port_ranges=[Ports.LINUX_UPDATE], direction=network.SecurityRuleDirection.OUTBOUND, name="AllowLinuxUpdatesOutbound", priority=NetworkingPriorities.INTERNAL_SHM_UPDATE_SERVERS, @@ -1087,7 +1088,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow outbound connections to DNS servers.", destination_address_prefix=dns_servers_prefix, - destination_port_ranges=["53"], + destination_port_ranges=[Ports.DNS], direction=network.SecurityRuleDirection.OUTBOUND, name="AllowDNSServersOutbound", priority=NetworkingPriorities.INTERNAL_SRE_DNS_SERVERS, @@ -1111,7 +1112,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow outbound connections to user services containers.", destination_address_prefix=subnet_user_services_containers_prefix, - destination_port_ranges=["22", "80", "443"], + destination_port_ranges=[Ports.SSH, Ports.HTTP, Ports.HTTPS], direction=network.SecurityRuleDirection.OUTBOUND, name="AllowUserServicesContainersOutbound", priority=NetworkingPriorities.INTERNAL_SRE_USER_SERVICES_CONTAINERS, @@ -1123,7 +1124,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow outbound connections to user services databases.", destination_address_prefix=subnet_user_services_databases_prefix, - destination_port_ranges=["1433", "5432"], + destination_port_ranges=[Ports.MSSQL, Ports.POSTGRESQL], direction=network.SecurityRuleDirection.OUTBOUND, name="AllowUserServicesDatabasesOutbound", priority=NetworkingPriorities.INTERNAL_SRE_USER_SERVICES_DATABASES, @@ -1135,7 +1136,7 @@ def __init__( access=network.SecurityRuleAccess.ALLOW, description="Allow outbound connections to user services software repositories.", destination_address_prefix=subnet_user_services_software_repositories_prefix, - destination_port_ranges=["80", "443", "3128"], + destination_port_ranges=[Ports.HTTP, Ports.HTTPS, Ports.SQUID], direction=network.SecurityRuleDirection.OUTBOUND, name="AllowUserServicesSoftwareRepositoriesOutbound", priority=NetworkingPriorities.INTERNAL_SRE_USER_SERVICES_SOFTWARE_REPOSITORIES, diff --git a/data_safe_haven/infrastructure/stacks/sre/software_repositories.py b/data_safe_haven/infrastructure/stacks/sre/software_repositories.py index 28e8a57b0a..2ded94a275 100644 --- a/data_safe_haven/infrastructure/stacks/sre/software_repositories.py +++ b/data_safe_haven/infrastructure/stacks/sre/software_repositories.py @@ -6,6 +6,7 @@ from pulumi_azure_native import containerinstance, storage from data_safe_haven.infrastructure.common import ( + Ports, get_ip_address_from_container_group, ) from data_safe_haven.infrastructure.components import ( @@ -219,7 +220,7 @@ def __init__( ), containerinstance.EnvironmentVariableArgs( name="NEXUS_PORT", - value="8081", + value=Ports.NEXUS, ), # Use fallback updating method due to issue with changes to # files on Azure storage mount not being recognised by entr