From 7df2b72a100efd206fdc80bc2d7507ed44e1e16e Mon Sep 17 00:00:00 2001 From: jineshnagori Date: Fri, 14 Jul 2023 16:18:49 +0530 Subject: [PATCH] Two intermediate task added : hub-n-spoke and egress traffic on aks using fw --- intermediate/README.md | 10 +- intermediate/azure/AZ_FW-AKS-Egress/README.md | 21 +++ intermediate/azure/AZ_FW-AKS-Egress/main.tf | 159 +++++++++++++++++ .../azure/AZ_FW-AKS-Egress/provider.tf | 17 ++ .../azure/AZ_FW-AKS-Egress/variables.tf | 7 + intermediate/azure/Hub-and-Spoke/README.md | 7 + intermediate/azure/Hub-and-Spoke/hub.tf | 166 ++++++++++++++++++ intermediate/azure/Hub-and-Spoke/onprem.tf | 143 +++++++++++++++ intermediate/azure/Hub-and-Spoke/output.tf | 0 intermediate/azure/Hub-and-Spoke/providers.tf | 23 +++ intermediate/azure/Hub-and-Spoke/spokes.tf | 123 +++++++++++++ intermediate/azure/Hub-and-Spoke/variables.tf | 129 ++++++++++++++ 12 files changed, 801 insertions(+), 4 deletions(-) create mode 100644 intermediate/azure/AZ_FW-AKS-Egress/README.md create mode 100644 intermediate/azure/AZ_FW-AKS-Egress/main.tf create mode 100644 intermediate/azure/AZ_FW-AKS-Egress/provider.tf create mode 100644 intermediate/azure/AZ_FW-AKS-Egress/variables.tf create mode 100644 intermediate/azure/Hub-and-Spoke/README.md create mode 100644 intermediate/azure/Hub-and-Spoke/hub.tf create mode 100644 intermediate/azure/Hub-and-Spoke/onprem.tf create mode 100644 intermediate/azure/Hub-and-Spoke/output.tf create mode 100644 intermediate/azure/Hub-and-Spoke/providers.tf create mode 100644 intermediate/azure/Hub-and-Spoke/spokes.tf create mode 100644 intermediate/azure/Hub-and-Spoke/variables.tf diff --git a/intermediate/README.md b/intermediate/README.md index 920a181..74a5640 100644 --- a/intermediate/README.md +++ b/intermediate/README.md @@ -1,8 +1,10 @@ # Terraform Intermediate Track -## Kubernetes - -- [Deploy Your EKS Cluster using Terraform](https://github.com/collabnix/terraform/blob/master/beginners/aws/README.md) +#### Azure + + - [Terraform Provisioners in Azure](https://github.com/collabnix/terraform/blob/master/intermediate/azure/Terraform-Provisioners/) + - [Hub and Spoke Architecture](https://github.com/collabnix/terraform/blob/master/intermediate/azure/Hub-and-Spoke/) + - [Control egress traffic using Azure Firewall in Azure Kubernetes Service](https://github.com/collabnix/terraform/blob/master/intermediate/azure/AZ_FW-AKS-Egress/) ## Generic Terraform Related @@ -10,6 +12,6 @@ - [Terraform Functions](https://github.com/collabnix/terraform/blob/master/intermediate/Terraform-Functions) - Terraform Conditionals - Using Remote Backend -- Terraform Provisioners +- [Terraform Provisioners](https://github.com/collabnix/terraform/blob/master/intermediate/azure/Terraform-Provisioners/) - Multiple Providers diff --git a/intermediate/azure/AZ_FW-AKS-Egress/README.md b/intermediate/azure/AZ_FW-AKS-Egress/README.md new file mode 100644 index 0000000..2994609 --- /dev/null +++ b/intermediate/azure/AZ_FW-AKS-Egress/README.md @@ -0,0 +1,21 @@ +# Control egress traffic using Azure Firewall in Azure Kubernetes Service (AKS) + +Architecture : + + + +link : https://learn.microsoft.com/en-us/azure/aks/limit-egress-traffic + +required commands after `terraform apply` : + +1. Update Api Server Authorized IP Ranges +``` +az aks update --resource-group rg-egress-001 --name aks-egress-001 --api-server-authorized-ip-ranges FW_PIP/32,Your_PIP/32 +``` + +2. Create DNAT rule in Azure Firewall Policy and add Source Address of K8s Service and Destination address of Firewall Public IP +``` +az network firewall policy rule-collection-group collection add-nat-collection -n nat_collection --collection-priority 10003 --policy-name {policy} -g {rg} --rule-collection-group-name {collectiongroup} --action DNAT --rule-name network_rule --description "test" --destination-addresses "202.120.36.15" --source-addresses "202.120.36.13" "202.120.36.14" --translated-address 128.1.1.1 --translated-port 1234 --destination-ports 12000 12001 --ip-protocols TCP UDP +``` +or +`Create DNAT rule using Azure Portal` \ No newline at end of file diff --git a/intermediate/azure/AZ_FW-AKS-Egress/main.tf b/intermediate/azure/AZ_FW-AKS-Egress/main.tf new file mode 100644 index 0000000..2176cb4 --- /dev/null +++ b/intermediate/azure/AZ_FW-AKS-Egress/main.tf @@ -0,0 +1,159 @@ +resource "azurerm_resource_group" "rg" { + name = "rg-${var.postfix}" + location = var.location +} + +resource "azurerm_virtual_network" "vnet" { + name = "vnet-${var.postfix}" + location = azurerm_resource_group.rg.location + resource_group_name = azurerm_resource_group.rg.name + address_space = ["10.42.0.0/16"] +} + +resource "azurerm_subnet" "aks_subnet" { + name = "subnet-${var.postfix}" + resource_group_name = azurerm_resource_group.rg.name + virtual_network_name = azurerm_virtual_network.vnet.name + address_prefixes = ["10.42.1.0/24"] +} + +resource "azurerm_subnet" "fw_subnet" { + name = "AzureFirewallSubnet" + resource_group_name = azurerm_resource_group.rg.name + virtual_network_name = azurerm_virtual_network.vnet.name + address_prefixes = ["10.42.2.0/24"] +} + +resource "azurerm_public_ip" "fw_public_ip" { + name = "fw-pip-${var.postfix}" + resource_group_name = azurerm_resource_group.rg.name + location = azurerm_resource_group.rg.location + allocation_method = "Static" + sku = "Standard" +} + +resource "azurerm_firewall" "fw" { + name = "fw-${var.postfix}" + resource_group_name = azurerm_resource_group.rg.name + location = azurerm_resource_group.rg.location + sku_name = "AZFW_VNet" + sku_tier = "Standard" + firewall_policy_id = azurerm_firewall_policy.fw_policy.id + ip_configuration { + name = "fw-ip-config-${var.postfix}" + subnet_id = azurerm_subnet.fw_subnet.id + public_ip_address_id = azurerm_public_ip.fw_public_ip.id + } +} + +resource "azurerm_route_table" "fw_route_table" { + name = "fw-route-table-${var.postfix}" + resource_group_name = azurerm_resource_group.rg.name + location = azurerm_resource_group.rg.location + + route { + name = "fw-route-${var.postfix}" + address_prefix = "0.0.0.0/0" + next_hop_type = "VirtualAppliance" + next_hop_in_ip_address = azurerm_firewall.fw.ip_configuration[0].private_ip_address + } + + route { + name = "fw-route-internet-${var.postfix}" + address_prefix = "${azurerm_public_ip.fw_public_ip.ip_address}/32" + next_hop_type = "Internet" + next_hop_in_ip_address = null + } +} + +resource "azurerm_firewall_policy" "fw_policy" { + name = "fw-policy-${var.postfix}" + resource_group_name = azurerm_resource_group.rg.name + location = azurerm_resource_group.rg.location + dns { + proxy_enabled = true + } +} + +resource "azurerm_firewall_policy_rule_collection_group" "fw_rule_collection_group" { + name = "fw-rule-collection-group-${var.postfix}" + firewall_policy_id = azurerm_firewall_policy.fw_policy.id + priority = 100 + + network_rule_collection { + name = "aksfwnr" + priority = 200 + action = "Allow" + rule { + name = "apiudp" + protocols = ["UDP"] + source_addresses = ["*"] + destination_addresses = ["AzureCloud.${var.location}"] + destination_ports = ["1194"] + } + rule { + name = "apitcp" + protocols = ["TCP"] + source_addresses = ["*"] + destination_addresses = ["AzureCloud.${var.location}"] + destination_ports = ["9000"] + } + rule { + name = "time" + protocols = ["UDP"] + source_addresses = ["*"] + destination_fqdns = ["ntp.ubuntu.com"] + destination_ports = ["123"] + } + } + + application_rule_collection { + name = "aksfwar" + priority = 300 + action = "Allow" + rule { + name = "fqdn" + source_addresses = ["*"] + destination_fqdn_tags = ["AzureKubernetesService"] + protocols { + type = "Http" + port = 80 + } + protocols { + type = "Https" + port = 443 + } + } + } +} + +resource "azurerm_subnet_route_table_association" "aks_subnet_route_table_association" { + subnet_id = azurerm_subnet.aks_subnet.id + route_table_id = azurerm_route_table.fw_route_table.id +} + +resource "azurerm_kubernetes_cluster" "aks" { + name = "aks-${var.postfix}" + location = azurerm_resource_group.rg.location + resource_group_name = azurerm_resource_group.rg.name + dns_prefix = "aks-${var.postfix}" + + default_node_pool { + name = "default" + node_count = 1 + vm_size = "Standard_D2_v2" + vnet_subnet_id = azurerm_subnet.aks_subnet.id + } + + network_profile { + network_plugin = "azure" + outbound_type = "userDefinedRouting" + load_balancer_sku = "standard" + } + + identity { + type = "SystemAssigned" + } + + api_server_authorized_ip_ranges = api_server_authorized_ip_ranges = ["${azurerm_public_ip.fw_public_ip.ip_address}/32"] +} \ No newline at end of file diff --git a/intermediate/azure/AZ_FW-AKS-Egress/provider.tf b/intermediate/azure/AZ_FW-AKS-Egress/provider.tf new file mode 100644 index 0000000..1f6c150 --- /dev/null +++ b/intermediate/azure/AZ_FW-AKS-Egress/provider.tf @@ -0,0 +1,17 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 2.65" + } + } +} + +provider "azurerm" { + features {} + + client_id = "" + client_secret = "" + tenant_id = "" + subscription_id = "" +} \ No newline at end of file diff --git a/intermediate/azure/AZ_FW-AKS-Egress/variables.tf b/intermediate/azure/AZ_FW-AKS-Egress/variables.tf new file mode 100644 index 0000000..71f8e56 --- /dev/null +++ b/intermediate/azure/AZ_FW-AKS-Egress/variables.tf @@ -0,0 +1,7 @@ +variable "postfix" { + default = "egress-001" +} + +variable "location" { + default = "canadacentral" +} \ No newline at end of file diff --git a/intermediate/azure/Hub-and-Spoke/README.md b/intermediate/azure/Hub-and-Spoke/README.md new file mode 100644 index 0000000..5f0cdcf --- /dev/null +++ b/intermediate/azure/Hub-and-Spoke/README.md @@ -0,0 +1,7 @@ +# Create a hub and spoke hybrid network topology in Azure using Terraform + +Architecture : + + + +link : https://learn.microsoft.com/en-us/azure/developer/terraform/hub-spoke-introduction \ No newline at end of file diff --git a/intermediate/azure/Hub-and-Spoke/hub.tf b/intermediate/azure/Hub-and-Spoke/hub.tf new file mode 100644 index 0000000..400db32 --- /dev/null +++ b/intermediate/azure/Hub-and-Spoke/hub.tf @@ -0,0 +1,166 @@ +resource "azurerm_resource_group" "hub_rg" { + name = var.hub_resource_group_name + location = var.resource_group_location +} + +resource "azurerm_virtual_network" "hub_vnet" { + name = var.hub_vnet_name + location = var.resource_group_location + resource_group_name = azurerm_resource_group.hub_rg.name + address_space = ["192.168.0.0/16"] +} + +resource "azurerm_subnet" "hub_subnet" { + name = var.hub_subnet_name + resource_group_name = azurerm_resource_group.hub_rg.name + virtual_network_name = azurerm_virtual_network.hub_vnet.name + address_prefixes = ["192.168.1.0/24"] +} + +resource "azurerm_subnet" "hub_gateway_subnet" { + name = "GatewaySubnet" + resource_group_name = azurerm_resource_group.hub_rg.name + virtual_network_name = azurerm_virtual_network.hub_vnet.name + address_prefixes = ["192.168.255.224/27"] +} + +# Create public IPs +resource "azurerm_public_ip" "hub_public_ip" { + name = "hub-public-ip" + location = azurerm_resource_group.hub_rg.location + resource_group_name = azurerm_resource_group.hub_rg.name + allocation_method = "Static" +} + +# Create Network Security Group and rule +resource "azurerm_network_security_group" "hub_nsg" { + name = var.hub_nsg_name + location = azurerm_resource_group.hub_rg.location + resource_group_name = azurerm_resource_group.hub_rg.name + + security_rule { + name = "SSH" + priority = 1001 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = "*" + destination_address_prefix = "*" + } +} + +# Create network interface +resource "azurerm_network_interface" "hub_nic" { + name = var.hub_nic_name + location = azurerm_resource_group.hub_rg.location + resource_group_name = azurerm_resource_group.hub_rg.name + + ip_configuration { + name = "hub_nic_configuration" + subnet_id = azurerm_subnet.hub_subnet.id + private_ip_address_allocation = "Dynamic" + public_ip_address_id = azurerm_public_ip.hub_public_ip.id + } +} + +# Connect the security group to the network interface +resource "azurerm_network_interface_security_group_association" "hub_nisga" { + network_interface_id = azurerm_network_interface.hub_nic.id + network_security_group_id = azurerm_network_security_group.hub_nsg.id +} + +# Create storage account for boot diagnostics +resource "azurerm_storage_account" "hub_storage_account" { + name = var.hub_storage_account_name + resource_group_name = azurerm_resource_group.hub_rg.name + location = azurerm_resource_group.hub_rg.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +# Create (and display) an SSH key +resource "tls_private_key" "hub_ssh_key" { + algorithm = "RSA" + rsa_bits = 4096 +} + +# Create virtual machine +resource "azurerm_linux_virtual_machine" "hub_vm" { + name = var.hub_vm_name + resource_group_name = azurerm_resource_group.hub_rg.name + location = azurerm_resource_group.hub_rg.location + size = "Standard_D2s_v3" + network_interface_ids = [azurerm_network_interface.hub_nic.id] + + os_disk { + name = "hubOsDisk" + caching = "ReadWrite" + storage_account_type = "Premium_LRS" + } + + source_image_reference { + publisher = "Canonical" + offer = "0001-com-ubuntu-server-jammy" + sku = "22_04-lts-gen2" + version = "latest" + } + + computer_name = "hubvm" + admin_username = "azureuser" + disable_password_authentication = true + + admin_ssh_key { + username = "azureuser" + public_key = tls_private_key.hub_ssh_key.public_key_openssh + } + + boot_diagnostics { + storage_account_uri = azurerm_storage_account.hub_storage_account.primary_blob_endpoint + } +} + +resource "azurerm_public_ip" "hub_vpn_gateway_public_ip" { + name = "hub-vpn-gateway-public-ip" + location = azurerm_resource_group.hub_rg.location + resource_group_name = azurerm_resource_group.hub_rg.name + allocation_method = "Dynamic" +} + +resource "azurerm_virtual_network_gateway" "hub_vpn_gateway" { + name = "hub-vpn-gateway" + location = azurerm_resource_group.hub_rg.location + resource_group_name = azurerm_resource_group.hub_rg.name + type = "Vpn" + vpn_type = "RouteBased" + sku = "VpnGw1" + ip_configuration { + name = "hub-vpn-gateway-ip-configuration" + public_ip_address_id = azurerm_public_ip.hub_vpn_gateway_public_ip.id + private_ip_address_allocation = "Dynamic" + subnet_id = azurerm_subnet.hub_gateway_subnet.id + } +} + +resource "azurerm_virtual_network_gateway_connection" "hub-onprem-conn" { + name = "hub-onprem-conn" + location = azurerm_resource_group.hub_rg.location + resource_group_name = azurerm_resource_group.hub_rg.name + virtual_network_gateway_id = azurerm_virtual_network_gateway.hub_vpn_gateway.id + peer_virtual_network_gateway_id = azurerm_virtual_network_gateway.onprem_vpn_gateway.id + type = "Vnet2Vnet" + shared_key = "Azure@123" + routing_weight = 1 +} + +resource "azurerm_virtual_network_gateway_connection" "onprem-hub-conn" { + name = "onprem-hub-conn" + location = azurerm_resource_group.onprem_rg.location + resource_group_name = azurerm_resource_group.onprem_rg.name + virtual_network_gateway_id = azurerm_virtual_network_gateway.onprem_vpn_gateway.id + peer_virtual_network_gateway_id = azurerm_virtual_network_gateway.hub_vpn_gateway.id + type = "Vnet2Vnet" + shared_key = "Azure@123" + routing_weight = 1 +} \ No newline at end of file diff --git a/intermediate/azure/Hub-and-Spoke/onprem.tf b/intermediate/azure/Hub-and-Spoke/onprem.tf new file mode 100644 index 0000000..7e8b64c --- /dev/null +++ b/intermediate/azure/Hub-and-Spoke/onprem.tf @@ -0,0 +1,143 @@ +resource "azurerm_resource_group" "onprem_rg" { + name = var.onprem_resource_group_name + location = var.resource_group_location +} + +resource "azurerm_virtual_network" "onprem_vnet" { + name = var.onprem_vnet_name + location = var.resource_group_location + resource_group_name = azurerm_resource_group.onprem_rg.name + address_space = ["172.168.0.0/16"] +} + +resource "azurerm_subnet" "onprem_subnet" { + name = var.onprem_subnet_name + resource_group_name = azurerm_resource_group.onprem_rg.name + virtual_network_name = azurerm_virtual_network.onprem_vnet.name + address_prefixes = ["172.168.1.0/24"] +} + +resource "azurerm_subnet" "onprem_gateway_subnet" { + name = "GatewaySubnet" + resource_group_name = azurerm_resource_group.onprem_rg.name + virtual_network_name = azurerm_virtual_network.onprem_vnet.name + address_prefixes = ["172.168.255.224/27"] +} + +# Create public IPs +resource "azurerm_public_ip" "onprem_public_ip" { + name = "onprem-public-ip" + location = azurerm_resource_group.onprem_rg.location + resource_group_name = azurerm_resource_group.onprem_rg.name + allocation_method = "Static" +} + +# Create Network Security Group and rule +resource "azurerm_network_security_group" "onprem_nsg" { + name = var.onprem_nsg_name + location = azurerm_resource_group.onprem_rg.location + resource_group_name = azurerm_resource_group.onprem_rg.name + + security_rule { + name = "SSH" + priority = 1001 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = "*" + destination_address_prefix = "*" + } +} + +# Create network interface +resource "azurerm_network_interface" "onprem_nic" { + name = var.onprem_nic_name + location = azurerm_resource_group.onprem_rg.location + resource_group_name = azurerm_resource_group.onprem_rg.name + + ip_configuration { + name = "onprem_nic_configuration" + subnet_id = azurerm_subnet.onprem_subnet.id + private_ip_address_allocation = "Dynamic" + public_ip_address_id = azurerm_public_ip.onprem_public_ip.id + } +} + +# Connect the security group to the network interface +resource "azurerm_network_interface_security_group_association" "onprem_nisga" { + network_interface_id = azurerm_network_interface.onprem_nic.id + network_security_group_id = azurerm_network_security_group.onprem_nsg.id +} + +# Create storage account for boot diagnostics +resource "azurerm_storage_account" "onprem_storage_account" { + name = var.onprem_storage_account_name + resource_group_name = azurerm_resource_group.onprem_rg.name + location = azurerm_resource_group.onprem_rg.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +# Create (and display) an SSH key +resource "tls_private_key" "onprem_ssh_key" { + algorithm = "RSA" + rsa_bits = 4096 +} + +# Create virtual machine +resource "azurerm_linux_virtual_machine" "onprem_vm" { + name = var.onprem_vm_name + resource_group_name = azurerm_resource_group.onprem_rg.name + location = azurerm_resource_group.onprem_rg.location + size = "Standard_D2s_v3" + network_interface_ids = [azurerm_network_interface.onprem_nic.id] + + os_disk { + name = "onpremOsDisk" + caching = "ReadWrite" + storage_account_type = "Premium_LRS" + } + + source_image_reference { + publisher = "Canonical" + offer = "0001-com-ubuntu-server-jammy" + sku = "22_04-lts-gen2" + version = "latest" + } + + computer_name = "onpremvm" + admin_username = "azureuser" + disable_password_authentication = true + + admin_ssh_key { + username = "azureuser" + public_key = tls_private_key.onprem_ssh_key.public_key_openssh + } + + boot_diagnostics { + storage_account_uri = azurerm_storage_account.onprem_storage_account.primary_blob_endpoint + } +} + +resource "azurerm_public_ip" "onprem_vpn_gateway_public_ip" { + name = "onprem-vpn-gateway-public-ip" + location = azurerm_resource_group.onprem_rg.location + resource_group_name = azurerm_resource_group.onprem_rg.name + allocation_method = "Dynamic" +} + +resource "azurerm_virtual_network_gateway" "onprem_vpn_gateway" { + name = "onprem-vpn-gateway" + location = azurerm_resource_group.onprem_rg.location + resource_group_name = azurerm_resource_group.onprem_rg.name + type = "Vpn" + vpn_type = "RouteBased" + sku = "VpnGw1" + ip_configuration { + name = "onprem-vpn-gateway-ip-configuration" + public_ip_address_id = azurerm_public_ip.onprem_vpn_gateway_public_ip.id + subnet_id = azurerm_subnet.onprem_gateway_subnet.id + } +} \ No newline at end of file diff --git a/intermediate/azure/Hub-and-Spoke/output.tf b/intermediate/azure/Hub-and-Spoke/output.tf new file mode 100644 index 0000000..e69de29 diff --git a/intermediate/azure/Hub-and-Spoke/providers.tf b/intermediate/azure/Hub-and-Spoke/providers.tf new file mode 100644 index 0000000..2aa6ace --- /dev/null +++ b/intermediate/azure/Hub-and-Spoke/providers.tf @@ -0,0 +1,23 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "~> 2.65" + } + tls = { + source = "hashicorp/tls" + version = "~>4.0" + } + } + + backend "azurerm" { + resource_group_name = "rg-demo-cc-001" + storage_account_name = "stdemocc001" + container_name = "contdemocc001" + key = "contdemocc001.tfstate" + } +} + +provider "azurerm" { + features {} +} \ No newline at end of file diff --git a/intermediate/azure/Hub-and-Spoke/spokes.tf b/intermediate/azure/Hub-and-Spoke/spokes.tf new file mode 100644 index 0000000..d7ffae3 --- /dev/null +++ b/intermediate/azure/Hub-and-Spoke/spokes.tf @@ -0,0 +1,123 @@ +resource "azurerm_resource_group" "spoke_rg" { + name = var.spoke_resource_group_name + location = var.resource_group_location +} + +resource "azurerm_virtual_network" "spoke_vnet" { + count = var.spoke_count + name = "${var.spoke_vnet_name_prefix}${format("%03d", count.index + 1)}" + location = var.resource_group_location + resource_group_name = azurerm_resource_group.spoke_rg.name + address_space = ["10.${count.index + 1}.0.0/16"] +} + +resource "azurerm_subnet" "spoke_subnet" { + count = var.spoke_count + name = "${var.spoke_subnet_name_prefix}${format("%03d", count.index + 1)}" + resource_group_name = azurerm_resource_group.spoke_rg.name + virtual_network_name = azurerm_virtual_network.spoke_vnet[count.index].name + address_prefixes = ["10.${count.index + 1}.0.0/24"] +} + +# Create public IPs +resource "azurerm_public_ip" "spoke_public_ip" { + count = var.spoke_count + name = "${var.spoke_public_ip_name_prefix}${format("%03d", count.index + 1)}" + location = azurerm_resource_group.spoke_rg.location + resource_group_name = azurerm_resource_group.spoke_rg.name + allocation_method = "Static" +} + +# Create Network Security Group and rule +resource "azurerm_network_security_group" "spoke_nsg" { + count = var.spoke_count + name = "${var.spoke_nsg_name_prefix}${format("%03d", count.index + 1)}" + location = azurerm_resource_group.spoke_rg.location + resource_group_name = azurerm_resource_group.spoke_rg.name + + security_rule { + name = "SSH" + priority = 1001 + direction = "Inbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "22" + source_address_prefix = "*" + destination_address_prefix = "*" + } +} + +# Create network interface +resource "azurerm_network_interface" "spoke_nic" { + count = var.spoke_count + name = "${var.spoke_nic_name_prefix}${format("%03d", count.index + 1)}" + location = azurerm_resource_group.spoke_rg.location + resource_group_name = azurerm_resource_group.spoke_rg.name + + ip_configuration { + name = "spoke_nic_configuration" + subnet_id = azurerm_subnet.spoke_subnet[count.index].id + private_ip_address_allocation = "Dynamic" + public_ip_address_id = azurerm_public_ip.spoke_public_ip[count.index].id + } +} + +# Connect the security group to the network interface +resource "azurerm_network_interface_security_group_association" "spoke_nisga" { + count = var.spoke_count + network_interface_id = azurerm_network_interface.spoke_nic[count.index].id + network_security_group_id = azurerm_network_security_group.spoke_nsg[count.index].id +} + +# Create storage account for boot diagnostics +resource "azurerm_storage_account" "spoke_storage_account" { + count = var.spoke_count + name = "${var.spoke_storage_account_name_prefix}${format("%03d", count.index + 1)}" + resource_group_name = azurerm_resource_group.spoke_rg.name + location = azurerm_resource_group.spoke_rg.location + account_tier = "Standard" + account_replication_type = "LRS" +} + +# Create (and display) an SSH key +resource "tls_private_key" "spoke_ssh_key" { + algorithm = "RSA" + rsa_bits = 4096 +} + +# Create virtual machine +resource "azurerm_linux_virtual_machine" "spoke_vm" { + count = var.spoke_count + name = "${var.spoke_vm_name_prefix}${format("%03d", count.index + 1)}" + resource_group_name = azurerm_resource_group.spoke_rg.name + location = azurerm_resource_group.spoke_rg.location + size = "Standard_D2s_v3" + network_interface_ids = [azurerm_network_interface.spoke_nic[count.index].id] + + os_disk { + name = "${var.spoke_vm_name_prefix}${format("%03d", count.index + 1)}_osdisk" + caching = "ReadWrite" + storage_account_type = "Standard_LRS" + } + + source_image_reference { + publisher = "Canonical" + offer = "0001-com-ubuntu-server-jammy" + sku = "22_04-lts-gen2" + version = "latest" + } + + computer_name = "spokevm" + admin_username = "azureuser" + disable_password_authentication = true + + admin_ssh_key { + username = "azureuser" + public_key = tls_private_key.spoke_ssh_key.public_key_openssh + } + + boot_diagnostics { + storage_account_uri = azurerm_storage_account.spoke_storage_account[count.index].primary_blob_endpoint + } +} \ No newline at end of file diff --git a/intermediate/azure/Hub-and-Spoke/variables.tf b/intermediate/azure/Hub-and-Spoke/variables.tf new file mode 100644 index 0000000..3e3de30 --- /dev/null +++ b/intermediate/azure/Hub-and-Spoke/variables.tf @@ -0,0 +1,129 @@ +variable "resource_group_location" { + type = string + default = "canadacentral" +} + +variable "hub_resource_group_name" { + type = string + default = "rg-hub-cc-001" +} + +variable "spoke_resource_group_name" { + type = string + default = "rg-spoke-cc-001" +} + +variable "onprem_resource_group_name" { + type = string + default = "rg-onprem-cc-001" +} + +variable "hub_vnet_name" { + type = string + default = "vnet-hub-cc-001" +} + +variable "spoke_vnet_name_prefix" { + type = string + default = "vnet-spoke-cc-" +} + +variable "onprem_vnet_name" { + type = string + default = "vnet-onprem-cc-001" +} + +variable "hub_subnet_name" { + type = string + default = "subnet-hub-cc-001" +} + +variable "spoke_subnet_name_prefix" { + type = string + default = "subnet-spoke-cc-" +} + +variable "onprem_subnet_name" { + type = string + default = "subnet-onprem-cc-001" +} + +variable "hub_vm_name" { + type = string + default = "vm-hub-cc-001" +} + +variable "spoke_vm_name_prefix" { + type = string + default = "vm-spoke-cc-" +} + +variable "onprem_vm_name" { + type = string + default = "vm-onprem-cc-001" +} + +variable "spoke_count" { + type = number + default = 2 +} + +variable "hub_nsg_name" { + type = string + default = "nsg-hub-cc-001" +} + +variable "hub_public_ip_name" { + type = string + default = "pip-hub-cc-001" +} + +variable "onprem_nsg_name" { + type = string + default = "nsg-onprem-cc-001" +} + +variable "onprem_public_ip_name" { + type = string + default = "pip-onprem-cc-001" +} + +variable "spoke_nsg_name_prefix" { + type = string + default = "nsg-spoke-cc-" +} + +variable "spoke_public_ip_name_prefix" { + type = string + default = "pip-spoke-cc-" +} + +variable "hub_nic_name" { + type = string + default = "nic-hub-cc-001" +} + +variable "onprem_nic_name" { + type = string + default = "nic-onprem-cc-001" +} + +variable "spoke_nic_name_prefix" { + type = string + default = "nic-spoke-cc-" +} + +variable "hub_storage_account_name" { + type = string + default = "sthubcc001" +} + +variable "onprem_storage_account_name" { + type = string + default = "stonpremcc001" +} + +variable "spoke_storage_account_name_prefix" { + type = string + default = "stspokecc" +} \ No newline at end of file