This is third part of the script and little bit improvement and 2 separate logics I have added to the script. It is modification of earlier written part Creating a Private Endpoint for Azure Storage Account with Terraform example 2. In the script I wanted to create multiple endpoint for sub resource based on input in Storage account kind, tier and replication type. Below are the output of the tf configuration after deployment. I can do the deployment with below 2 examples.
terraform apply --auto-approve data.azurerm_subscription.subscriptioninfo: Reading... data.azurerm_resource_group.rginfo: Reading... data.azurerm_resource_group.rginfo: Read complete after 1s [id=/subscriptions/9e22xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/vcloud-lab.com] data.azurerm_subscription.subscriptioninfo: Read complete after 1s [id=/subscriptions/9e22xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx] data.azurerm_virtual_network.vnetinfo: Reading... data.azurerm_virtual_network.vnetinfo: Read complete after 0s [id=/subscriptions/9e22xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/vcloud-lab.com/providers/Microsoft.Network/virtualNetworks/vcloud_lab_global_vnet01] data.azurerm_subnet.subnetinfo: Reading... data.azurerm_subnet.subnetinfo: Read complete after 1s [id=/subscriptions/9e22xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/vcloud-lab.com/providers/Microsoft.Network/virtualNetworks/vcloud_lab_global_vnet01/subnets/default] Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # azurerm_private_endpoint.private_endpoint["blob"] will be created + resource "azurerm_private_endpoint" "private_endpoint" { + custom_dns_configs = (known after apply) + id = (known after apply) + location = "eastus" + name = "vcloudlabsa-blob" + network_interface = (known after apply) + private_dns_zone_configs = (known after apply) + resource_group_name = "vcloud-lab.com" + subnet_id = "/subscriptions/9e22xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/vcloud-lab.com/providers/Microsoft.Network/virtualNetworks/vcloud_lab_global_vnet01/subnets/default" + tags = { + "name" = "test" } + private_dns_zone_group { + id = (known after apply) + name = "vcloudlabsa-blob-dnszonegroup" + private_dns_zone_ids = [ + "/subscriptions/9e22xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/vcloud-lab.com/providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net", ] } + private_service_connection { + is_manual_connection = false + name = "vcloudlabsa-blob" + private_connection_resource_id = (known after apply) + private_ip_address = (known after apply) + subresource_names = [ + "blob", ] } } # azurerm_private_endpoint.private_endpoint["web"] will be created + resource "azurerm_private_endpoint" "private_endpoint" { + custom_dns_configs = (known after apply) + id = (known after apply) + location = "eastus" + name = "vcloudlabsa-web" + network_interface = (known after apply) + private_dns_zone_configs = (known after apply) + resource_group_name = "vcloud-lab.com" + subnet_id = "/subscriptions/9e22xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/vcloud-lab.com/providers/Microsoft.Network/virtualNetworks/vcloud_lab_global_vnet01/subnets/default" + tags = { + "name" = "test" } + private_dns_zone_group { + id = (known after apply) + name = "vcloudlabsa-web-dnszonegroup" + private_dns_zone_ids = [ + "/subscriptions/9e22xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/vcloud-lab.com/providers/Microsoft.Network/privateDnsZones/privatelink.web.core.windows.net", ] } + private_service_connection { + is_manual_connection = false + name = "vcloudlabsa-web" + private_connection_resource_id = (known after apply) + private_ip_address = (known after apply) + subresource_names = [ + "web", ] } } # azurerm_storage_account.storageaccount will be created + resource "azurerm_storage_account" "storageaccount" { + access_tier = (known after apply) + account_kind = "StorageV2" + account_replication_type = "LRS" + account_tier = "Premium" + allow_nested_items_to_be_public = true + cross_tenant_replication_enabled = true + default_to_oauth_authentication = false + dns_endpoint_type = "Standard" + enable_https_traffic_only = true + id = (known after apply) + infrastructure_encryption_enabled = false + is_hns_enabled = false + large_file_share_enabled = (known after apply) + local_user_enabled = true + location = "eastus" + min_tls_version = "TLS1_2" + name = "vcloudlabsa" + nfsv3_enabled = false + primary_access_key = (sensitive value) + primary_blob_connection_string = (sensitive value) + primary_blob_endpoint = (known after apply) + primary_blob_host = (known after apply) + primary_blob_internet_endpoint = (known after apply) + primary_blob_internet_host = (known after apply) + primary_blob_microsoft_endpoint = (known after apply) + primary_blob_microsoft_host = (known after apply) + primary_connection_string = (sensitive value) + primary_dfs_endpoint = (known after apply) + primary_dfs_host = (known after apply) + primary_dfs_internet_endpoint = (known after apply) + primary_dfs_internet_host = (known after apply) + primary_dfs_microsoft_endpoint = (known after apply) + primary_dfs_microsoft_host = (known after apply) + primary_file_endpoint = (known after apply) + primary_file_host = (known after apply) + primary_file_internet_endpoint = (known after apply) + primary_file_internet_host = (known after apply) + primary_file_microsoft_endpoint = (known after apply) + primary_file_microsoft_host = (known after apply) + primary_location = (known after apply) + primary_queue_endpoint = (known after apply) + primary_queue_host = (known after apply) + primary_queue_microsoft_endpoint = (known after apply) + primary_queue_microsoft_host = (known after apply) + primary_table_endpoint = (known after apply) + primary_table_host = (known after apply) + primary_table_microsoft_endpoint = (known after apply) + primary_table_microsoft_host = (known after apply) + primary_web_endpoint = (known after apply) + primary_web_host = (known after apply) + primary_web_internet_endpoint = (known after apply) + primary_web_internet_host = (known after apply) + primary_web_microsoft_endpoint = (known after apply) + primary_web_microsoft_host = (known after apply) + public_network_access_enabled = false + queue_encryption_key_type = "Service" + resource_group_name = "vcloud-lab.com" + secondary_access_key = (sensitive value) + secondary_blob_connection_string = (sensitive value) + secondary_blob_endpoint = (known after apply) + secondary_blob_host = (known after apply) + secondary_blob_internet_endpoint = (known after apply) + secondary_blob_internet_host = (known after apply) + secondary_blob_microsoft_endpoint = (known after apply) + secondary_blob_microsoft_host = (known after apply) + secondary_connection_string = (sensitive value) + secondary_dfs_endpoint = (known after apply) + secondary_dfs_host = (known after apply) + secondary_dfs_internet_endpoint = (known after apply) + secondary_dfs_internet_host = (known after apply) + secondary_dfs_microsoft_endpoint = (known after apply) + secondary_dfs_microsoft_host = (known after apply) + secondary_file_endpoint = (known after apply) + secondary_file_host = (known after apply) + secondary_file_internet_endpoint = (known after apply) + secondary_file_internet_host = (known after apply) + secondary_file_microsoft_endpoint = (known after apply) + secondary_file_microsoft_host = (known after apply) + secondary_location = (known after apply) + secondary_queue_endpoint = (known after apply) + secondary_queue_host = (known after apply) + secondary_queue_microsoft_endpoint = (known after apply) + secondary_queue_microsoft_host = (known after apply) + secondary_table_endpoint = (known after apply) + secondary_table_host = (known after apply) + secondary_table_microsoft_endpoint = (known after apply) + secondary_table_microsoft_host = (known after apply) + secondary_web_endpoint = (known after apply) + secondary_web_host = (known after apply) + secondary_web_internet_endpoint = (known after apply) + secondary_web_internet_host = (known after apply) + secondary_web_microsoft_endpoint = (known after apply) + secondary_web_microsoft_host = (known after apply) + sftp_enabled = false + shared_access_key_enabled = true + table_encryption_key_type = "Service" + blob_properties (known after apply) + network_rules (known after apply) + queue_properties (known after apply) + routing (known after apply) + share_properties (known after apply) } Plan: 3 to add, 0 to change, 0 to destroy. azurerm_storage_account.storageaccount: Creating... azurerm_storage_account.storageaccount: Still creating... [10s elapsed] azurerm_storage_account.storageaccount: Still creating... [20s elapsed] azurerm_storage_account.storageaccount: Still creating... [30s elapsed] azurerm_storage_account.storageaccount: Still creating... [40s elapsed] azurerm_storage_account.storageaccount: Creation complete after 49s [id=/subscriptions/9e22xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/vcloud-lab.com/providers/Microsoft.Storage/storageAccounts/vcloudlabsa] azurerm_private_endpoint.private_endpoint["blob"]: Creating... azurerm_private_endpoint.private_endpoint["web"]: Creating... azurerm_private_endpoint.private_endpoint["web"]: Still creating... [10s elapsed] azurerm_private_endpoint.private_endpoint["blob"]: Still creating... [10s elapsed] azurerm_private_endpoint.private_endpoint["blob"]: Still creating... [20s elapsed] azurerm_private_endpoint.private_endpoint["web"]: Still creating... [20s elapsed] azurerm_private_endpoint.private_endpoint["web"]: Still creating... [30s elapsed] azurerm_private_endpoint.private_endpoint["blob"]: Still creating... [30s elapsed] azurerm_private_endpoint.private_endpoint["blob"]: Still creating... [40s elapsed] azurerm_private_endpoint.private_endpoint["web"]: Still creating... [40s elapsed] azurerm_private_endpoint.private_endpoint["web"]: Still creating... [50s elapsed] azurerm_private_endpoint.private_endpoint["blob"]: Still creating... [50s elapsed] azurerm_private_endpoint.private_endpoint["web"]: Still creating... [1m0s elapsed] azurerm_private_endpoint.private_endpoint["blob"]: Still creating... [1m0s elapsed] azurerm_private_endpoint.private_endpoint["web"]: Creation complete after 1m1s [id=/subscriptions/9e22xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/vcloud-lab.com/providers/Microsoft.Network/privateEndpoints/vcloudlabsa-web] azurerm_private_endpoint.private_endpoint["blob"]: Creation complete after 1m1s [id=/subscriptions/9e22xxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/vcloud-lab.com/providers/Microsoft.Network/privateEndpoints/vcloudlabsa-blob] Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
In the below example I mentioned my endpoint sub resources structure in locals. Different sub resources for different combination of SA kind, tier and replication type. Based on that it will create Private endpoint for either non read only or read only replication types. In this condition it will deploy multiple Private Endpoint resources from different AzureRM Private Endpoint blocks.
Example 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
provider "azurerm" { features {} } #################################################### ## variables #################################################### variable "prefix" { type = string description = "value" default = "vcloudlab" } variable "storage_account_name_override" { type = string description = "value" default = "" } variable "storage_account_name" { type = string description = "value" default = "sa" } variable "account_tier" { type = string description = "value" default = "Premium" } variable "account_kind" { type = string description = "value" default = "StorageV2" #["BlobStorage" "BlockBlobStorage" "FileStorage" "Storage" "StorageV2"] } variable "account_replication_type" { type = string description = "value" default = "LRS" } variable "tags" { type = map(any) description = "value" default = { name = "test" } } variable "resource_group_name" { type = string default = "vcloud-lab.com" description = "value" } variable "virtual_network_name" { type = string default = "vcloud_lab_global_vnet01" description = "value" } variable "subnet_name" { type = string default = "default" description = "value" } #################################################### ## data #################################################### data "azurerm_subscription" "subscriptioninfo" {} data "azurerm_resource_group" "rginfo" { name = var.resource_group_name } data "azurerm_virtual_network" "vnetinfo" { name = var.virtual_network_name resource_group_name = data.azurerm_resource_group.rginfo.name } data "azurerm_subnet" "subnetinfo" { name = var.subnet_name resource_group_name = data.azurerm_resource_group.rginfo.name virtual_network_name = data.azurerm_virtual_network.vnetinfo.name } #################################################### ## local variable #################################################### locals { account_name = var.storage_account_name_override != "" ? var.storage_account_name_override : "${var.prefix}${var.storage_account_name}" # characters: 3-24 characters [lowercase letters and numbers] private_service_connections = { standardstoragev2 = ["blob", "file", "queue", "table", "web", "dfs"] premiumstoragev2 = ["blob", "web"] premiumfilestorage = ["file"] } private_service_connections_ra = { standardstoragev2 = ["blob_secondary", "table_secondary", "web_secondary", "dfs_secondary"] #we can only put blob, table, web, dfs } selected_private_endpoint = lookup(local.private_service_connections, lower("${var.account_tier}${var.account_kind}"), []) selected_private_endpoint_ra = startswith(lower(var.account_replication_type), "RA") ? lookup(local.private_service_connections_ra, lower("${var.account_tier}${var.account_kind}"), []) : [] } #################################################### ## Storage Account resource #################################################### resource "azurerm_storage_account" "storageaccount" { name = lower(local.account_name) resource_group_name = data.azurerm_resource_group.rginfo.name location = data.azurerm_resource_group.rginfo.location account_kind = var.account_kind account_tier = var.account_tier account_replication_type = var.account_replication_type public_network_access_enabled = false } #################################################### ## Private Endpoint resource #################################################### resource "azurerm_private_endpoint" "private_endpoint" { for_each = toset(local.selected_private_endpoint) name = "${local.account_name}-${each.key}" location = data.azurerm_resource_group.rginfo.location resource_group_name = data.azurerm_resource_group.rginfo.name subnet_id = data.azurerm_subnet.subnetinfo.id private_service_connection { name = "${local.account_name}-${each.value}" private_connection_resource_id = resource.azurerm_storage_account.storageaccount.id subresource_names = [each.key] is_manual_connection = false } private_dns_zone_group { name = "${local.account_name}-${each.key}-dnszonegroup" private_dns_zone_ids = ["/subscriptions/${data.azurerm_subscription.subscriptioninfo.subscription_id}/resourceGroups/${data.azurerm_resource_group.rginfo.name}/providers/Microsoft.Network/privateDnsZones/privatelink.${each.value}.core.windows.net"] } tags = var.tags } resource "azurerm_private_endpoint" "private_endpoint_ra" { for_each = toset(local.selected_private_endpoint_ra) name = "${local.account_name}-${each.key}" location = data.azurerm_resource_group.rginfo.location resource_group_name = data.azurerm_resource_group.rginfo.name subnet_id = data.azurerm_subnet.subnetinfo.id private_service_connection { name = "${local.account_name}-${each.value}" private_connection_resource_id = azurerm_storage_account.storageaccount.id subresource_names = [each.key] is_manual_connection = false } private_dns_zone_group { name = "${local.account_name}-${each.key}-dnszonegroup" private_dns_zone_ids = ["/subscriptions/${data.azurerm_subscription.subscriptioninfo.subscription_id}/resourceGroups/${data.azurerm_resource_group.rginfo.name}/providers/Microsoft.Network/privateDnsZones/privatelink.${trimsuffix(each.value), "_secondary"}.core.windows.net"] } tags = var.tags } |
In below second example it is implementation of old code, All the logic is happening in the Variables and Locals block, and using only single Azure Private Endpoint block unlike example 1 to deploy Storage Account and Private Endpoints.
Example 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
variable "resource_group_name" { type = string default = "vcloud-lab.com" description = "value" } variable "virtual_network_name" { type = string default = "vcloud_lab_global_vnet01" description = "value" } variable "subnet_name" { type = string default = "default" description = "value" } variable "storage_account_name" { type = string default = "vcloudlabsademo01" description = "value" } variable "storage_account_tier" { type = string default = "Standard" #Standard,Premium | (For Premium only BlockBlobStorage And FileStorage) description = "value" } variable "storage_account_kind" { type = string default = "StorageV2" #BlobStorage,BlockBlobStorage,FileStorage,Storage,StorageV2 | (default: StorageV2) description = "value" } variable "storage_account_replication_type" { type = string default = "LRS" #"LRS" "ZRS" "GRS" "RAGRS" "GZRS" "RAGZRS" | Default: description = "value" } variable "private_endpoint_name" { type = string default = "vcloud-lab-endpoint" description = "value" } variable "private_service_connection_name" { type = string default = "privateendpointserviceconnection" description = "value" } variable "private_dns_zone_group_name" { type = string default = "privateendpointdnzzonegroup" description = "value" } variable "private_service_connections" { description = "A map of DNS records to create based on the storage account kind" type = map(any) default = { standardstoragev2 = ["blob", "file"] premiumstoragev2 = ["file"] blobstorage = ["blob"] ragrsstandardstoragev2 = ["blob"] } } terraform { required_providers { azurerm = { source = "hashicorp/azurerm" #version = "=2.91.0" } } } # Configure the Microsoft Azure Provider provider "azurerm" { features {} } data "azurerm_subscription" "subscriptioninfo" {} data "azurerm_resource_group" "rginfo" { name = var.resource_group_name } data "azurerm_virtual_network" "vnetinfo" { name = var.virtual_network_name resource_group_name = data.azurerm_resource_group.rginfo.name } data "azurerm_subnet" "subnetinfo" { name = var.subnet_name resource_group_name = data.azurerm_resource_group.rginfo.name virtual_network_name = data.azurerm_virtual_network.vnetinfo.name } resource "azurerm_storage_account" "storageaccount" { name = var.storage_account_name resource_group_name = data.azurerm_resource_group.rginfo.name location = data.azurerm_resource_group.rginfo.location account_kind = var.storage_account_kind account_tier = var.storage_account_tier account_replication_type = var.storage_account_replication_type public_network_access_enabled = false } locals { non_read_replication_types = ["lrs", "grs", "zrs"] private_endpoint_prefix_name = contains(local.non_read_replication_types, lower(var.storage_account_replication_type)) ? "" : var.storage_account_replication_type selected_private_endpoint = lookup(var.private_service_connections, lower("${local.private_endpoint_prefix_name}${var.storage_account_tier}${var.storage_account_kind}"), []) } resource "azurerm_private_endpoint" "privateendpoint" { for_each = toset(local.selected_private_endpoint) #{ for ep, connection in local.selected_private_endpoint : ep => ep } # ep => connection name = "${var.private_endpoint_name}-${each.key}" resource_group_name = data.azurerm_resource_group.rginfo.name location = data.azurerm_resource_group.rginfo.location subnet_id = data.azurerm_subnet.subnetinfo.id custom_network_interface_name = "${var.private_endpoint_name}-${each.value}-nic" private_service_connection { name = "${var.private_service_connection_name}-${each.value}" private_connection_resource_id = resource.azurerm_storage_account.storageaccount.id subresource_names = [each.value] is_manual_connection = false } private_dns_zone_group { name = var.private_dns_zone_group_name private_dns_zone_ids = ["/subscriptions/${data.azurerm_subscription.subscriptioninfo.subscription_id}/resourceGroups/${data.azurerm_resource_group.rginfo.name}/providers/Microsoft.Network/privateDnsZones/privatelink.${each.value}.core.windows.net"] } } |
Download this Terraform_Storage_Account_Private_Endpoints here or it is also available on github.com.
Useful Articles
Terraform clone virtual machine template in VMware vSphere vCenter from CSV file
Terraform error retrieving storage account failure responding to request StatusCode 404 StorageAccountNotFound The storage account was not found
Terraform testing local variables and output csv file without resource Part 1
Terraform testing variable map object values without resource configuration part 2
Terraform foreach module output to show only required results
Terraform deploy create A Private DNS Record in Microsoft Azure from list of objects
Terraform clone virtual machine template in VMware vSphere vCenter Dynamic Content Part 2
Creating a Private Endpoint for Azure Storage Account with required sub services using Terraform
Terraform Azure Create Private Endpoint to existing Storage Account with Custom Private DNS zone record link
Using terraform to clone a virtual machine on VMware vSphere infrastructure
Terraform module clone VMware vSphere Linux and Windows virtual machine
Terraform VMware vSphere Virtual Machine customization clone failed on Windows
Terraform VMware vSphere Virtual Machine cloning Operating system not found