HashiCorp Terraform implementation

The HeartAI implementation of Microsoft Azure is managed with the Terraform declarative infrastructure-as-code software framework. Terraform allows for the declaration of system components using configuration files specified with the HashiCorp Configuration Language (HCL). Collections of these configuration files provide a declarative representation of HeartAI infrastructure-level components, which are synchronisable with the state of Microsoft Azure environments through the Azure Resource Manager API. Infrastructure deployment with Terraform supports HeartAI system infrastructure management in a way that is consistent, maintainable, scalable, and reproducible.

Terraform state management

To support Terraform operations, the representative state of the Terraform instance is itself stored within the Azure environment and managed by Terraform. This state is used by Terraform to map resources to its local representation, keep track of metadata, and to improve performance. Terraform uses this state to coordinate synchronisations to the Azure Resource Manager API. Prior to any operation, Terraform performs a refresh to update this state with the corresponding Azure environment. For the HeartAI Azure environment, all modifications to the Azure environment are administered through Terraform, such that the Terraform state should be the representative state of the Azure environment.

The following figure shows the process through which a user agent or client may utilise Terraform to communicate with Terraform State and Microsoft Azure to perform a sychronisation of Azure resources:

heartai-azure-terraform-process.svg

Example: Terraform configuration for Azure management

The following example shows Terraform declarations to configure Terraform to utilise the Azure Resource Manager API and coordinate with corresponding Azure resources.

This implementation coordinates instances of the following Azure components:

Azure component Functionality for Terraform Azure configuration
Storage Account Persists Terraform state
Key Vault access policy Manages a SystemAssigned service principal and associates an access policy.
Key Vault key Enables Terraform state data encryption .
Storage Account customer managed key Uses the above key for data encryption
Private Endpoint Provides network endpoint within the corresponding Azure Private DNS zone
Private DNS zone A record Resolves network endpoint within the corresponding Azure Private DNS zone
provider "azurerm" {
  features {}
}


data "azurerm_client_config" "current" {}

