Menu

Virtual Geek

Tales from real IT system administrators world and non-production environment

Terraform Azure Create Private Endpoint to existing Storage Account with Custom Private DNS zone record link

I had a task to create Private Endpoint in Microsoft Azure and was requirement to automate this job using HashiCorp Terraform automation tf configuration files. This Private endpoint will be linked to existing Storage Account and Virtual Network. Other required sub resources Virtual Network Links and other connection and Private DNS zone A record will be created in custom Private DNS zone.

Microsoft Azure Storage Account Private Endpoint virtual network links virtual network subnet nsg Resource group Private DNS zone blob virtual machine.png

Related Articles Creating a Private Endpoint for Azure Storage Account with required sub resources using Terraform

This is the output after applying terraform configuration. It fetches and register data of existing Resource Group, Private DNS zone, Virtual Network, Subnet, Storage Account. These resource are already present on Azure cloud. After using data it configures new environment Private Endpoint and related resources.

 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
terraform apply --auto-approve

data.azurerm_resource_group.rginfo: Reading...
data.azurerm_resource_group.rginfo: Read complete after 0s [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/vcloud-lab.com]
data.azurerm_private_dns_zone.privatednszoneinfo: Reading...
data.azurerm_virtual_network.vnetinfo: Reading...
data.azurerm_storage_account.storageaccountinfo: Reading...
data.azurerm_private_dns_zone.privatednszoneinfo: Read complete after 0s [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/vcloud-lab.com/providers/Microsoft.Network/privateDnsZones/vcloud-lab.com]
data.azurerm_virtual_network.vnetinfo: Read complete after 1s [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/vcloud-lab.com/providers/Microsoft.Network/virtualNetworks/vcloud_lab_global_vnet01]
data.azurerm_subnet.subnetinfo: Reading...
data.azurerm_storage_account.storageaccountinfo: Read complete after 1s [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/vcloud-lab.com/providers/Microsoft.Storage/storageAccounts/vcloudlabdemo01]
data.azurerm_subnet.subnetinfo: Read complete after 0s [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/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_dns_a_record.private_dns_a_record will be created
  + resource "azurerm_private_dns_a_record" "private_dns_a_record" {
      + fqdn                = (known after apply)
      + id                  = (known after apply)
      + name                = "vcloudlabdemo01"
      + records             = (known after apply)
      + resource_group_name = "vcloud-lab.com"
      + ttl                 = 300
      + zone_name           = "vcloud-lab.com"
    }

  # azurerm_private_dns_zone_virtual_network_link.networklink will be created
  + resource "azurerm_private_dns_zone_virtual_network_link" "networklink" {
      + id                    = (known after apply)
      + name                  = "privatednsnetworklink"
      + private_dns_zone_name = "vcloud-lab.com"
      + registration_enabled  = false
      + resource_group_name   = "vcloud-lab.com"
      + virtual_network_id    = "/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/vcloud-lab.com/providers/Microsoft.Network/virtualNetworks/vcloud_lab_global_vnet01"
    }

  # azurerm_private_endpoint.privateendpoint will be created
  + resource "azurerm_private_endpoint" "privateendpoint" {
      + custom_dns_configs       = (known after apply)
      + id                       = (known after apply)
      + location                 = "eastus"
      + name                     = "vcloud-lab-endpoint"
      + network_interface        = (known after apply)
      + private_dns_zone_configs = (known after apply)
      + resource_group_name      = "vcloud-lab.com"
      + subnet_id                = "/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/vcloud-lab.com/providers/Microsoft.Network/virtualNetworks/vcloud_lab_global_vnet01/subnets/default"

      + private_dns_zone_group {
          + id                   = (known after apply)
          + name                 = "privateendpointdnzzonegroup"
          + private_dns_zone_ids = [
              + "/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/vcloud-lab.com/providers/Microsoft.Network/privateDnsZones/vcloud-lab.com",
            ]
        }

      + private_service_connection {
          + is_manual_connection           = false
          + name                           = "privateendpointserviceconnection"
              + "blob",
            ]
        }
    }

Plan: 3 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + name = (known after apply)
azurerm_private_dns_zone_virtual_network_link.networklink: Creating...
azurerm_private_endpoint.privateendpoint: Creating...
azurerm_private_endpoint.privateendpoint: Still creating... [10s elapsed]
azurerm_private_dns_zone_virtual_network_link.networklink: Still creating... [10s elapsed]
azurerm_private_endpoint.privateendpoint: Still creating... [20s elapsed]
azurerm_private_dns_zone_virtual_network_link.networklink: Still creating... [20s elapsed]
azurerm_private_dns_zone_virtual_network_link.networklink: Still creating... [30s elapsed]
azurerm_private_endpoint.privateendpoint: Still creating... [30s elapsed]
azurerm_private_dns_zone_virtual_network_link.networklink: Still creating... [40s elapsed]
azurerm_private_endpoint.privateendpoint: Still creating... [40s elapsed]
azurerm_private_endpoint.privateendpoint: Still creating... [50s elapsed]
azurerm_private_dns_zone_virtual_network_link.networklink: Still creating... [50s elapsed]
azurerm_private_endpoint.privateendpoint: Creation complete after 59s [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/vcloud-lab.com/providers/Microsoft.Network/privateEndpoints/vcloud-lab-endpoint]
azurerm_private_dns_a_record.private_dns_a_record: Creating...
azurerm_private_dns_zone_virtual_network_link.networklink: Still creating... [1m0s elapsed]
azurerm_private_dns_a_record.private_dns_a_record: Creation complete after 3s [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/vcloud-lab.com/providers/Microsoft.Network/privateDnsZones/vcloud-lab.com/A/vcloudlabdemo01]
azurerm_private_dns_zone_virtual_network_link.networklink: Creation complete after 1m6s [id=/subscriptions/9e22fba3-00a9-447c-b954-a26fec38e029/resourceGroups/vcloud-lab.com/providers/Microsoft.Network/privateDnsZones/vcloud-lab.com/virtualNetworkLinks/privatednsnetworklink]

