Created
October 24, 2024 15:55
-
-
Save Tcarters/61a5093058565fd3f0104fb40d8b6ee4 to your computer and use it in GitHub Desktop.
Building a 4-Tier Virtual Network on Azure Cloud using Terraform
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ## Step 1: App Subnet | |
| resource "azurerm_subnet" "appsubnet" { | |
| name = "${azurerm_virtual_network.vnet.name}-${var.app_subnetName}" | |
| resource_group_name = azurerm_resource_group.mainRG.name | |
| virtual_network_name = azurerm_virtual_network.vnet.name | |
| address_prefixes = var.app_subnetAddress | |
| } | |
| ## Step 2: App Network Security Group | |
| resource "azurerm_network_security_group" "app_subnet_nsg" { | |
| name = "${azurerm_subnet.appsubnet.name}-nsg" | |
| resource_group_name = azurerm_resource_group.mainRG.name | |
| location = azurerm_resource_group.mainRG.location | |
| } | |
| ## Step 3: App Security Rules | |
| ### Define locals Blocks for Security Rules | |
| locals { | |
| app_inbound_ports_map = { | |
| "100" : "80", # If the key starts with a number, you must use the colon syntax ":" instead of "=" | |
| "110" : "443", | |
| "120" : "8080", | |
| "130" : "22" | |
| } | |
| } | |
| resource "azurerm_network_security_rule" "app_nsg_inbound" { | |
| for_each = local.app_inbound_ports_map | |
| name = "Allow-Rule-Port-${each.value}" | |
| priority = "${each.key}" | |
| direction = "Inbound" | |
| access = "Allow" | |
| protocol = "Tcp" | |
| source_port_range = "*" | |
| destination_port_range = "${each.value}" | |
| source_address_prefix = "*" | |
| destination_address_prefix = "*" | |
| resource_group_name = azurerm_resource_group.mainRG.name | |
| network_security_group_name = azurerm_network_security_group.app_subnet_nsg.name | |
| } | |
| ## Step 4: App Association Subnet and NSG | |
| resource "azurerm_subnet_network_security_group_association" "app_subnet_nsg_association" { | |
| depends_on = [ azurerm_network_security_rule.app_nsg_inbound ] | |
| subnet_id = azurerm_subnet.appsubnet.id | |
| network_security_group_id = azurerm_network_security_group.app_subnet_nsg.id | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # This manifest file is used to create bastion subnets and its NSG | |
| ## Step 1: Bastion / Management Subnet | |
| resource "azurerm_subnet" "bastionsubnet" { | |
| name = "${azurerm_virtual_network.vnet.name}-${var.bastion_subnetName}" | |
| resource_group_name = azurerm_resource_group.mainRG.name | |
| virtual_network_name = azurerm_virtual_network.vnet.name | |
| address_prefixes = var.bastion_subnetAddress | |
| } | |
| ## Step 2: Bastion Network Security Group (NSG) | |
| resource "azurerm_network_security_group" "bastion_subnet_nsg" { | |
| name = "${azurerm_subnet.bastionsubnet.name}-nsg" | |
| resource_group_name = azurerm_resource_group.mainRG.name | |
| location = azurerm_resource_group.mainRG.location | |
| } | |
| ## Step 3: Bastion Security Rules | |
| ### Define locals Blocks for Security Rules | |
| locals { | |
| bastion_inbound_ports_map = { | |
| "400" : "22", # If the key starts with a number, you must use the colon syntax ":" instead of "=" | |
| "410" : "3389" | |
| } | |
| } | |
| resource "azurerm_network_security_rule" "bastion_nsg_inbound" { | |
| for_each = local.bastion_inbound_ports_map | |
| name = "Allow-Rule-Port-${each.value}" | |
| priority = "${each.key}" | |
| direction = "Inbound" | |
| access = "Allow" | |
| protocol = "Tcp" | |
| source_port_range = "*" | |
| destination_port_range = "${each.value}" | |
| source_address_prefix = "*" | |
| destination_address_prefix = "*" | |
| resource_group_name = azurerm_resource_group.mainRG.name | |
| network_security_group_name = azurerm_network_security_group.bastion_subnet_nsg.name | |
| } | |
| ## Step 4: bastion Association Subnet and NSG | |
| resource "azurerm_subnet_network_security_group_association" "bastion_subnet_nsg_association" { | |
| depends_on = [ azurerm_network_security_rule.bastion_nsg_inbound ] | |
| subnet_id = azurerm_subnet.bastionsubnet.id | |
| network_security_group_id = azurerm_network_security_group.bastion_subnet_nsg.id | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # This file define the creation of db subnets | |
| ## Step 1: Create dbTier Subnet | |
| resource "azurerm_subnet" "dbsubnet" { | |
| name = "${azurerm_virtual_network.vnet.name}-${var.db_subnetName}" | |
| resource_group_name = azurerm_resource_group.mainRG.name | |
| virtual_network_name = azurerm_virtual_network.vnet.name | |
| address_prefixes = var.db_subnetAddress | |
| } | |
| ## Step 2: Create Network Security Group (NSG) | |
| resource "azurerm_network_security_group" "db_subnet_nsg" { | |
| name = "${azurerm_subnet.dbsubnet.name}-nsg" | |
| location = azurerm_resource_group.mainRG.location | |
| resource_group_name = azurerm_resource_group.mainRG.name | |
| } | |
| ## Step 3: Associate NSG and Subnet | |
| resource "azurerm_subnet_network_security_group_association" "db_subnet_nsg_association" { | |
| depends_on = [ azurerm_network_security_rule.db_nsg_inbound ] | |
| subnet_id = azurerm_subnet.dbsubnet.id | |
| network_security_group_id = azurerm_network_security_group.db_subnet_nsg.id | |
| } | |
| ## Step 4: Create NSG Rules for port 1433, 3306, | |
| locals { # For each port we use the local blocks for security rules creation | |
| db_inbound_ports_map = { | |
| # We use colon below cause the key starts with a number | |
| "300" : "3306", | |
| "310" : "1433" | |
| #"120" : "22" | |
| } | |
| } | |
| # Defining NSG Inbound Rules for port 80, 443, 22 in the dbTier Subnets | |
| resource "azurerm_network_security_rule" "db_nsg_inbound" { | |
| for_each = local.db_inbound_ports_map | |
| name = "Allow-Rule-Port-${each.value}" | |
| priority = "${each.key}" | |
| direction = "Inbound" | |
| access = "Allow" | |
| protocol = "Tcp" | |
| source_port_range = "*" # Allow all incoming connections | |
| destination_port_range = "${each.value}" # Allow to port 22 | |
| source_address_prefix = "*" | |
| destination_address_prefix = "*" | |
| resource_group_name = azurerm_resource_group.mainRG.name | |
| network_security_group_name = azurerm_network_security_group.db_subnet_nsg.name | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # This file contains all varibles for building the Virtual Network and its subnets | |
| ## Virtual Network | |
| variable "vnet_name" { | |
| description = "This is the Virtual Network Name" | |
| type = string | |
| default = "mainVnet" | |
| } | |
| # Virtual Network Address space | |
| variable "vnet_address_space" { | |
| description = "Vnet Address Space" | |
| type = list(string) | |
| default = [ "10.0.0.0/16" ] | |
| } | |
| #---------> | |
| ## Subnet 1: Bastion / Management Subnet | |
| variable "bastion_subnetName" { | |
| description = "Vnet Subnet bastion" | |
| type = string | |
| default = "bastionSubnet" | |
| } | |
| # Bastion Subnet Address space | |
| variable "bastion_subnetAddress" { | |
| description = "Bastion Address Space" | |
| type = list(string) | |
| default = [ "10.0.200.0/24" ] | |
| } | |
| #--------> | |
| ## Subnet 2: DB Subnet | |
| variable "db_subnetName" { | |
| description = "Vnet Subnet db" | |
| type = string | |
| default = "dbSubnet" | |
| } | |
| # Db Subnet Address space | |
| variable "db_subnetAddress" { | |
| description = "DB Address Space" | |
| type = list(string) | |
| default = [ "10.0.10.0/24" ] | |
| } | |
| #--------> | |
| ## Subnet 3: Web Subnet | |
| variable "web_subnetName" { | |
| description = "Vnet Subnet web" | |
| type = string | |
| default = "webSubnet" | |
| } | |
| # Web Subnet Address space | |
| variable "web_subnetAddress" { | |
| description = "Web Address Space" | |
| type = list(string) | |
| default = [ "10.0.20.0/24" ] | |
| } | |
| #--------> | |
| ## Subnet 4: App Subnet | |
| variable "app_subnetName" { | |
| description = "Vnet Subnet app" | |
| type = string | |
| default = "appSubnet" | |
| } | |
| # App Subnet Address space | |
| variable "app_subnetAddress" { | |
| description = "App Address Space" | |
| type = list(string) | |
| default = [ "10.0.30.0/24" ] | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Input variables serve as parameters for a Terraform module , allowing aspects of the module to be customised without altering | |
| # the module's own source code, and allowing modules to be shared between different configurations. | |
| # Subscript ID | |
| variable "subscription_id" { | |
| } | |
| # Dpartment division in the Entreprise | |
| variable "department_division" { | |
| description = "Department / Business Division refers to the large organization in this Infrastructure" | |
| type = string | |
| default = "guest" | |
| } | |
| # Environment variable | |
| variable "environment" { | |
| description = "this is the variable used as a prefix" | |
| default = "staging" | |
| } | |
| # Az Resource Group name | |
| variable "resource_group_name" { | |
| description = "This is the Resource Group name variable" | |
| type = string | |
| default = "mainRG" | |
| } | |
| # Az Resource Location | |
| variable "resource_location" { | |
| description = "Azure resource Region" | |
| type = string | |
| default = "West Europe" | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # A local value assigns a name to an expression, so you can use that name multiple times within a module without repeating it. | |
| # Local values are like a function's temporary local variables. | |
| locals { | |
| owners = var.department_division | |
| environment = var.environment | |
| resourceName_prefix = "${var.department_division}-${var.environment}" | |
| common_tags = { | |
| owners = local.owners, | |
| environment = local.environment | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Virtual Network Outputs | |
| ## Vnet name | |
| output "vnet_name" { | |
| description = "Virtual Network name" | |
| value = azurerm_virtual_network.vnet.name | |
| } | |
| ## Vnet ID | |
| output "virtual_network_name_id" { | |
| description = "Vnet ID" | |
| value = azurerm_virtual_network.vnet.id | |
| } | |
| ## Subnets Outputs | |
| output "web_subnetName" { | |
| description = "webTier Subnet name" | |
| value = azurerm_subnet.websubnet.name | |
| } | |
| output "app_subnetName" { | |
| description = "appTier Subnet name" | |
| value = azurerm_subnet.appsubnet.name | |
| } | |
| output "db_subnetName" { | |
| description = "dbTier Subnet name" | |
| value = azurerm_subnet.dbsubnet.name | |
| } | |
| output "bastion_subnetName" { | |
| description = "bastionTier Subnet name" | |
| value = azurerm_subnet.bastionsubnet.name | |
| } | |
| ## Network Security Group and IDs Outputs | |
| ### Web Subnet NSG Name 1 | |
| output "web_subnet_nsg" { | |
| description = "webTier Subnet NSG Name" | |
| value = azurerm_network_security_group.web_subnet_nsg.name | |
| } | |
| ### Web Subnet NSG ID | |
| output "web_subnet_nsg_id" { | |
| description = "webTier Subnet NSG ID" | |
| value = azurerm_network_security_group.web_subnet_nsg.id | |
| } | |
| ### App Subnet NSG Name 2 | |
| output "app_subnet_nsg" { | |
| description = "appTier Subnet NSG Name" | |
| value = azurerm_network_security_group.app_subnet_nsg.name | |
| } | |
| ### Web Subnet NSG ID | |
| output "app_subnet_nsg_id" { | |
| description = "appTier Subnet NSG ID" | |
| value = azurerm_network_security_group.app_subnet_nsg.id | |
| } | |
| ### Db Subnet NSG Name 3 | |
| output "db_subnet_nsg" { | |
| description = "dbTier Subnet NSG Name" | |
| value = azurerm_network_security_group.db_subnet_nsg.name | |
| } | |
| ### Web Subnet NSG ID | |
| output "db_subnet_nsg_id" { | |
| description = "dbTier Subnet NSG ID" | |
| value = azurerm_network_security_group.db_subnet_nsg.id | |
| } | |
| ### Bastion Subnet NSG Name 4 | |
| output "bastion_subnet_nsg" { | |
| description = "bastionTier Subnet NSG Name" | |
| value = azurerm_network_security_group.bastion_subnet_nsg.name | |
| } | |
| ### Web Subnet NSG ID | |
| output "bastion_subnet_nsg_id" { | |
| description = "bastionTier Subnet NSG ID" | |
| value = azurerm_network_security_group.bastion_subnet_nsg.id | |
| } | |
| # locals { | |
| # list_subnets = { | |
| # "subnet1" = "web", | |
| # subnet2 = "app", | |
| # subnet3 = "db", | |
| # subnet4 = "bastion" | |
| # } | |
| # } | |
| # for_each = local.list_subnets | |
| # # output "$${each.value}_subnetName" { | |
| # # description = "${each.key} - ${each.value}" | |
| # # value = "azure_subnet.${each.value}_subnetName.name" | |
| # # } | |
| # output "subnet_outputs" { | |
| # value = { for key, value in local.list_subnets : "${value}_subnetName" => azure_subnet[value].name } | |
| # } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| terraform { | |
| required_providers { | |
| azurerm = { | |
| source = "hashicorp/azurerm" | |
| version = ">= 4.5.0" | |
| } | |
| } | |
| } | |
| # Provider Block | |
| provider "azurerm" { | |
| subscription_id = var.subscription_id | |
| features { | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Random string Resource | |
| resource "random_string" "myRandom" { | |
| length = 6 | |
| upper = false | |
| special = false | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Resource Group definition | |
| resource "azurerm_resource_group" "mainRG" { | |
| name = "${local.resourceName_prefix}-${var.resource_group_name}-${random_string.myRandom.id}" | |
| location = var.resource_location | |
| tags = local.common_tags | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| department_division = "eng" #<Put your real department division here, recommended for production> | |
| subscription_id = "" # <Put your azure account subscription here> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # this is the definition of the virtual network to be created | |
| resource "azurerm_virtual_network" "vnet" { | |
| name = "${local.resourceName_prefix}-${var.vnet_name}" | |
| resource_group_name = azurerm_resource_group.mainRG.name | |
| location = azurerm_resource_group.mainRG.location | |
| address_space = var.vnet_address_space | |
| tags = local.common_tags | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # This file define the creation of web subnets | |
| ## Step 1: Create WebTier Subnet | |
| resource "azurerm_subnet" "websubnet" { | |
| name = "${azurerm_virtual_network.vnet.name}-${var.web_subnetName}" | |
| resource_group_name = azurerm_resource_group.mainRG.name | |
| virtual_network_name = azurerm_virtual_network.vnet.name | |
| address_prefixes = var.web_subnetAddress | |
| } | |
| ## Step 2: Create Network Security Group (NSG) | |
| resource "azurerm_network_security_group" "web_subnet_nsg" { | |
| name = "${azurerm_subnet.websubnet.name}-nsg" | |
| location = azurerm_resource_group.mainRG.location | |
| resource_group_name = azurerm_resource_group.mainRG.name | |
| } | |
| ## Step 3: Associate NSG and Subnet | |
| resource "azurerm_subnet_network_security_group_association" "web_subnet_nsg_association" { | |
| depends_on = [ azurerm_network_security_rule.web_nsg_inbound ] | |
| subnet_id = azurerm_subnet.websubnet.id | |
| network_security_group_id = azurerm_network_security_group.web_subnet_nsg.id | |
| } | |
| ## Step 4: Create NSG Rules for port 22, 80, 443, 8080, 8081, 8082, 9090, 9091 | |
| locals { # For each port we use the local blocks for security rules creation | |
| web_inbound_ports_map = { | |
| # We use colon below cause the key starts with a number | |
| "200" : "80", | |
| "210" : "443", | |
| "220" : "22" | |
| } | |
| } | |
| # Defining NSG Inbound Rules for port 80, 443, 22 in the WebTier Subnets | |
| resource "azurerm_network_security_rule" "web_nsg_inbound" { | |
| for_each = local.web_inbound_ports_map | |
| name = "Allow-Rule-Port-${each.value}" | |
| priority = "${each.key}" | |
| direction = "Inbound" | |
| access = "Allow" | |
| protocol = "Tcp" | |
| source_port_range = "*" # Allow all incoming connections | |
| destination_port_range = "${each.value}" # Allow to port 22 | |
| source_address_prefix = "*" | |
| destination_address_prefix = "*" | |
| resource_group_name = azurerm_resource_group.mainRG.name | |
| network_security_group_name = azurerm_network_security_group.web_subnet_nsg.name | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment