Skip to content

CloudAstro/terraform-azurerm-private-endpoint

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

4 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Azure Private Endpoint Terraform Module

Changelog Notice Apache V2 License OpenTofu Registry

This module is designed to manage Manages a Private Endpoint.

Azure Private Endpoint is a network interface that connects you privately and securely to a service powered by Azure Private Link. Private Endpoint uses a private IP address from your VNet, effectively bringing the service into your VNet. The service could be an Azure service such as Azure Storage, SQL, etc. or your own Private Link Service.

Features

  • Private Connectivity: Provides secure, private access to Azure services over a private IP address.
  • Azure Private Link Integration: Connects to supported Azure PaaS services and custom services using Private Link.
  • DNS Configuration: Supports automatic or manual DNS setup for private endpoint name resolution.
  • Network Security Integration: Works with Network Security Groups (NSGs) and role-based access control (RBAC) for traffic and resource management.

Example Usage

This example demonstrates how to use the terraform-azurerm-private-endpoint module to create a Private Endpoint and associate it to e private dns.

resource "azurerm_resource_group" "example" {
  name     = "rg-privateendpoint-example"
  location = "germanywestcentral"
}

module "vnet" {
  source              = "CloudAstro/virtual-network/azurerm"
  name                = "vnet"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
  address_space       = ["10.20.0.0/24"]
}

module "subnet" {
  source               = "CloudAstro/subnet/azurerm"
  name                 = "snet-example"
  resource_group_name  = azurerm_resource_group.example.name
  virtual_network_name = module.vnet.virtual_network.name
  address_prefixes     = ["10.20.0.0/25"]
}

