Skip to content

Commit 3d8c4ff

Browse files
Merge pull request #145 from Barts-Life-Science/dns-whitelist
Prevent data exfiltration by DNS tunneling or malicious DNS lookups
2 parents cd1bb57 + 8d56e54 commit 3d8c4ff

File tree

20 files changed

+236
-13
lines changed

20 files changed

+236
-13
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#
2+
# Add the domains to be whitelisted here.
3+
# Use an octothorpe to comment lines out.
4+
#
5+
# api.snapcraft.io
6+
# archive.ubuntu.com
7+
# azure.archive.ubuntu.com
8+
# cloud.r-project.org
9+
# azure.com
10+
# conda.anaconda.org
11+
# cran.r-project.org
12+
# docker.com
13+
# docker.io
14+
# download-ib01.fedoraproject.org
15+
# download.microsoft.com
16+
# download1.rstudio.org
17+
# files.pythonhosted.org
18+
# keyserver.ubuntu.com
19+
# microsoft.com
20+
# nhs.net
21+
# nhs.org
22+
# nhs.uk
23+
# packages.microsoft.com
24+
# pypi.org
25+
# repo.almalinux.org
26+
# repo.anaconda.com
27+
# security.ubuntu.com
28+
# snapcraftcontent.com

core/terraform/dns-resolver/locals.tf

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
locals {
2+
# This is not DRY! See the network module.
3+
core_services_vnet_subnets = cidrsubnets(var.core_address_space, 4, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4)
4+
dns_resolver_subnet_address_prefix = local.core_services_vnet_subnets[11] # .128 - .191
5+
6+
tre_core_tags = {
7+
tre_id = var.tre_id
8+
tre_core_service_id = var.tre_id
9+
}
10+
}

