Creating the infrastructure for a secure 3-tier application on Azure
Kishaloy Kar Chowdhury
3 min read
main.tf file :
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~>3.0"
}
}
}
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "rg" {
name = "appservice-rg"
location = "francecentral"
}
resource "azurerm_virtual_network" "vnet" {
name = "vnet"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
address_space = ["10.0.0.0/16"]
}
resource "azurerm_subnet" "integrationsubnet" {
name = "integrationsubnet"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = ["10.0.1.0/24"]
delegation {
name = "delegation"
service_delegation {
name = "Microsoft.Web/serverFarms"
}
}
}
resource "azurerm_subnet" "endpointsubnet" {
name = "endpointsubnet"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = ["10.0.2.0/24"]
private_endpoint_network_policies_enabled = true
}
resource "azurerm_service_plan" "appserviceplan" {
name = "appserviceplan"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
os_type = "Windows"
sku_name = "S1"
}
resource "azurerm_windows_web_app" "frontwebapp" {
name = "frontend-kk"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
service_plan_id = azurerm_service_plan.appserviceplan.id
site_config {}
app_settings = {
"WEBSITE_DNS_SERVER" = "168.63.129.16",
"BACKEND_URL" = "http://${azurerm_private_dns_zone_virtual_network_link.dnszonelink.private_dns_zone_name}/api/message"
}
}
resource "azurerm_app_service_virtual_network_swift_connection" "vnetintegrationconnection" {
app_service_id = azurerm_windows_web_app.frontwebapp.id
subnet_id = azurerm_subnet.integrationsubnet.id
}
resource "azurerm_windows_web_app" "backwebapp" {
name = "backend-kk"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
service_plan_id = azurerm_service_plan.appserviceplan.id
site_config {}
}
resource "azurerm_private_dns_zone" "dnsprivatezone" {
name = "privatelink.azurewebsites.net"
resource_group_name = azurerm_resource_group.rg.name
}
resource "azurerm_private_dns_zone_virtual_network_link" "dnszonelink" {
name = "dnszonelink"
resource_group_name = azurerm_resource_group.rg.name
private_dns_zone_name = azurerm_private_dns_zone.dnsprivatezone.name
virtual_network_id = azurerm_virtual_network.vnet.id
}
resource "azurerm_private_endpoint" "privateendpoint" {
name = "backwebappprivateendpoint"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
subnet_id = azurerm_subnet.endpointsubnet.id
private_dns_zone_group {
name = "privatednszonegroup"
private_dns_zone_ids = [azurerm_private_dns_zone.dnsprivatezone.id]
}
private_service_connection {
name = "privateendpointconnection"
private_connection_resource_id = azurerm_windows_web_app.backwebapp.id
subresource_names = ["sites"]
is_manual_connection = false
}
}
resource "random_pet" "azurerm_mssql_server_name" {
prefix = "sql"
}
resource "azurerm_mssql_server" "server" {
name = random_pet.azurerm_mssql_server_name.id
resource_group_name = azurerm_resource_group.rg.name
location = azurerm_resource_group.rg.location
version = "12.0"
administrator_login = "sqladmin"
administrator_login_password = "ENTER THE PASSWORD"
}
# MSSQL Database
resource "azurerm_mssql_database" "sqldatabase" {
name = "appdatabase"
server_id = azurerm_mssql_server.server.id
collation = "SQL_Latin1_General_CP1_CI_AS"
license_type = "LicenseIncluded"
max_size_gb = 10
sku_name = "S0"
zone_redundant = false
}
# Network Security Group for MSSQL Database
resource "azurerm_network_security_group" "sqlnsg" {
name = "sqlnsg"
location = azurerm_resource_group.rg.location
resource_group_name = azurerm_resource_group.rg.name
}
# Network Security Rule to allow SQL traffic
resource "azurerm_network_security_rule" "sqlrule" {
name = "SQLTraffic"
priority = 100
direction = "Inbound"
access = "Allow"
protocol = "Tcp"
source_port_range = "*"
destination_port_range = "1433"
source_address_prefix = "VirtualNetwork"
destination_address_prefix = "*"
resource_group_name = azurerm_resource_group.rg.name
network_security_group_name = azurerm_network_security_group.sqlnsg.name
}
# Associate NSG to the Subnet
resource "azurerm_subnet_network_security_group_association" "sqlsubnetnsgassociation" {
subnet_id = azurerm_subnet.endpointsubnet.id
network_security_group_id = azurerm_network_security_group.sqlnsg.id
}
Then we have to follow the below commands :
terraform init
terraform plan
terraform apply
On doing this, the Terraform code provisions a secure 3-tier application infrastructure on Azure. It creates a resource group, virtual network with two subnets, an app service plan, frontend and backend web apps, a private DNS zone, and a private endpoint for the backend app. It also sets up an MSSQL server and database, along with a network security group and rules to allow SQL traffic within the virtual network.
10
Subscribe to my newsletter
Read articles from Kishaloy Kar Chowdhury directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by