resource "azurerm_storage_account" "example" {
  name                     = "examplestorageacct111" # must be globally unique, lowercase
  resource_group_name      = azurerm_resource_group.example.name
  location                 = azurerm_resource_group.example.location
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

resource "azurerm_private_dns_zone" "example" {
  name                = "privatelink.blob.core.windows.net"
  resource_group_name = azurerm_resource_group.example.name
}

module "private_endpoint" {
  source                        = "../../"
  name                          = "example-private-endpoint"
  resource_group_name           = azurerm_resource_group.example.name
  location                      = azurerm_resource_group.example.location
  subnet_id                     = module.subnet.subnet.id
  custom_network_interface_name = "custom-nic"

  private_dns_zone_group = {
    dns_zone_group = {
      private_dns_zone_ids = [azurerm_private_dns_zone.example.id]
      name                 = "example_group"
    }
  }

  private_service_connection = {
    name                           = "example-connection"
    private_connection_resource_id = azurerm_storage_account.example.id
    is_manual_connection           = false
    subresource_names              = ["blob"]
  }

  ip_configurations = {
    ipconfig1 = {
      name               = "ipconfig1"
      member_name        = "blob"
      subresource_name   = "blob"
      private_ip_address = "10.20.0.10"
    }
  }

  application_security_group = {
    asg-https = {
      name = "asg-https"
    }
    asg-smb = {
      name = "asg-smb"
    }
  }

  tags = {
    env = "PE"
  }
}

Requirements

Name Version
terraform ~> 1.9.0
azurerm >= 4.0.0

Providers

Name Version
azurerm >= 4.0.0

Resources

Name Type
azurerm_application_security_group.application_security_group resource
azurerm_management_lock.this resource
azurerm_monitor_diagnostic_setting.this resource
azurerm_private_endpoint.private_endpoint resource
azurerm_private_endpoint_application_security_group_association.application_security_group_accociation resource
azurerm_role_assignment.private_endpoint resource

Inputs

Name Description Type Default Required
location * location - (Required) The supported Azure location where the resource exists. Changing this forces a new resource to be created.

Example Input:
location = "East US"
string n/a yes
name * name - (Required) Specifies the Name of the Private Endpoint. Changing this forces a new resource to be created.

Example Input:
name = "blob-private-endpoint"
string n/a yes
private_service_connection * private_service_connection - (Required) Specify service connection for private endpoint
A private_service_connection block supports the following:
* name - (Required) Specifies the Name of the Private Service Connection. Changing this forces a new resource to be created.
* is_manual_connection - (Required) Does the Private Endpoint require Manual Approval from the remote resource owner? Changing this forces a new resource to be created.
-> NOTE: If you are trying to connect the Private Endpoint to a remote resource without having the correct RBAC permissions on the remote resource set this value to true.
* private_connection_resource_id - (Optional) The ID of the Private Link Enabled Remote Resource which this Private Endpoint should be connected to. One of private_connection_resource_id or private_connection_resource_alias must be specified. Changing this forces a new resource to be created. For a web app or function app slot, the parent web app should be used in this field instead of a reference to the slot itself.
* private_connection_resource_alias - (Optional) The Service Alias of the Private Link Enabled Remote Resource which this Private Endpoint should be connected to. One of private_connection_resource_id or private_connection_resource_alias must be specified. Changing this forces a new resource to be created.
* subresource_names - (Optional) A list of subresource names which the Private Endpoint is able to connect to. subresource_names corresponds to group_id. Possible values are detailed in the product documentation in the Subresources column. Changing this forces a new resource to be created.
-> NOTE: Some resource types (such as Storage Account) only support 1 subresource per private endpoint.
-> NOTE: For most Private Links one or more subresource_names will need to be specified, please see the linked documentation for details.
* request_message - (Optional) A message passed to the owner of the remote resource when the private endpoint attempts to establish the connection to the remote resource. The provider allows a maximum request message length of 140 characters, however the request message maximum length is dependent on the service the private endpoint is connected to. Only valid if is_manual_connection is set to true.
-> NOTE: When connected to an SQL resource the request_message maximum length is 128.

Example Input:
private_service_connection = {
name = "connection1" # Example value
private_connection_resource_id = "/subscriptions//resourceGroups//providers/Microsoft.KeyVault/vaults/"
is_manual_connection = false # Example value
subresource_names = ["blob"] # Example value
request_message = "Please approve this connection."
}
object({
name = string
is_manual_connection = bool
private_connection_resource_id = optional(string)
private_connection_resource_alias = optional(string)
subresource_names = optional(set(string))
request_message = optional(string)
})
n/a yes
resource_group_name * resource_group_name - (Required) Specifies the Name of the Resource Group within which the Private Endpoint should exist. Changing this forces a new resource to be created.

Example Input:
resource_group_name = "my-resource-group"
string n/a yes
subnet_id * subnet_id - (Required) The ID of the Subnet from which Private IP Addresses will be allocated for this Private Endpoint. Changing this forces a new resource to be created.

Example Input:
subnet_id = "/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets/"
string n/a yes
application_security_group Map of Application Security Group configurations
* application_security_group - (Optional) Map of Application Security Group configurations
The following arguments are supported:
* name - (Required) Specifies the name of the Application Security Group. Changing this forces a new resource to be created.
* resource_group_name - (Required) The name of the resource group in which to create the Application Security Group. Changing this forces a new resource to be created.
* location - (Optional) (Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created.
The timeouts block allows you to specify timeouts for certain actions:
* create - (Defaults to 30 minutes) Used when creating the Diagnostics Setting.
* update - (Defaults to 30 minutes) Used when updating the Diagnostics Setting.
* read - (Defaults to 5 minutes) Used when retrieving the Diagnostics Setting.
* delete - (Defaults to 30 minutes) Used when deleting the Diagnostics Setting.
* tags - (Optional) A mapping of tags to assign to the resource.

Example Input:
application_security_group = {
asg1 = {
name = "asg1"
}
}
map(object({
name = string
resource_group_name = optional(string)
location = optional(string)
tags = optional(map(string))
timeouts = optional(object({
create = optional(string, "30")
update = optional(string, "30")
read = optional(string, "5")
delete = optional(string, "30")
}))
}))
null no
custom_network_interface_name * custom_network_interface_name - (Optional) The custom name of the network interface attached to the private endpoint. Changing this forces a new resource to be created.

Example Input:
custom_network_interface_name = "my-custom-nic"
string null no
diagnostic_settings * diagnostic_settings - (Optional) Diagnostic settings for azure resources.
The following arguments are supported:
* name - (Required) Specifies the name of the Diagnostic Setting. Changing this forces a new resource to be created.
-> NOTE: If the name is set to 'service' it will not be possible to fully delete the diagnostic setting. This is due to legacy API support.
* target_resource_id - (Optional) The ID of an existing Resource on which to configure Diagnostic Settings. Changing this forces a new resource to be created.
* eventhub_name - (Optional) Specifies the name of the Event Hub where Diagnostics Data should be sent.
-> NOTE: If this isn't specified then the default Event Hub will be used.
* eventhub_authorization_rule_id - (Optional) Specifies the ID of an Event Hub Namespace Authorization Rule used to send Diagnostics Data.
-> NOTE: This can be sourced from the azurerm_eventhub_namespace_authorization_rule resource and is different from a azurerm_eventhub_authorization_rule resource.
-> NOTE: At least one of eventhub_authorization_rule_id, log_analytics_workspace_id, partner_solution_id and storage_account_id must be specified.
* log_analytics_workspace_id - (Optional) Specifies the ID of a Log Analytics Workspace where Diagnostics Data should be sent.
-> NOTE: At least one of eventhub_authorization_rule_id, log_analytics_workspace_id, partner_solution_id and storage_account_id must be specified.
* storage_account_id - (Optional) The ID of the Storage Account where logs should be sent.
-> NOTE: At least one of eventhub_authorization_rule_id, log_analytics_workspace_id, partner_solution_id and storage_account_id must be specified.
* log_analytics_destination_type - (Optional) Possible values are AzureDiagnostics and Dedicated. When set to Dedicated, logs sent to a Log Analytics workspace will go into resource specific tables, instead of the legacy AzureDiagnostics table.
-> NOTE: This setting will only have an effect if a log_analytics_workspace_id is provided. For some target resource type (e.g., Key Vault), this field is unconfigurable. Please see resource types for services that use each method. Please see the documentation for details on the differences between destination types.
* partner_solution_id - (Optional) The ID of the market partner solution where Diagnostics Data should be sent. For potential partner integrations, click to learn more about partner integration.
-> NOTE: At least one of eventhub_authorization_rule_id, log_analytics_workspace_id, partner_solution_id and storage_account_id must be specified.
An enabled_log block supports the following:
* category - (Optional) The name of a Diagnostic Log Category for this Resource.
-> NOTE: The Log Categories available vary depending on the Resource being used. You may wish to use the azurerm_monitor_diagnostic_categories Data Source or list of service specific schemas to identify which categories are available for a given Resource.
* category_group - (Optional) The name of a Diagnostic Log Category Group for this Resource.
-> NOTE: Not all resources have category groups available.
-> NOTE: Exactly one of category or category_group must be specified.
A metric block supports the following:
* category - (Required) The name of a Diagnostic Metric Category for this Resource.
* -> NOTE: The Metric Categories available vary depending on the Resource being used. You may wish to use the azurerm_monitor_diagnostic_categories Data Source to identify which categories are available for a given Resource.
* enabled - (Optional) Is this Diagnostic Metric enabled? Defaults to true.
The timeouts block allows you to specify timeouts for certain actions:
* create - (Defaults to 30 minutes) Used when creating the Diagnostics Setting.
* update - (Defaults to 30 minutes) Used when updating the Diagnostics Setting.
* read - (Defaults to 5 minutes) Used when retrieving the Diagnostics Setting.
* delete - (Defaults to 60 minutes) Used when deleting the Diagnostics Setting.

Example Input:
diagnostic_settings = {
"diagnostic" = {
name = "diagnostic_settings"
target_resource_id = null
eventhub_name = null
eventhub_authorization_rule_id = null
log_analytics_workspace_id = "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.OperationalInsights/workspaces/myLogAnalyticsWorkspace"
storage_account_id = "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/myResourceGroup/providers/Microsoft.Network/loadBalancers/my_load_balancer_1"
log_analytics_destination_type = null
partner_solution_id = null
metric = {
category = "AllMetrics"
enabled = true
}
}
}
map(object({
name = string
target_resource_id = optional(string)
eventhub_name = optional(string)
eventhub_authorization_rule_id = optional(string)
log_analytics_workspace_id = optional(string)
storage_account_id = optional(string)
log_analytics_destination_type = optional(string)
partner_solution_id = optional(string)
enabled_log = optional(list(object({
category = optional(string)
category_group = optional(string)
})))
metric = optional(object({
category = optional(string, "AllMetrics")
enabled = optional(bool)
}))
timeouts = optional(object({
create = optional(string, "30")
update = optional(string, "30")
read = optional(string, "5")
delete = optional(string, "60")
}))
}))
null no
ip_configurations * ip_configurations - (Optional) Specify ip configurations for private endpoint
An ip_configuration block supports the following:
* name - (Required) Specifies the Name of the IP Configuration. Changing this forces a new resource to be created.
* private_ip_address - (Required) Specifies the static IP address within the private endpoint's subnet to be used. Changing this forces a new resource to be created.
* subresource_name - (Optional) Specifies the subresource this IP address applies to. subresource_names corresponds to group_id. Changing this forces a new resource to be created.
* member_name - (Optional) Specifies the member name this IP address applies to. If it is not specified, it will use the value of subresource_name. Changing this forces a new resource to be created.
-> NOTE: member_name will be required and will not take the value of subresource_name in the next major version.
Example Input:
ip_configurations = {
ipconfig1= {
name = "ipconfig1" # Example value
member_name = "member1" # Example value
subresource_name = "blob" # Example value
private_ip_address = "10.0.0.4" # Example value
}
}
map(object({
name = string
private_ip_address = string
subresource_name = optional(string)
member_name = optional(string)
}))
null no
lock * lock - (Optional) Controls the Resource Lock configuration for this resource.
The following arguments are supported:
* kind - (Required) The type of lock. Possible values are \"CanNotDelete\" and \"ReadOnly\".
* name - (Optional) The name of the lock. If not specified, a name will be generated based on the kind value. Changing this forces the creation of a new resource.

Example Input:
lock = {
kind = "CanNotDelete"
name = "my-resource-lock"
}
object({
kind = string
name = optional(string, null)
})
null no
private_dns_zone_group * private_dns_zone_group -(Optional) Specify private dns zone group for private endpoint
A private_dns_zone_group block supports the following:
* name - (Required) Specifies the Name of the Private DNS Zone Group.
* private_dns_zone_ids - (Required) Specifies the list of Private DNS Zones to include within the private_dns_zone_group.

Example Input:
private_dns_zone_group = {
"group1" = {
name = "example-dns-zone-group"
private_dns_zone_ids = [
"/subscriptions//resourceGroups//providers/Microsoft.Network/privateDnsZones/privatelink.blob.core.windows.net"
]
}
}
map(object({
name = string
private_dns_zone_ids = set(string)
}))
null no
role_assignments * role_assignments - (Optional) A map of role assignments to create on the private endpoint. The map key is deliberately arbitrary to avoid issues where map keys maybe unknown at plan time. See var.role_assignments for more information
The following arguments are supported:
* name - (Optional) A unique UUID/GUID for this Role Assignment - one will be generated if not specified. Changing this forces a new resource to be created.
* scope - (Required) The scope at which the Role Assignment applies to, such as /subscriptions/0b1f6471-1bf0-4dda-aec3-111122223333, /subscriptions/0b1f6471-1bf0-4dda-aec3-111122223333/resourceGroups/myGroup, or /subscriptions/0b1f6471-1bf0-4dda-aec3-111122223333/resourceGroups/myGroup/providers/Microsoft.Compute/virtualMachines/myVM, or /providers/Microsoft.Management/managementGroups/myMG. Changing this forces a new resource to be created.
* role_definition_id - (Optional) The Scoped-ID of the Role Definition. Changing this forces a new resource to be created. Conflicts with role_definition_name.
* role_definition_name - (Optional) The name of a built-in Role. Changing this forces a new resource to be created. Conflicts with role_definition_id.
* principal_id - (Required) The ID of the Principal (User, Group or Service Principal) to assign the Role Definition to. Changing this forces a new resource to be created.
~> NOTE: The Principal ID is also known as the Object ID (ie not the "Application ID" for applications).
* principal_type - (Optional) The type of the principal_id. Possible values are User, Group and ServicePrincipal. Changing this forces a new resource to be created. It is necessary to explicitly set this attribute when creating role assignments if the principal creating the assignment is constrained by ABAC rules that filters on the PrincipalType attribute.
~> NOTE: If one of condition or condition_version is set both fields must be present.
* condition - (Optional) The condition that limits the resources that the role can be assigned to. Changing this forces a new resource to be created.
* condition_version - (Optional) The version of the condition. Possible values are 1.0 or 2.0. Changing this forces a new resource to be created.
* delegated_managed_identity_resource_id - (Optional) The delegated Azure Resource Id which contains a Managed Identity. Changing this forces a new resource to be created.
~> NOTE: this field is only used in cross tenant scenario.
* description - (Optional) The description for this Role Assignment. Changing this forces a new resource to be created.
* skip_service_principal_aad_check - (Optional) If the principal_id is a newly provisioned Service Principal set this value to true to skip the Azure Active Directory check which may fail due to replication lag. This argument is only valid if the principal_id is a Service Principal identity. Defaults to false.
~> NOTE: If it is not a Service Principal identity it will cause the role assignment to fail.

Example Input:
role_assignments = {
"example_assignment" = {
role_definition_id_or_name = "Contributor"
principal_id = "/subscriptions//resourceGroups//providers/Microsoft.ManagedIdentity/userAssignedIdentities/"
description = "Assignment for contributor role"
skip_service_principal_aad_check = false
}
}
map(object({
name = optional(string, null)
scope = string
role_definition_id = optional(string, null)
role_definition_name = optional(string, null)
principal_id = string
principal_type = optional(string, null)
condition = optional(string, null)
condition_version = optional(string, null)
delegated_managed_identity_resource_id = optional(string, null)
description = optional(string, null)
skip_service_principal_aad_check = optional(bool, false)
}))
null no
tags * tags - (Optional) A mapping of tags to assign to the resource.

Example Input:
tags = {
foo = bar
}
map(any) null no
timeouts The timeouts block allows you to specify timeouts for certain actions:
* create - (Defaults to 60 minutes) Used when creating the Subnet.
* update - (Defaults to 60 minutes) Used when updating the Subnet.
* read - (Defaults to 5 minutes) Used when retrieving the Subnet.
* delete - (Defaults to 60 minutes) Used when deleting the Subnet.
object({
create = optional(string, "60")
update = optional(string, "60")
read = optional(string, "5")
delete = optional(string, "60")
})
null no

Outputs

Name Description
private_endpoint * name - Specifies the Name of the Private Endpoint. Changing this forces a new resource to be created.
* resource_group_name - Specifies the Name of the Resource Group within which the Private Endpoint should exist. Changing this forces a new resource to be created.
* location - The supported Azure location where the resource exists. Changing this forces a new resource to be created.
* subnet_id - The ID of the Subnet from which Private IP Addresses will be allocated for this Private Endpoint. Changing this forces a new resource to be created.
* custom_network_interface_name - The custom name of the network interface attached to the private endpoint. Changing this forces a new resource to be created.
* private_dns_zone_group - A private_dns_zone_group block as defined below.
* private_service_connection - (A private_service_connection block as defined below.
* ip_configuration - One or more ip_configuration blocks as defined below. This allows a static IP address to be set for this Private Endpoint, otherwise an address is dynamically allocated from the Subnet.

A private_dns_zone_group block exports:
* id - The ID of the Private DNS Zone Group.
* name - Specifies the Name of the Private DNS Zone Group.
* private_dns_zone_ids - Specifies the list of Private DNS Zones to include within the private_dns_zone_group.

A private_service_connection block exports:
* private_ip_address - (Computed)The private IP address associated with the private endpoint, note that you will have a private IP address assigned to the private endpoint even if the connection request was Rejected.
* name - Specifies the Name of the Private Service Connection. Changing this forces a new resource to be created.
* is_manual_connection - Does the Private Endpoint require Manual Approval from the remote resource owner? Changing this forces a new resource to be created.
* private_connection_resource_id - The ID of the Private Link Enabled Remote Resource which this Private Endpoint should be connected to. One of private_connection_resource_id or private_connection_resource_alias must be specified. Changing this forces a new resource to be created. For a web app or function app slot, the parent web app should be used in this field instead of a reference to the slot itself.
* private_connection_resource_alias - The Service Alias of the Private Link Enabled Remote Resource which this Private Endpoint should be connected to. One of private_connection_resource_id or private_connection_resource_alias must be specified. Changing this forces a new resource to be created.
* subresource_names - A list of subresource names which the Private Endpoint is able to connect to. subresource_names corresponds to group_id. Possible values are detailed in the product documentation in the Subresources column. Changing this forces a new resource to be created.
* request_message - A message passed to the owner of the remote resource when the private endpoint attempts to establish the connection to the remote resource. The provider allows a maximum request message length of 140 characters, however the request message maximum length is dependent on the service the private endpoint is connected to. Only valid if is_manual_connection is set to true.

An ip_configuration block exports:
* name - Specifies the Name of the IP Configuration. Changing this forces a new resource to be created.
* private_ip_address - Specifies the static IP address within the private endpoint's subnet to be used. Changing this forces a new resource to be created.
* subresource_name - Specifies the subresource this IP address applies to. subresource_names corresponds to group_id. Changing this forces a new resource to be created.
* member_name - Specifies the member name this IP address applies to. If it is not specified, it will use the value of subresource_name. Changing this forces a new resource to be created.

Example output:
output "name" {
value = module.module_name.private_endpoint.name
}

Modules

No modules.

๐ŸŒ Additional Information

For more information about Azure Private Endpoint and their configurations, refer to the Azure Private Endpoint documentation. This module is designed to manage Manages a Private Endpoint.

๐Ÿ“š Resources

โš ๏ธ Notes

  • Private Endpoints are created within a specific VNet. Services can be accessed privately from within the same VNet or peered VNets.
  • Costs associated with Private Endpoints include charges for the private endpoint resource and any associated DNS zone usage. Regular data transfer costs still apply within Azure regions.
  • Validate your Terraform configuration to ensure that all storage resources are created and configured correctly.

๐Ÿงพ License

This module is released under the Apache 2.0 License. See the LICENSE file for full details.

About

Terraform module for Azure Private Endpoint

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published

Languages