diff --git a/main.tf b/main.tf index 0b991382..78efc99a 100644 --- a/main.tf +++ b/main.tf @@ -20,9 +20,9 @@ locals { }, var.tags) } -# ------------------------------------------------------------ +# COMMON NETWORKING ------------------------------------------- -# TODO: To be moved in another module +# TODO: To be moved in another module ? resource "azurerm_resource_group" "graphdb" { name = var.resource_name_prefix @@ -60,6 +60,57 @@ resource "azurerm_subnet" "graphdb-vmss" { address_prefixes = var.graphdb_subnet_address_prefix } +resource "azurerm_network_security_group" "graphdb-gateway" { + name = "${var.resource_name_prefix}-gateway" + resource_group_name = azurerm_resource_group.graphdb.name + location = var.location + + security_rule { + name = "AllowGatewayManager" + description = "Allows Gateway Manager to perform health monitoring." + priority = 100 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_address_prefix = "GatewayManager" + source_port_range = "*" + destination_address_prefix = "*" + destination_port_range = "65200-65535" + } + + security_rule { + name = "AllowInternetInbound" + description = "Allows inbound internet traffic to the gateway subnet." + priority = 1000 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_address_prefix = "Internet" + source_port_range = "*" + destination_address_prefixes = var.app_gateway_subnet_address_prefix + destination_port_ranges = [80, 443] + } + + tags = var.tags +} + +resource "azurerm_network_security_group" "graphdb-vmss" { + name = "${var.resource_name_prefix}-vmss" + resource_group_name = azurerm_resource_group.graphdb.name + location = var.location + tags = var.tags +} + +resource "azurerm_subnet_network_security_group_association" "graphdb-gateway" { + network_security_group_id = azurerm_network_security_group.graphdb-gateway.id + subnet_id = azurerm_subnet.graphdb-gateway.id +} + +resource "azurerm_subnet_network_security_group_association" "graphdb-vmss" { + network_security_group_id = azurerm_network_security_group.graphdb-vmss.id + subnet_id = azurerm_subnet.graphdb-vmss.id +} + # ------------------------------------------------------------ # Creates a public IP address with assigned FQDN from the regional Azure DNS @@ -166,11 +217,13 @@ module "bastion" { source = "./modules/bastion" - resource_group_name = azurerm_resource_group.graphdb.name - location = var.location + resource_name_prefix = var.resource_name_prefix + location = var.location + resource_group_name = azurerm_resource_group.graphdb.name + virtual_network_name = azurerm_virtual_network.graphdb.name - resource_name_prefix = var.resource_name_prefix bastion_subnet_address_prefix = var.bastion_subnet_address_prefix + bastion_allowed_cidr_blocks = var.management_cidr_blocks tags = local.tags } @@ -199,8 +252,7 @@ module "vm" { resource_group_id = azurerm_resource_group.graphdb.id zones = var.zones - graphdb_subnet_id = azurerm_subnet.graphdb-vmss.id - graphdb_subnet_cidr = one(azurerm_subnet.graphdb-vmss.address_prefixes) + graphdb_subnet_id = azurerm_subnet.graphdb-vmss.id identity_id = module.identity.identity_id identity_principal_id = module.identity.identity_principal_id @@ -214,11 +266,10 @@ module "vm" { disk_mbps_read_write = var.disk_mbps_read_write disk_size_gb = var.disk_size_gb - instance_type = var.instance_type - image_id = module.graphdb_image.image_id - node_count = var.node_count - ssh_key = var.ssh_key - source_ssh_blocks = var.source_ssh_blocks + instance_type = var.instance_type + image_id = module.graphdb_image.image_id + node_count = var.node_count + ssh_key = var.ssh_key custom_user_data = var.custom_graphdb_vm_user_data diff --git a/modules/bastion/main.tf b/modules/bastion/main.tf index bb973ef3..7c2e5df6 100644 --- a/modules/bastion/main.tf +++ b/modules/bastion/main.tf @@ -1,11 +1,84 @@ -resource "azurerm_subnet" "graphdb-bastion-subnet" { +resource "azurerm_subnet" "graphdb-bastion" { name = "AzureBastionSubnet" resource_group_name = var.resource_group_name virtual_network_name = var.virtual_network_name address_prefixes = var.bastion_subnet_address_prefix } -resource "azurerm_public_ip" "graphdb-bastion-public-ip" { +resource "azurerm_network_security_group" "graphdb-bastion" { + name = "${var.resource_name_prefix}-bastion" + resource_group_name = var.resource_group_name + location = var.location + + # The following rules are required by Azure Bastion in order to function properly + # See https://learn.microsoft.com/en-us/azure/bastion/bastion-nsg + # See https://learn.microsoft.com/en-gb/azure/bastion/native-client#secure + + # INBOUND + + security_rule { + name = "AllowHTTPSInternetInbound" + description = "Allows specified CIDRs to access the Bastion subnet" + priority = 100 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_address_prefixes = var.bastion_allowed_cidr_blocks + source_port_range = "*" + destination_address_prefix = "*" + destination_port_range = 443 + } + + security_rule { + name = "AllowGatewayManagerInbound" + description = "Allows Gateway Manager to perform system operations" + priority = 110 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_address_prefix = "GatewayManager" + source_port_range = "*" + destination_address_prefix = "*" + destination_port_range = 443 + } + + # OUTBOUND + + security_rule { + name = "AllowSSHOutbound" + description = "Allows outbound SSH/RDP connections" + priority = 100 + direction = "Outbound" + access = "Allow" + protocol = "*" + source_address_prefix = "*" + source_port_range = "*" + destination_address_prefix = "VirtualNetwork" + destination_port_ranges = [22, 3389] + } + + security_rule { + name = "AllowAzureCloudOutbound" + description = "Allows outbound connections to Azure Cloud services" + priority = 110 + direction = "Outbound" + access = "Allow" + protocol = "Tcp" + source_address_prefix = "*" + source_port_range = "*" + destination_address_prefix = "AzureCloud" + destination_port_range = 443 + } + + tags = var.tags +} + +resource "azurerm_subnet_network_security_group_association" "graphdb-bastion" { + network_security_group_id = azurerm_network_security_group.graphdb-bastion.id + subnet_id = azurerm_subnet.graphdb-bastion.id +} + +resource "azurerm_public_ip" "graphdb-bastion" { name = "${var.resource_name_prefix}_bastion_publicIP" location = var.location resource_group_name = var.resource_group_name @@ -14,15 +87,19 @@ resource "azurerm_public_ip" "graphdb-bastion-public-ip" { tags = var.tags } -resource "azurerm_bastion_host" "graphdb-bastion-host" { +resource "azurerm_bastion_host" "graphdb" { name = "${var.resource_name_prefix}_bastion" location = var.location resource_group_name = var.resource_group_name + # Enables additional features such as native client support (Azure CLI) + sku = "Standard" + tunneling_enabled = true + ip_configuration { name = "configuration" - subnet_id = azurerm_subnet.graphdb-bastion-subnet.id - public_ip_address_id = azurerm_public_ip.graphdb-bastion-public-ip.id + subnet_id = azurerm_subnet.graphdb-bastion.id + public_ip_address_id = azurerm_public_ip.graphdb-bastion.id } tags = var.tags diff --git a/modules/bastion/variables.tf b/modules/bastion/variables.tf index 30264aa1..04b8e1c2 100644 --- a/modules/bastion/variables.tf +++ b/modules/bastion/variables.tf @@ -33,3 +33,8 @@ variable "bastion_subnet_address_prefix" { type = list(string) default = ["10.0.3.0/27"] } + +variable "bastion_allowed_cidr_blocks" { + description = "CIDR blocks allowed for connecting to Bastion" + type = list(string) +} diff --git a/modules/vm/main.tf b/modules/vm/main.tf index 15e0490c..d15032d3 100644 --- a/modules/vm/main.tf +++ b/modules/vm/main.tf @@ -1,46 +1,3 @@ -# Create Network Security Group and rules -resource "azurerm_network_security_group" "graphdb" { - name = "${var.resource_name_prefix}-nic" - resource_group_name = var.resource_group_name - location = var.location - - tags = var.tags -} - -resource "azurerm_network_security_rule" "graphdb-inbound-ssh" { - count = var.source_ssh_blocks != null ? 1 : 0 - - resource_group_name = var.resource_group_name - network_security_group_name = azurerm_network_security_group.graphdb.name - - name = "graphdb_ssh_inbound" - description = "Allow specified CIDRs SSH access to the GraphDB instances." - priority = 900 - direction = "Inbound" - access = "Allow" - protocol = "Tcp" - source_port_range = "*" - destination_port_range = 22 - source_address_prefixes = var.source_ssh_blocks - destination_address_prefix = var.graphdb_subnet_cidr -} - -resource "azurerm_network_security_rule" "graphdb-proxies-inbound" { - resource_group_name = var.resource_group_name - network_security_group_name = azurerm_network_security_group.graphdb.name - - name = "graphdb_proxies_inbound" - description = "Allow internet traffic to reach the GraphDB proxies" - priority = 1000 - direction = "Inbound" - access = "Allow" - protocol = "Tcp" - source_port_range = "*" - destination_port_range = "7201" - source_address_prefixes = ["0.0.0.0/0"] - destination_address_prefix = var.graphdb_subnet_cidr -} - locals { user_data_script = var.custom_user_data != null ? var.custom_user_data : templatefile("${path.module}/templates/entrypoint.sh.tpl", { graphdb_external_address_fqdn : var.graphdb_external_address_fqdn @@ -76,10 +33,14 @@ resource "azurerm_linux_virtual_machine_scale_set" "graphdb" { computer_name_prefix = "${var.resource_name_prefix}-" admin_username = "graphdb" + scale_in { + # In case of re-balancing, remove the newest VM which might have not been IN-SYNC yet with the cluster + rule = "NewestVM" + } + network_interface { - name = "${var.resource_name_prefix}-vmss-nic" - primary = true - network_security_group_id = azurerm_network_security_group.graphdb.id + name = "${var.resource_name_prefix}-vmss-nic" + primary = true ip_configuration { name = "${var.resource_name_prefix}-ip-config" @@ -104,6 +65,26 @@ resource "azurerm_linux_virtual_machine_scale_set" "graphdb" { depends_on = [azurerm_role_assignment.rg-contributor-role] } +resource "azurerm_monitor_autoscale_setting" "graphdb-autoscale-settings" { + name = "${var.resource_name_prefix}-vmss" + location = var.location + resource_group_name = var.resource_group_name + target_resource_id = azurerm_linux_virtual_machine_scale_set.graphdb.id + + profile { + name = "${var.resource_name_prefix}-vmss-fixed" + + # We want to keep a tight count for 3 node quorum + capacity { + default = var.node_count + maximum = var.node_count + minimum = var.node_count + } + } + + tags = var.tags +} + resource "azurerm_role_definition" "managed_disk_manager" { name = "ManagedDiskManager" scope = var.resource_group_id diff --git a/modules/vm/variables.tf b/modules/vm/variables.tf index 13a5ae03..68f50c7b 100644 --- a/modules/vm/variables.tf +++ b/modules/vm/variables.tf @@ -39,11 +39,6 @@ variable "graphdb_subnet_id" { type = string } -variable "graphdb_subnet_cidr" { - description = "CIDR of the subnet where GraphDB will be deployed" - type = string -} - # Security variable "identity_id" { @@ -100,12 +95,6 @@ variable "ssh_key" { default = null } -variable "source_ssh_blocks" { - description = "CIDR blocks to allow SSH traffic from." - type = list(string) - default = null -} - variable "custom_user_data" { description = "Custom user data script used during the cloud init phase in the GraphDB VMs. Should be in base64 encoding." type = string diff --git a/variables.tf b/variables.tf index eff5ffea..8a454cfc 100644 --- a/variables.tf +++ b/variables.tf @@ -48,6 +48,11 @@ variable "graphdb_subnet_address_prefix" { default = ["10.0.2.0/24"] } +variable "management_cidr_blocks" { + description = "CIDR blocks allowed to perform management operations such as connecting to Bastion or Key Vault." + type = list(string) +} + # TLS variable "tls_certificate_path" { @@ -125,12 +130,6 @@ variable "ssh_key" { default = null } -variable "source_ssh_blocks" { - description = "CIDR blocks to allow SSH traffic from." - type = list(string) - default = null -} - variable "custom_graphdb_vm_user_data" { description = "Custom user data script used during the cloud init phase in the GraphDB VMs. Should be in base64 encoding." type = string