Apply complete! Resources: 3 added, 0 changed, 0 destroyed.

Outputs:

name = "10.0.0.4"

Once Terraform Apply is completed successfully, I can confirm and verify, resources are deployed successfully in the Resource Group with Private Endpoint and its associated network interface.

Microsoft azure private endpoint network interface private dns zone group virtual network subnet storage account blob file table queue privatelink blob core windows net resource group storagev2 block page global.png

Next if I deep dive into Private Endpoint DNS configuration, I see Custom DNS zone group and Customer Visible FQDNs are integrated and created successfully

Microsoft Private Endpoint DNS configuration Application security groups private dns integration Customer visible fqdn storage account Custom dns records blob.core.windows.net no internet public service endpoint.png

In the existing Storage Account section Private endpoint connections, I can see connection state is approved and created with connected Virtual Network.

Microsoft Storage account blob connection state private endpoint firewalls and virtual networks custom domain networking fornt door and CDN access keys .png

Next in the Private DNS zone service, under DNS Management >> Recordsets required DNS A record is created and Virtual Network Links is created with selected vNet.

Microsoft Azure recordsets alias a record ptr private dns zone virtual network links virtual network subnet link status Auto registration locs properties settings IAM access control activity log @.png

Download this terraform configuration file main.tf or it is also available on github.com.

 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
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      #version = "=2.91.0"
    }
  }
}

# Configure the Microsoft Azure Provider
provider "azurerm" {
  features {}
}

data "azurerm_resource_group" "rginfo" {
  name                = "vcloud-lab.com"
}

data "azurerm_virtual_network" "vnetinfo" {
  name                = "vcloud_lab_global_vnet01"
  resource_group_name = data.azurerm_resource_group.rginfo.name
}

data "azurerm_subnet" "subnetinfo" {
  name                 = "default"
  resource_group_name  = data.azurerm_resource_group.rginfo.name
  virtual_network_name = data.azurerm_virtual_network.vnetinfo.name
}

data "azurerm_private_dns_zone" "privatednszoneinfo" {
  name                = "vcloud-lab.com"
  resource_group_name = data.azurerm_resource_group.rginfo.name
}

data "azurerm_storage_account" "storageaccountinfo" {
  name                = "vcloudlabdemo01"
  resource_group_name = data.azurerm_resource_group.rginfo.name
}

resource "azurerm_private_endpoint" "privateendpoint" {
  name                = "vcloud-lab-endpoint"
  resource_group_name = data.azurerm_resource_group.rginfo.name
  location            = data.azurerm_resource_group.rginfo.location
  subnet_id           = data.azurerm_subnet.subnetinfo.id

  private_service_connection {
    name                           = "privateendpointserviceconnection"
    private_connection_resource_id = data.azurerm_storage_account.storageaccountinfo.id
    subresource_names              = ["blob"]
    is_manual_connection           = false
  }

  private_dns_zone_group {
    name                 = "privateendpointdnzzonegroup"
    private_dns_zone_ids = [data.azurerm_private_dns_zone.privatednszoneinfo.id]
  }
}

resource "azurerm_private_dns_zone_virtual_network_link" "networklink" {
  name                  = "privatednsnetworklink"
  resource_group_name   = data.azurerm_resource_group.rginfo.name
  private_dns_zone_name = data.azurerm_private_dns_zone.privatednszoneinfo.name
  virtual_network_id    = data.azurerm_virtual_network.vnetinfo.id
}

resource "azurerm_private_dns_a_record" "private_dns_a_record" {
  name                = data.azurerm_storage_account.storageaccountinfo.name
  zone_name           = data.azurerm_private_dns_zone.privatednszoneinfo.name
  resource_group_name = data.azurerm_resource_group.rginfo.name
  ttl                 = 300
  records             = [resource.azurerm_private_endpoint.privateendpoint.private_service_connection[0].private_ip_address]
}

output "name" {
  value = resource.azurerm_private_endpoint.privateendpoint.private_service_connection[0].private_ip_address
}

Useful Articles
Hashicorp Terraform map and object inside module and variable example
Terraform one module deploy null or multiple resources based on input
Terraform A reference to a resource type must be followed by at least one attribute access, specifying the resource name
Terraform fore_each for loop filter with if condition example
Terraform remote-exec provisioner with ssh connection in null_resource
Terraform count vs for_each for examples with map of objects
Terraform one module deploy null or multiple resources based on input (nested for loop) Example of flatten and coalesce
Using element function with count meta argument example Terraform Azure subnets

Go Back

Comment

Blog Search

Page Views

12176570

Follow me on Blogarama