SHIFT-WIKI

--- Sjoerd Hooft's InFormation Technology ---

User Tools

Site Tools


terraformmoduleprivateendpoint

Terraform Module for a Private Endpoint

Summary: This is a terraform module that I use to deploy a private endpoint for resources in Azure.
Date: 8 February 2025

Read the post to learn more about private endpoints and:

  • How to depoloy a private endpoint using a terraform module
    • Notice how we can provide the nic for the private endpoint with a custom name
  • How we can assign an ip address to the private endpoint

About Private Endpoints

Private endpoints are a way to connect to a resource in Azure privately. This means that the resource is not exposed to the public internet. Instead, the resource is connected to a virtual network and can only be accessed from within that network. To accomplish this, a private endpoint is assigned a network interface card (NIC) that is connected to the virtual network. The network card gets assigned an IP address and a DNS name that can be used to connect to the resource. The private endpoint is connected to the resource.

Note the following tips should you start working with private endpoints:

  • Not all azure resources support private endpoints
  • Assigning a private endpoint to a resource does not automatically make the resource private. You need to configure the resource to only accept traffic from the private endpoint.

Terraform Module for a Private Endpoint

The module for the Private Endpoint is defined over three files:

  • main.tf: Contains the resources for the private endpoint
  • outputs.tf: Contains the output of the private endpoint
  • variables.tf: Contains the input variables for the private endpoint

main.tf

Notice the following:

  • The custom_network_interface_name is used to set a custom name for the network interface card. This option came available only recently.
  • The private_connection_resource_id is the resource id of the resource that the private endpoint is connected to.
  • The subresource_names to use is defined by microsoft. You can look them up here
  • The private dns zone group name can be defined by your own naming conventions. The DNS zone group has a strong association between the private DNS zone and the private endpoint. It helps with managing the private DNS zone records when there's an update on the private endpoint. See here for more information.
main.tf
resource "azurerm_private_endpoint" "private_endpoint" {
  name                          = var.name
  location                      = var.location
  resource_group_name           = var.resource_group_name
  subnet_id                     = var.subnet_id
  tags                          = var.tags
  custom_network_interface_name = "nic-${var.name}"
 
  private_service_connection {
    name                           = "${var.name}-serviceconnection"
    private_connection_resource_id = var.private_connection_resource_id
    is_manual_connection           = var.is_manual_connection
    subresource_names              = try([var.subresource_name], null)
    request_message                = try(var.request_message, null)
  }
 
  private_dns_zone_group {
    name                 = var.private_dns_zone_group_name
    private_dns_zone_ids = var.private_dns_zone_group_ids
  }
 
  dynamic "ip_configuration" {
    for_each = { for i, ip_config in var.ip_configurations : ip_config.private_ip_address => { index = i, member_name = ip_config.member_name } }
 
    content {
      name               = "${var.name}-ipconfig-${ip_configuration.value.index}"
      private_ip_address = ip_configuration.key
      subresource_name   = var.subresource_name
      member_name        = ip_configuration.value.member_name
    }
  }
 
  lifecycle {
    ignore_changes = [
    ]
  }
}

outputs.tf

outputs.tf
output "id" {
  description = "Specifies the resource id of the private endpoint."
  value       = azurerm_private_endpoint.private_endpoint.id
}
 
output "nic_name" {
  description = "Specifies the name of the private endpoint nic."
  value       = azurerm_private_endpoint.private_endpoint.custom_network_interface_name
}
 
output "private_dns_zone_group" {
  description = "Specifies the private dns zone group of the private endpoint."
  value       = azurerm_private_endpoint.private_endpoint.private_dns_zone_group
}
 
output "private_dns_zone_configs" {
  description = "Specifies the private dns zone(s) configuration"
  value       = azurerm_private_endpoint.private_endpoint.private_dns_zone_configs
}

variables.tf

Note that most of the descriptions are copied from the terraform registry.
variables.tf
variable "name" {
  description = "(Required) Specifies the name of the private endpoint. Changing this forces a new resource to be created."
  type        = string
}
 
variable "resource_group_name" {
  description = "(Required) The name of the resource group. Changing this forces a new resource to be created."
  type        = string
}
 
variable "private_connection_resource_id" {
  description = "(Required) Specifies the resource id of the private link service"
  type        = string
}
 
variable "location" {
  description = "(Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created."
  type        = string
}
 
variable "subnet_id" {
  description = "(Required) Specifies the resource id of the subnet"
  type        = string
}
 
variable "private_dns_zone_group_name" {
  description = "(Required) Specifies the Name of the Private DNS Zone Group. Changing this forces a new private_dns_zone_group resource to be created."
  type        = string
}
 
variable "private_dns_zone_group_ids" {
  description = "(Required) Specifies the list of Private DNS Zones to include within the private_dns_zone_group."
  type        = list(string)
}
 
variable "ip_configurations" {
  description = "(Optional) Specifies the static IP addresses within the private endpoint's subnet to be used. Changing this forces a new resource to be created."
  default     = []
  type        = list(object({ private_ip_address = string, member_name = string }))
}
 
variable "is_manual_connection" {
  description = "(Optional) Specifies whether the private endpoint connection requires manual approval from the remote resource owner."
  type        = string
  default     = false
}
 
variable "subresource_name" {
  description = "(Optional) Specifies a subresource name which the Private Endpoint is able to connect to."
  type        = string
  default     = null
}
 
variable "request_message" {
  description = "(Optional) Specifies a message passed to the owner of the remote resource when the private endpoint attempts to establish the connection to the remote resource."
  type        = string
  default     = null
}
 
variable "tags" {
  description = "(Optional) Specifies the tags of the network security group"
  default     = {}
}
terraformmoduleprivateendpoint.txt · Last modified: 2025/04/21 17:09 by 127.0.0.1