core/terraform/dns-resolver/main.tf

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
terraform {
2+
# In modules we should only specify the min version
3+
required_providers {
4+
azurerm = {
5+
source = "hashicorp/azurerm"
6+
version = ">= 3.8"
7+
}
8+
}
9+
}
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/bin/bash
2+
#
3+
# Generate a JSON object with the DNS rules for the private resolver
4+
#
5+
6+
cd $(dirname $(realpath $0))
7+
8+
resolver="8.8.8.8" # Google, is there a better choice?
9+
i=0
10+
11+
echo "{"
12+
for domain in $(cat dns-whitelist.txt | sed -e 's%#.*$%%')
13+
do
14+
echo " \"rule_${i}\": \"{ \\\"address\\\": \\\"${resolver}\\\", \\\"domain\\\": \\\"${domain}.\\\" }\","
15+
i=$(( i + 1 ))
16+
done
17+
18+
echo " \"sink\": \"{ \\\"address\\\": \\\"0.0.0.0\\\", \\\"domain\\\": \\\".\\\" }\""
19+
echo "}"
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# resource "azurerm_subnet" "dns-snet-inbound" {
2+
# name = "dns-snet-inbound"
3+
# resource_group_name = local.rg_name
4+
# virtual_network_name = azurerm_virtual_network.dns-vnet.name
5+
# address_prefixes = [ local.core_services_vnet_subnets[11] ]
6+
# delegation {
7+
# name = "Microsoft.Network.dnsResolvers"
8+
# service_delegation {
9+
# actions = ["Microsoft.Network/virtualNetworks/subnets/join/action"]
10+
# name = "Microsoft.Network/dnsResolvers"
11+
# }
12+
# }
13+
# }
14+
15+
resource "azurerm_subnet" "dns-snet-outbound" {
16+
name = "AzurePrivateDnsResolverSubnet"
17+
resource_group_name = var.resource_group_name
18+
virtual_network_name = var.core_vnet_name
19+
address_prefixes = [local.dns_resolver_subnet_address_prefix]
20+
delegation {
21+
name = "Microsoft.Network.dnsResolvers"
22+
service_delegation {
23+
actions = ["Microsoft.Network/virtualNetworks/subnets/join/action"]
24+
name = "Microsoft.Network/dnsResolvers"
25+
}
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
resource "azurerm_private_dns_resolver" "dns-resolver" {
2+
name = "dns-resolver"
3+
resource_group_name = var.resource_group_name
4+
location = var.location
5+
virtual_network_id = var.core_vnet_id
6+
}
7+
8+
resource "azurerm_private_dns_resolver_outbound_endpoint" "dns-resolver-outbound" {
9+
name = "dns-resolver-outbound-endpoint"
10+
private_dns_resolver_id = azurerm_private_dns_resolver.dns-resolver.id
11+
location = azurerm_private_dns_resolver.dns-resolver.location
12+
subnet_id = azurerm_subnet.dns-snet-outbound.id
13+
}
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# terraform {
2+
# required_version = ">= 1.0.0"
3+
# required_providers {
4+
# azurerm = {
5+
# source = "hashicorp/azurerm"
6+
# version = ">=3.0.0"
7+
# }
8+
# }
9+
# }
10+
11+
# provider "azurerm" {
12+
# features {}
13+
# }
14+

core/terraform/dns-resolver/rules.tf

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
data "external" "dns-rules" {
2+
program = ["bash", "${path.module}/make-rules.sh"]
3+
}
4+
5+
resource "azurerm_private_dns_resolver_forwarding_rule" "dns-rules" {
6+
# This is how to do it in-situ, in which case you don't need the 'jsondecode' wrappers below
7+
# for_each = tomap( {
8+
# net = { domain = "net.", address = "8.8.8.8" },
9+
# sink = { domain = ".", address = "0.0.0.0" }
10+
# } )
11+
for_each = data.external.dns-rules.result
12+
name = "dns-rule-${each.key}"
13+
dns_forwarding_ruleset_id = azurerm_private_dns_resolver_dns_forwarding_ruleset.dns-ruleset.id
14+
domain_name = jsondecode(each.value).domain
15+
enabled = true
16+
target_dns_servers {
17+
ip_address = jsondecode(each.value).address
18+
port = 53
19+
}
20+
}
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
resource "azurerm_private_dns_resolver_dns_forwarding_ruleset" "dns-ruleset" {
2+
name = "dns-ruleset"
3+
resource_group_name = var.resource_group_name
4+
location = var.location
5+
private_dns_resolver_outbound_endpoint_ids = [azurerm_private_dns_resolver_outbound_endpoint.dns-resolver-outbound.id]
6+
}
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
variable "tre_id" {
2+
type = string
3+
}
4+
variable "location" {
5+
type = string
6+
}
7+
variable "resource_group_name" {
8+
type = string
9+
}
10+
variable "core_address_space" {
11+
type = string
12+
}
13+
variable "arm_environment" {
14+
type = string
15+
}
16+
variable "core_vnet_name" {
17+
type = string
18+
}
19+
variable "core_vnet_id" {
20+
type = string
21+
}

core/terraform/main.tf

+11
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,17 @@ module "network" {
8888
arm_environment = var.arm_environment
8989
}
9090

91+
module "dns-resolver" {
92+
source = "./dns-resolver"
93+
tre_id = var.tre_id
94+
location = var.location
95+
resource_group_name = azurerm_resource_group.core.name
96+
core_address_space = var.core_address_space
97+
arm_environment = var.arm_environment
98+
core_vnet_name = module.network.core_vnet_name
99+
core_vnet_id = module.network.core_vnet_id
100+
}
101+
91102
module "appgateway" {
92103
source = "./appgateway"
93104
tre_id = var.tre_id

core/terraform/network/locals.tf

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ locals {
1919
# .3
2020
resource_processor_subnet_address_prefix = local.core_services_vnet_subnets[9] # .0 - .63
2121
firewall_management_subnet_address_prefix = local.core_services_vnet_subnets[10] # .64 - .127
22-
# FREE = local.core_services_vnet_subnets[11] # .128 - .191
22+
# see the dns-resolver module = local.core_services_vnet_subnets[11] # .128 - .191
2323
# FREE = local.core_services_vnet_subnets[12] # .192 - .254
2424

2525
tre_core_tags = {

core/terraform/network/outputs.tf

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ output "core_vnet_id" {
22
value = azurerm_virtual_network.core.id
33
}
44

5+
output "core_vnet_name" {
6+
value = azurerm_virtual_network.core.name
7+
}
8+
59
output "bastion_subnet_id" {
610
value = azurerm_subnet.bastion.id
711
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# syntax=docker/dockerfile-upstream:1.4.0
2+
FROM --platform=linux/amd64 debian:bullseye-slim
3+
4+
# PORTER_INIT
5+
6+
RUN rm -f /etc/apt/apt.conf.d/docker-clean; echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache
7+
8+
# Git is required for terraform_azurerm_environment_configuration
9+
RUN --mount=type=cache,target=/var/cache/apt --mount=type=cache,target=/var/lib/apt \
10+
apt-get update && apt-get install -y git --no-install-recommends
11+
12+
# PORTER_MIXINS
13+
14+
# Use the BUNDLE_DIR build argument to copy files into the bundle
15+
COPY --link . ${BUNDLE_DIR}/

templates/workspace_services/guacamole/user_resources/guacamole-azure-linuxvm/terraform/vm_config.sh

+2-11
Original file line numberDiff line numberDiff line change
@@ -125,16 +125,6 @@ if [ "${SHARED_STORAGE_ACCESS}" -eq 1 ]; then
125125
# Change permissions on the credential file so only root can read or modify the password file.
126126
sudo chmod 600 "$smbCredentialFile"
127127

128-
# # Configure autofs
129-
# echo "$fileShareName -fstype=cifs,rw,dir_mode=0777,credentials=$smbCredentialFile :$smbPath" | sudo tee /etc/auto.fileshares > /dev/null
130-
# echo "$mntRoot /etc/auto.fileshares --timeout=60" | sudo tee /etc/auto.master > /dev/null
131-
132-
# # Restart service to register changes
133-
# sudo systemctl restart autofs
134-
135-
# # Autofs mounts when accessed for 60 seconds. Folder created for constant visible mount
136-
# sudo ln -s "$mntPath" "/$fileShareName"
137-
# sudo mkdir -p $mntRoot
138128
echo "$smbPath $mntRoot cifs rw,vers=default,dir_mode=0777,file_mode=0777,uid=1000,gid=1000,credentials=$smbCredentialFile 0 0" | sudo tee -a /etc/fstab >/dev/null
139129
sudo mount $mntRoot
140130
fi
@@ -172,9 +162,9 @@ sudo update-alternatives --config x-www-browser
172162

173163
# Prevent screen timeout
174164
echo "init_vm.sh: Preventing Timeout"
165+
sudo mkdir -p /home/"${VM_USER}"/.config/xfce4/xfconf/xfce-perchannel-xml
175166
sudo touch /home/"${VM_USER}"/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-screensaver.xml
176167
sudo chmod 664 /home/"${VM_USER}"/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-screensaver.xml
177-
sudo chown "${VM_USER}":"${VM_USER}" /home/"${VM_USER}"/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-screensaver.xml
178168
sudo tee /home/"${VM_USER}"/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-screensaver.xml << END
179169
<?xml version="1.0" encoding="UTF-8"?>
180170
<channel name="xfce4-screensaver" version="1.0">
@@ -187,6 +177,7 @@ sudo tee /home/"${VM_USER}"/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-scree
187177
</property>
188178
</ channel>
189179
END
180+
sudo chown -Rf "${VM_USER}":"${VM_USER}" /home/"${VM_USER}"/.config
190181

191182
## Cleanup
192183
echo "init_vm.sh: Cleanup"

templates/workspaces/base-adf/terraform/network/data.tf

+5
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ data "azurerm_private_dns_zone" "postgres" {
9393
resource_group_name = local.core_resource_group_name
9494
}
9595

96+
data "azurerm_private_dns_zone" "azuresql" {
97+
name = module.terraform_azurerm_environment_configuration.private_links["privatelink.database.windows.net"]
98+
resource_group_name = local.core_resource_group_name
99+
}
100+
96101
data "azurerm_public_ip" "app_gateway_ip" {
97102
name = "pip-agw-${var.tre_id}"
98103
resource_group_name = local.core_resource_group_name
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
data "azurerm_private_dns_resolver_dns_forwarding_ruleset" "core-dns-ruleset" {
2+
name = "dns-ruleset"
3+
resource_group_name = local.core_resource_group_name
4+
}
5+
6+
resource "azurerm_private_dns_resolver_virtual_network_link" "dns-ws-link" {
7+
name = "dns-ws-link-${local.workspace_resource_name_suffix}"
8+
dns_forwarding_ruleset_id = data.azurerm_private_dns_resolver_dns_forwarding_ruleset.core-dns-ruleset.id
9+
virtual_network_id = azurerm_virtual_network.ws.id
10+
}

templates/workspaces/base-adf/terraform/network/network.tf

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,6 @@ resource "azurerm_subnet_route_table_association" "rt_webapps_subnet_association
105105
}
106106

107107
module "terraform_azurerm_environment_configuration" {
108-
source = "git::https://github.com/microsoft/terraform-azurerm-environment-configuration.git?ref=0.2.0"
108+
source = "git::https://github.com/microsoft/terraform-azurerm-environment-configuration.git?ref=0.5.0"
109109
arm_environment = var.arm_environment
110110
}

templates/workspaces/base-adf/terraform/network/zone_links.tf

+10
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,16 @@ resource "azurerm_private_dns_zone_virtual_network_link" "postgreslink" {
129129
lifecycle { ignore_changes = [tags] }
130130
}
131131

132+
resource "azurerm_private_dns_zone_virtual_network_link" "azuresqllink" {
133+
name = "azuresqllink-${local.workspace_resource_name_suffix}"
134+
resource_group_name = local.core_resource_group_name
135+
private_dns_zone_name = data.azurerm_private_dns_zone.azuresql.name
136+
virtual_network_id = azurerm_virtual_network.ws.id
137+
tags = var.tre_workspace_tags
138+
139+
lifecycle { ignore_changes = [tags] }
140+
}
141+
132142
resource "azurerm_private_dns_zone_virtual_network_link" "nexuslink" {
133143
name = "nexuslink-${local.workspace_resource_name_suffix}"
134144
resource_group_name = local.core_resource_group_name
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
data "azurerm_private_dns_resolver_dns_forwarding_ruleset" "core-dns-ruleset" {
2+
name = "dns-ruleset"
3+
resource_group_name = local.core_resource_group_name
4+
}
5+
6+
resource "azurerm_private_dns_resolver_virtual_network_link" "dns-ws-link" {
7+
name = "dns-ws-link-${local.workspace_resource_name_suffix}"
8+
dns_forwarding_ruleset_id = data.azurerm_private_dns_resolver_dns_forwarding_ruleset.core-dns-ruleset.id
9+
virtual_network_id = azurerm_virtual_network.ws.id
10+
}

0 commit comments

Comments
 (0)