resource "azurerm_resource_group" "rg_terraform" {
  name = "sah-heartai-rg-prod-tfstate-aue-001"
  location = "australiaeast"

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

resource "azurerm_storage_account" "terraform_state_storage" {
  name = "tfstate29819"
  resource_group_name = azurerm_resource_group.rg_terraform.name
  location = azurerm_resource_group.rg_terraform.location
  account_tier = "Standard"
  account_replication_type = "LRS"

  identity {
    type = "SystemAssigned"
  }

  network_rules {
    default_action = "Deny"
    bypass = [
      "AzureServices"]
  }

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

resource "azurerm_key_vault_access_policy" "keyvault_access_policy_terraform_storage" {
  key_vault_id = azurerm_key_vault.keyvault.id
  tenant_id = data.azurerm_client_config.current.tenant_id
  object_id = azurerm_storage_account.terraform_state_storage.identity[0].principal_id

  key_permissions = [
    "Get",
    "Create",
    "List",
    "Restore",
    "Recover",
    "Unwrapkey",
    "Wrapkey",
    "Purge",
    "Encrypt",
    "Decrypt",
    "Sign",
    "Verify"]
  secret_permissions = [
    "Get"]
}

resource "azurerm_key_vault_key" "terraform_storage_key" {
  depends_on = [
    azurerm_key_vault_access_policy.keyvault_access_policy_keyvault_client,
    azurerm_key_vault_access_policy.keyvault_access_policy_terraform_storage
  ]

  name = "sah-heartai-terraform-state-sa-key"
  key_vault_id = azurerm_key_vault.keyvault.id
  key_type = "RSA"
  key_size = 2048
  key_opts = [
    "decrypt",
    "encrypt",
    "sign",
    "unwrapKey",
    "verify",
    "wrapKey"]
}

resource "azurerm_storage_account_customer_managed_key" "terraform_state_storage_cmk" {
  storage_account_id = azurerm_storage_account.terraform_state_storage.id
  key_vault_id = azurerm_key_vault.keyvault.id
  key_name = azurerm_key_vault_key.terraform_storage_key.name
}

resource "azurerm_private_endpoint" "terraform_state_storage_private_endpoint" {
  depends_on = [
    azurerm_resource_group.rg,
    azurerm_virtual_network.vnet,
    azurerm_subnet.snet_paas,
    azurerm_storage_account.terraform_state_storage]
  name = "sah-heartai-pe-sa-terraform-state-prod-aue-001"
  location = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  subnet_id = azurerm_subnet.snet_paas.id

  private_service_connection {
    name = "sah-heartai-pe-sa-terraform-state-prod-aue-001"
    is_manual_connection = false
    private_connection_resource_id = azurerm_storage_account.terraform_state_storage.id
    subresource_names = [
      "blob"]
  }

  private_dns_zone_group {
    name = azurerm_private_dns_zone.azure_storage_blob_dns_private.name
    private_dns_zone_ids = [
      azurerm_private_dns_zone.azure_storage_blob_dns_private.id]
  }

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

data "azurerm_private_endpoint_connection" "terraform_state_storage_private_endpoint_connection" {
  depends_on = [
    azurerm_resource_group.rg,
    azurerm_private_endpoint.terraform_state_storage_private_endpoint]
  name = azurerm_private_endpoint.terraform_state_storage_private_endpoint.name
  resource_group_name = azurerm_resource_group.rg.name
}

resource "azurerm_private_dns_a_record" "terraform_state_storage_dns_a_record" {
  depends_on = [
    azurerm_resource_group.rg,
    azurerm_storage_account.terraform_state_storage,
    azurerm_private_dns_zone.azure_storage_blob_dns_private,
    data.azurerm_private_endpoint_connection.terraform_state_storage_private_endpoint_connection]
  name = lower(azurerm_storage_account.terraform_state_storage.name)
  zone_name = azurerm_private_dns_zone.azure_storage_blob_dns_private.name
  resource_group_name = azurerm_resource_group.rg.name
  ttl = 300
  records = [
    data.azurerm_private_endpoint_connection.terraform_state_storage_private_endpoint_connection.private_service_connection.0.private_ip_address]

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

output terraform_state_storage_private_ip {
  value = data.azurerm_private_endpoint_connection.terraform_state_storage_private_endpoint_connection.private_service_connection.0.private_ip_address
}

terraform {
  backend "azurerm" {
    resource_group_name = "sah-heartai-rg-prod-tfstate-aue-001"
    storage_account_name = "tfstate29819"
    container_name = "tfstate"
    key = "terraform-tfstate-prod-dnszone"
  }

  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
      version = "=2.49.0"
    }
    postgresql = {
      source  = "cyrilgdn/postgresql"
    }
    random = {
      source  = "hashicorp/random"
    }
  }
}

Example: Azure Virtual Network

The following example shows Terraform declarations to specify an Azure Virtual Network. This implementation coordinates instances of the following Azure components:

Azure component Functionality for Azure Virtual Network
Private DNS Provides private name resolution for Azure Storage Account network endpoints within the corresponding Azure Private DNS zone
Virtual Network Configures and deploys an Azure Virtual Network
Network Watcher Integrates an instance of Azure Network Watcher to a corresponding Azure Virtual Network
resource "azurerm_private_dns_zone" "heartai-dns-private" {
  name = "sah.heartai.net"
  resource_group_name = azurerm_resource_group.rg.name

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

resource "azurerm_virtual_network" "vnet" {
  name = "sah-heartai-vnet-prod-aue-001"
  location = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  address_space = [
    var.vnet-prod-aue-001-address-space.vnet]

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

resource "azurerm_subnet" "snet_aroworker" {
  name = "sah-heartai-snet-aroworker-prod-aue-001"
  resource_group_name = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes = [
    var.vnet-prod-aue-001-address-space.snet1]
  service_endpoints = [
    "Microsoft.ContainerRegistry"]
  enforce_private_link_endpoint_network_policies = true
}

resource "azurerm_subnet" "snet_aromaster" {
  name = "sah-heartai-snet-aromaster-prod-aue-002"
  resource_group_name = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes = [
    var.vnet-prod-aue-001-address-space.snet2]
  service_endpoints = [
    "Microsoft.ContainerRegistry"]
  enforce_private_link_service_network_policies = true
}

resource "azurerm_subnet" "snet_vpn_gateway" {
  name = "GatewaySubnet"
  resource_group_name = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes = [
    var.vnet-prod-aue-001-address-space.snet3]
  enforce_private_link_endpoint_network_policies = true
}

resource "azurerm_subnet" "snet_paas" {
  name = "sah-heartai-snet-paas-prod-aue-004"
  resource_group_name = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes = [
    var.vnet-prod-aue-001-address-space.snet4]
  enforce_private_link_endpoint_network_policies = true
}

resource "azurerm_network_watcher" "network_watcher" {
  name = "NetworkWatcher_australiaeast"
  location = "australiaeast"
  resource_group_name = "NetworkWatcherRG"

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

Example: Azure network security group

The following example shows Terraform declarations to specify the HeartAI default Azure network security group. This implementation coordinates instances of the following Azure components:

Azure component Functionality for network security group
Network security group Specifies configuration for corresponding Azure network security group
resource "azurerm_network_security_group" "nsg_default" {
  name = "sah-heartai-nsg-default-prod-aue-001"
  location = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  security_rule {
    name = "AllowVnetInBound"
    description = "Allow inbound traffic from all VMs to all VMs in VNET"
    priority = 100
    direction = "Inbound"
    access = "Allow"
    protocol = "*"
    source_port_range = "*"
    destination_port_range = "*"
    source_address_prefix = "VirtualNetwork"
    destination_address_prefix = "VirtualNetwork"
  }

  security_rule {
    name = "AllowAzureLoadBalancerInBound"
    description = "Allow inbound traffic from Azure Load Balancer"
    priority = 101
    direction = "Inbound"
    access = "Allow"
    protocol = "*"
    source_port_range = "*"
    destination_port_range = "*"
    source_address_prefix = "AzureLoadBalancer"
    destination_address_prefix = "*"
  }

  security_rule {
    name = "DenyAllInBound"
    description = "Deny all inbound traffic"
    priority = 102
    direction = "Inbound"
    access = "Deny"
    protocol = "*"
    source_port_range = "*"
    destination_port_range = "*"
    source_address_prefix = "*"
    destination_address_prefix = "*"
  }

  security_rule {
    name = "AllowVnetOutBound"
    description = "Allow outbound traffic from all VMs to all VMs in VNET"
    priority = 100
    direction = "Outbound"
    access = "Allow"
    protocol = "*"
    source_port_range = "*"
    destination_port_range = "*"
    source_address_prefix = "VirtualNetwork"
    destination_address_prefix = "VirtualNetwork"
  }

  security_rule {
    name = "AllowInternetOutBound"
    description = "Allow outbound traffic from all VMs to Internet"
    priority = 101
    direction = "Outbound"
    access = "Allow"
    protocol = "*"
    source_port_range = "*"
    destination_port_range = "*"
    source_address_prefix = "*"
    destination_address_prefix = "Internet"
  }

  security_rule {
    name = "DenyAllOutBound"
    description = "Deny all outbound traffic"
    priority = 102
    direction = "Outbound"
    access = "Deny"
    protocol = "*"
    source_port_range = "*"
    destination_port_range = "*"
    source_address_prefix = "*"
    destination_address_prefix = "*"
  }

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

Example: Azure Storage Account virtual network linking

The following example shows Terraform declarations to expose Azure Storage Account network endpoints to the corresponding Azure Virtual Network. This implementation coordinates instances of the following Azure components:

Azure component Functionality for Azure Storage Account virtual network linking
Private DNS Provides private name resolution for Azure Storage Account network endpoints within the corresponding Private DNS zone
Virtual Network Link Exposes Azure Storage Account network endpoints within the corresponding Azure Virtual Network
resource "azurerm_private_dns_zone" "azure_storage_blob_dns_private" {
  depends_on = [
    azurerm_resource_group.rg]
  name = "privatelink.blob.core.windows.net"
  resource_group_name = azurerm_resource_group.rg.name

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

resource "azurerm_private_dns_zone_virtual_network_link" "azure_storage_blob_dns_vnet_link" {
  depends_on = [
    azurerm_resource_group.rg,
    azurerm_virtual_network.vnet,
    azurerm_private_dns_zone.azure_storage_blob_dns_private]
  name = "sah-heartai-sa-blob-vnetlink-prod-aue-001"
  resource_group_name = azurerm_resource_group.rg.name
  private_dns_zone_name = azurerm_private_dns_zone.azure_storage_blob_dns_private.name
  virtual_network_id = azurerm_virtual_network.vnet.id

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

resource "azurerm_private_dns_zone" "azure_storage_table_dns_private" {
  depends_on = [
    azurerm_resource_group.rg]
  name = "privatelink.table.core.windows.net"
  resource_group_name = azurerm_resource_group.rg.name

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

resource "azurerm_private_dns_zone_virtual_network_link" "azure_storage_table_dns_vnet_link" {
  depends_on = [
    azurerm_resource_group.rg,
    azurerm_virtual_network.vnet,
    azurerm_private_dns_zone.azure_storage_table_dns_private]
  name = "sah-heartai-sa-table-vnetlink-prod-aue-001"
  resource_group_name = azurerm_resource_group.rg.name
  private_dns_zone_name = azurerm_private_dns_zone.azure_storage_table_dns_private.name
  virtual_network_id = azurerm_virtual_network.vnet.id

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

resource "azurerm_private_dns_zone" "azure_storage_queue_dns_private" {
  depends_on = [
    azurerm_resource_group.rg]
  name = "privatelink.queue.core.windows.net"
  resource_group_name = azurerm_resource_group.rg.name

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

resource "azurerm_private_dns_zone_virtual_network_link" "azure_storage_queue_dns_vnet_link" {
  depends_on = [
    azurerm_resource_group.rg,
    azurerm_virtual_network.vnet,
    azurerm_private_dns_zone.azure_storage_queue_dns_private]
  name = "sah-heartai-sa-queue-vnetlink-prod-aue-001"
  resource_group_name = azurerm_resource_group.rg.name
  private_dns_zone_name = azurerm_private_dns_zone.azure_storage_queue_dns_private.name
  virtual_network_id = azurerm_virtual_network.vnet.id
}

resource "azurerm_private_dns_zone" "azure_storage_file_dns_private" {
  depends_on = [
    azurerm_resource_group.rg]
  name = "privatelink.file.core.windows.net"
  resource_group_name = azurerm_resource_group.rg.name

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

resource "azurerm_private_dns_zone_virtual_network_link" "azure_storage_file_dns_vnet_link" {
  depends_on = [
    azurerm_resource_group.rg,
    azurerm_virtual_network.vnet,
    azurerm_private_dns_zone.azure_storage_file_dns_private]
  name = "sah-heartai-sa-file-vnetlink-prod-aue-001"
  resource_group_name = azurerm_resource_group.rg.name
  private_dns_zone_name = azurerm_private_dns_zone.azure_storage_file_dns_private.name
  virtual_network_id = azurerm_virtual_network.vnet.id

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

Example: Azure Key Vault

The following example shows Terraform declarations to configure and deploy an instance of Azure Key Vault. This implementation coordinates instances of the following Azure components:

Azure component Functionality for Azure Key Vault
Azure Key Vault Configure and deploy an instance of Azure Key Vault
resource "azurerm_key_vault" "keyvault" {
  name = "sah-heartai-kv-prod"
  resource_group_name = azurerm_resource_group.rg_keyvault.name
  location = azurerm_resource_group.rg_keyvault.location
  enabled_for_disk_encryption = true
  tenant_id = data.azurerm_client_config.client.tenant_id
  soft_delete_retention_days = var.kv_prod_aue_001_soft_delete_retention_days
  purge_protection_enabled = true

  sku_name = "standard"

  network_acls {
    default_action = "Deny"
    bypass = "AzureServices"
  }

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

Example: Azure Key Vault private endpoint

The following Terraform declaration shows the HeartAI production environment Azure Private Link private endpoint for the system instance of Azure Key Vault. This implementation coordinates instances of the following Azure components:

Azure component Functionality for Azure Key Vault private endpoint
Private DNS Provides private name resolution for Azure Key Vault network endpoints within the corresponding Private DNS zone
Storage Account customer managed key Uses the above key for data encryption
Private endpoint Provides network endpoint within the corresponding Azure Private DNS zone
Private DNS zone A record Resolves network endpoint within the corresponding Azure Private DNS zone
Virtual Network Link Exposes Azure Key Vault network endpoints within the corresponding Azure Virtual Network
resource "azurerm_private_dns_zone" "keyvault_dns_private" {
  name = "privatelink.vaultcore.azure.net"
  resource_group_name = azurerm_resource_group.rg.name

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

resource "azurerm_private_endpoint" "keyvault_private_endpoint" {
  depends_on = [
    azurerm_key_vault.keyvault]
  name = "sah-heartai-pe-kv-prod-aue-001"
  location = azurerm_resource_group.rg_keyvault.location
  resource_group_name = azurerm_resource_group.rg_keyvault.name
  subnet_id = azurerm_subnet.snet_paas.id

  private_service_connection {
    name = "sah-heartai-pe-kv-prod-aue-001"
    is_manual_connection = false
    private_connection_resource_id = azurerm_key_vault.keyvault.id
    subresource_names = [
      "vault"]
  }

  private_dns_zone_group {
    name = azurerm_private_dns_zone.keyvault_dns_private.name
    private_dns_zone_ids = [azurerm_private_dns_zone.keyvault_dns_private.id]
  }

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

data "azurerm_private_endpoint_connection" "keyvault_private_endpoint_connection" {
  depends_on = [
    azurerm_private_endpoint.keyvault_private_endpoint]
  name = azurerm_private_endpoint.keyvault_private_endpoint.name
  resource_group_name = azurerm_resource_group.rg_keyvault.name
}

resource "azurerm_private_dns_a_record" "keyvault_dns_a_record" {
  depends_on = [
    azurerm_key_vault.keyvault]
  name = lower(azurerm_key_vault.keyvault.name)
  zone_name = azurerm_private_dns_zone.keyvault_dns_private.name
  resource_group_name = azurerm_resource_group.rg.name
  ttl = 300
  records = [
    data.azurerm_private_endpoint_connection.keyvault_private_endpoint_connection.private_service_connection.0.private_ip_address]

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

resource "azurerm_private_dns_zone_virtual_network_link" "keyvault_dns_vnet_link" {
  name                  = "sah-heartai-keyvault-vnetlink-prod-aue-001"
  resource_group_name   = azurerm_resource_group.rg.name
  private_dns_zone_name = azurerm_private_dns_zone.keyvault_dns_private.name
  virtual_network_id    = azurerm_virtual_network.vnet.id

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

output keyvault_private_ip {
  value = data.azurerm_private_endpoint_connection.keyvault_private_endpoint_connection.private_service_connection.0.private_ip_address
}

Example: Azure Key Vault logging and monitoring

The following example shows Terraform declarations to manage resources for logging and monitoring of the HeartAI instance of Azure Key Vault. This implementation coordinates instances of the following Azure components:

Azure component Functionality for Azure Key Vault logging and monitoring
Storage Account Configures and deploys an Azure Storage Account assigned to a SystemAssigned service principal
Log Analytics Ingests data and provides observability
Monitor Ingests data and provides observability
Key Vault access policy Assigns an access policy to the SystemAssigned service principal
Key Vault key Enables data encryption .
Storage Account customer managed key Uses the above key for data encryption
Private Endpoint Provides network endpoint within Azure Private DNS zone
Private DNS zone A record Resolves network endpoint within Azure Private DNS zone
resource "azurerm_storage_account" "keyvault_logs_storage" {
  name = "sahheartaisakvaue001"
  resource_group_name = azurerm_resource_group.rg_keyvault.name
  location = azurerm_resource_group.rg_keyvault.location
  account_tier = "Standard"
  account_replication_type = "LRS"

  identity {
    type = "SystemAssigned"
  }

  network_rules {
    default_action = "Deny"
    bypass = [
      "AzureServices"]
  }

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

resource "azurerm_log_analytics_workspace" "keyvault_log_analytics" {
  name = "sah-heartai-la-kv-aue-001"
  resource_group_name = azurerm_resource_group.rg_keyvault.name
  location = azurerm_resource_group.rg_keyvault.location
  sku = "PerGB2018"
  retention_in_days = var.la-kv-aue-001-retention-in-days

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

resource "azurerm_monitor_diagnostic_setting" "keyvault_monitoring" {
  name = "sah-heartai-mnt-kv-aue-001"
  target_resource_id = azurerm_key_vault.keyvault.id
  storage_account_id = azurerm_storage_account.keyvault_logs_storage.id
  log_analytics_workspace_id = azurerm_log_analytics_workspace.keyvault_log_analytics.id

  log {
    category = "AuditEvent"
    enabled = true

    retention_policy {
      days = 0
      enabled = false
    }
  }

  metric {
    category = "AllMetrics"
    enabled = true

    retention_policy {
      days = 0
      enabled = false
    }
  }
}

resource "azurerm_key_vault_access_policy" "keyvault_access_policy_keyvault_logs_storage" {
  key_vault_id = azurerm_key_vault.keyvault.id
  tenant_id = data.azurerm_client_config.current.tenant_id
  object_id = azurerm_storage_account.keyvault_logs_storage.identity[0].principal_id

  key_permissions = [
    "Get",
    "Create",
    "List",
    "Restore",
    "Recover",
    "Unwrapkey",
    "Wrapkey",
    "Purge",
    "Encrypt",
    "Decrypt",
    "Sign",
    "Verify"]
  secret_permissions = [
    "Get"]
}

resource "azurerm_key_vault_key" "keyvault_logs_storage_key" {
  depends_on = [
    azurerm_key_vault_access_policy.keyvault_access_policy_keyvault_client,
    azurerm_key_vault_access_policy.keyvault_access_policy_keyvault_logs_storage
  ]

  name = "sah-heartai-kv-storage-key"
  key_vault_id = azurerm_key_vault.keyvault.id
  key_type = "RSA"
  key_size = 2048
  key_opts = [
    "decrypt",
    "encrypt",
    "sign",
    "unwrapKey",
    "verify",
    "wrapKey"]
}


resource "azurerm_storage_account_customer_managed_key" "keyvault_logs_storage_cmk" {
  storage_account_id = azurerm_storage_account.keyvault_logs_storage.id
  key_vault_id = azurerm_key_vault.keyvault.id
  key_name = azurerm_key_vault_key.keyvault_logs_storage_key.name
}

resource "azurerm_private_endpoint" "keyvault_logs_storage_private_endpoint" {
  depends_on = [
    azurerm_resource_group.rg,
    azurerm_virtual_network.vnet,
    azurerm_subnet.snet_paas,
    azurerm_storage_account.keyvault_logs_storage]
  name = "sah-heartai-pe-sa-kv-logs-prod-aue-001"
  location = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  subnet_id = azurerm_subnet.snet_paas.id

  private_service_connection {
    name = "sah-heartai-pe-sa-kv-logs-prod-aue-001"
    is_manual_connection = false
    private_connection_resource_id = azurerm_storage_account.keyvault_logs_storage.id
    subresource_names = [
      "blob"]
  }

  private_dns_zone_group {
    name = azurerm_private_dns_zone.azure_storage_blob_dns_private.name
    private_dns_zone_ids = [
      azurerm_private_dns_zone.azure_storage_blob_dns_private.id]
  }

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

data "azurerm_private_endpoint_connection" "keyvault_logs_storage_private_endpoint_connection" {
  depends_on = [
    azurerm_resource_group.rg,
    azurerm_private_endpoint.keyvault_logs_storage_private_endpoint]
  name = azurerm_private_endpoint.keyvault_logs_storage_private_endpoint.name
  resource_group_name = azurerm_resource_group.rg.name
}

resource "azurerm_private_dns_a_record" "keyvault_logs_storage_dns_a_record" {
  depends_on = [
    azurerm_resource_group.rg,
    azurerm_storage_account.keyvault_logs_storage,
    azurerm_private_dns_zone.azure_storage_blob_dns_private,
    data.azurerm_private_endpoint_connection.keyvault_logs_storage_private_endpoint_connection]
  name = lower(azurerm_storage_account.keyvault_logs_storage.name)
  zone_name = azurerm_private_dns_zone.azure_storage_blob_dns_private.name
  resource_group_name = azurerm_resource_group.rg.name
  ttl = 300
  records = [
    data.azurerm_private_endpoint_connection.keyvault_logs_storage_private_endpoint_connection.private_service_connection.0.private_ip_address]

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

output keyvault_logs_storage_private_ip {
  value = data.azurerm_private_endpoint_connection.keyvault_logs_storage_private_endpoint_connection.private_service_connection.0.private_ip_address
}

Example: Azure VPN Gateway

The following example shows Terraform declarations to deploy an instance of Azure VPN Gateway. This implementation coordinates instances of the following Azure components:

Azure component Functionality for Azure VPN Gateway
Key Vault certificate Root certificate for corresponding Azure VPN Gateway client
Public IP Allocates and associates a public IP address
VPN Gateway Configures and deploys Azure VPN Gateway
resource "azurerm_key_vault_certificate" "vgw_root_certificate" {
  name = "sah-heartai-vgw-root-cert-003"
  key_vault_id = azurerm_key_vault.keyvault.id

  certificate_policy {
    issuer_parameters {
      name = "Self"
    }

    key_properties {
      exportable = true
      key_size = 2048
      key_type = "RSA"
      reuse_key = true
    }

    lifetime_action {
      action {
        action_type = "AutoRenew"
      }

      trigger {
        days_before_expiry = 30
      }
    }

    secret_properties {
      content_type = "application/x-pkcs12"
    }

    x509_certificate_properties {
      extended_key_usage = [
        "1.3.6.1.5.5.7.3.1",
        "1.3.6.1.5.5.7.3.2"]

      key_usage = [
        "cRLSign",
        "dataEncipherment",
        "digitalSignature",
        "keyAgreement",
        "keyCertSign",
        "keyEncipherment",
      ]

      subject_alternative_names {
        dns_names = [
          "sah.heartai.net"]
      }

      subject = "CN=heartai-vpn-gateway"
      validity_in_months = 12
    }
  }
}

resource "azurerm_public_ip" "vpn_gateway_ip" {
  name = "sah-heartai-pip-vgw-prod-aue-001"
  location = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  allocation_method = "Dynamic"
}

resource "azurerm_virtual_network_gateway" "vpn_gateway" {
  name = "sah-heartai-vgw-prod-aue-001"
  location = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  type = "Vpn"
  vpn_type = "RouteBased"
  active_active = false
  enable_bgp = false
  sku = "VpnGw1"
  ip_configuration {
    name = "sah-heartai-vgw-ipconfig-prod-aue-001"
    public_ip_address_id = azurerm_public_ip.vpn_gateway_ip.id
    private_ip_address_allocation = "Dynamic"
    subnet_id = azurerm_subnet.snet_vpn_gateway.id
  }

  vpn_client_configuration {
    address_space = [
      var.heartai-prod-vgw-address-space]
    root_certificate {
      name = "VPNROOT"
      public_cert_data = azurerm_key_vault_certificate.vgw_root_certificate.certificate_data_base64
    }
  }
}

Example: Azure Database for PostgreSQL

The following example shows Terraform declarations to configure and deploy an instance of Azure Database for PostgreSQL. This implementation coordinates instances of the following Azure components:

Azure component Functionality for Azure Database for PostgreSQL
Private DNS Provides private name resolution for Azure Database for PostgreSQL network endpoints within the corresponding Private DNS zone
Azure Database for PostgreSQL Configures and deploys an instance of Azure Database for PostgreSQL
Virtual Network Link Exposes Azure Database for PostgreSQL network endpoints within the corresponding Azure Virtual Network
Private endpoint Provides network endpoint within the corresponding Azure Private DNS zone
Private DNS zone A record Resolves Azure Database for PostgreSQL network endpoints within the corresponding Azure Private DNS zone
Key Vault access policy Assigns an access policy to the Azure Database for PostgresSQL SystemAssigned service principal.
Key Vault key Enables data encryption .
PostgreSQL server key Uses the above key for data encryption
resource "azurerm_private_dns_zone" "postgresql_dns_private" {
  depends_on = [
    azurerm_resource_group.rg]
  name = "privatelink.postgres.database.azure.com"
  resource_group_name = azurerm_resource_group.rg.name

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

resource "azurerm_postgresql_server" "postgresql" {
  name = "sah-heartai-psql-prod-aue-001"
  location = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name

  administrator_login = var.postgres_admin_credentials_id
  administrator_login_password = var.postgres_admin_credentials_key

  sku_name = "GP_Gen5_2"
  version = "11"
  storage_mb = 51200

  backup_retention_days = var.postgres_backup_retention_days
  geo_redundant_backup_enabled = true
  auto_grow_enabled = true

  public_network_access_enabled = false
  ssl_enforcement_enabled = true
  ssl_minimal_tls_version_enforced = "TLS1_2"

  identity {
    type = "SystemAssigned"
  }

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

resource "azurerm_private_dns_zone_virtual_network_link" "postgresql_dns_vnet_link" {
  depends_on = [
    azurerm_resource_group.rg,
    azurerm_virtual_network.vnet,
    azurerm_private_dns_zone.postgresql_dns_private]
  name = "sah-heartai-psql-vnetlink-prod-aue-001"
  resource_group_name = azurerm_resource_group.rg.name
  private_dns_zone_name = azurerm_private_dns_zone.postgresql_dns_private.name
  virtual_network_id = azurerm_virtual_network.vnet.id
}

resource "azurerm_private_endpoint" "postgresql_private_endpoint" {
  depends_on = [
    azurerm_resource_group.rg,
    azurerm_virtual_network.vnet,
    azurerm_subnet.snet_paas,
    azurerm_postgresql_server.postgresql]
  name = "sah-heartai-pe-psql-prod-aue-001"
  location = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  subnet_id = azurerm_subnet.snet_paas.id

  private_service_connection {
    name = "sah-heartai-pe-psql-prod-aue-001"
    is_manual_connection = false
    private_connection_resource_id = azurerm_postgresql_server.postgresql.id
    subresource_names = [
      "postgresqlServer"]
  }

  private_dns_zone_group {
    name = azurerm_private_dns_zone.postgresql_dns_private.name
    private_dns_zone_ids = [
      azurerm_private_dns_zone.postgresql_dns_private.id]
  }

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

data "azurerm_private_endpoint_connection" "postgres_private_endpoint_connection" {
  depends_on = [
    azurerm_resource_group.rg,
    azurerm_private_endpoint.postgresql_private_endpoint]
  name = azurerm_private_endpoint.postgresql_private_endpoint.name
  resource_group_name = azurerm_resource_group.rg.name
}

resource "azurerm_private_dns_a_record" "postgresql_dns_a_record" {
  depends_on = [
    azurerm_resource_group.rg,
    azurerm_postgresql_server.postgresql,
    azurerm_private_dns_zone.postgresql_dns_private,
    data.azurerm_private_endpoint_connection.postgres_private_endpoint_connection]
  name = lower(azurerm_postgresql_server.postgresql.name)
  zone_name = azurerm_private_dns_zone.postgresql_dns_private.name
  resource_group_name = azurerm_resource_group.rg.name
  ttl = 300
  records = [
    data.azurerm_private_endpoint_connection.postgres_private_endpoint_connection.private_service_connection.0.private_ip_address]

  tags = {
    "Application Name" = var.heartai-environment.application-name
    "Application Owner" = var.heartai-environment.application-owner
    "Environment" = var.heartai-environment.environment
    "Division Department" = var.heartai-environment.division-department
    "Cost Centre" = var.heartai-environment.cost-centre
  }
}

resource "azurerm_key_vault_access_policy" "keyvault_access_policy_postgresql_server" {
  depends_on = [
    azurerm_key_vault.keyvault,
    data.azurerm_client_config.client,
    azurerm_postgresql_server.postgresql]
  key_vault_id = azurerm_key_vault.keyvault.id
  tenant_id = data.azurerm_client_config.current.tenant_id
  object_id = azurerm_postgresql_server.postgresql.identity[0].principal_id

  key_permissions = [
    "Get",
    "Unwrapkey",
    "Wrapkey"]
  secret_permissions = [
    "Get"]
}

resource "azurerm_key_vault_key" "postgresql_key" {
  depends_on = [
    azurerm_key_vault_access_policy.keyvault_access_policy_keyvault_client,
    azurerm_key_vault_access_policy.keyvault_access_policy_postgresql_server]

  name = "sah-heartai-psql-key"
  key_vault_id = azurerm_key_vault.keyvault.id
  key_type = "RSA"
  key_size = 2048
  key_opts = [
    "decrypt",
    "encrypt",
    "sign",
    "unwrapKey",
    "verify",
    "wrapKey"]
}

resource "azurerm_postgresql_server_key" "postgresql_key" {
  depends_on = [
    azurerm_postgresql_server.postgresql,
    azurerm_key_vault_key.postgresql_key]
  server_id = azurerm_postgresql_server.postgresql.id
  key_vault_key_id = azurerm_key_vault_key.postgresql_key.id
}

Example: PostgreSQL database and users

The following example shows Terraform declarations to provision and reference a database and users of a corresponding PostgreSQL instance. This implementation coordinates instances of the following PostgreSQL components:

PostgreSQL component Functionality for PostgreSQL
Provider References an instance of PostgreSQL
Role Creates PostgreSQL identity principal and assigns secure password
Database Creates PostgreSQL database
Default privileges Associates permissions to PostgreSQL database
//provider "postgresql" {
//  host = azurerm_private_dns_a_record.postgresql_dns_a_record.fqdn
//  port = 5432
//  username = var.postgres_admin_credentials_id
//  password = var.postgres_admin_credentials_key
//  sslmode = "require"
//  connect_timeout = 30
//  superuser = false
//}
//
//variable "hello_world_prod_database_name" {
//  type = string
//  default = "hello_world_prod"
//}
//
//resource "random_id" "hello_world_prod_password_admin" {
//  byte_length = var.hello_world_prod_password_byte_length
//}
//
//resource "random_id" "hello_world_prod_password_user" {
//  byte_length = var.hello_world_prod_password_byte_length
//}
//
//resource "postgresql_role" "hello_world_prod_admin" {
//  name = "${var.hello_world_prod_database_name}_admin"
//  password = random_id.hello_world_prod_password_admin.hex
//  login = true
//  create_database = "false"
//}
//
//resource "postgresql_role" "hello_world_prod_user" {
//  name = "${var.hello_world_prod_database_name}_user"
//  password = random_id.hello_world_prod_password_user.hex
//  login = true
//  create_database = "false"
//}
//
//resource "postgresql_database" "hello_world_prod_database" {
//  name = var.hello_world_prod_database_name
//  owner = var.postgres_admin_credentials_id
//  lc_collate = "en_US.UTF-8"
//  lc_ctype = "en_US.UTF-8"
//  encoding = "UTF8"
//}
//
//resource "postgresql_default_privileges" "hello_world_prod_table" {
//  depends_on = [
//    postgresql_database.hello_world_prod_database,
//    postgresql_role.hello_world_prod_admin,
//    postgresql_role.hello_world_prod_user]
//  database = var.hello_world_prod_database_name
//  owner = "${var.hello_world_prod_database_name}_admin"
//  role = "${var.hello_world_prod_database_name}_user"
//  schema = "public"
//  object_type = "table"
//  privileges = [
//    "ALL"]
//}
//
//output "hello_world_prod_database_admin_key" {
//  sensitive = true
//  value = random_id.hello_world_prod_password_admin.hex
//}
//
//output "hello_world_prod_database_user_key" {
//  sensitive = true
//  value = random_id.hello_world_prod_password_user.hex
//}