hashicorp / terraform-provider-azurerm

Terraform provider for Azure Resource Manager
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs
Mozilla Public License 2.0
4.52k stars 4.6k forks source link

Support for Auto-Approval when adding ADF (azure data factory) Managed Private Endpoints #19777

Open meghdivya opened 1 year ago

meghdivya commented 1 year ago

Is there an existing issue for this?

Community Note

Description

Currently we can use the ADF(azure data factory) provider to create managed private endpoints. Unfortunately at the moment these private endpoints need to be approved manually and it prevents a full deployment using Terraform.

There is a similar feature request filed for Synapse managed private endpoints: https://github.com/hashicorp/terraform-provider-azurerm/issues/13107

New or Affected Resource(s)/Data Source(s)

azurerm_data_factory_managed_private_endpoint

Potential Terraform Configuration

is_manual_connection = false

References

https://learn.microsoft.com/en-us/azure/data-factory/managed-virtual-network-private-endpoint#managed-private-endpoints

https://github.com/hashicorp/terraform-provider-azurerm/issues/13107

robertbrandso commented 1 year ago

Here's an example on how it can be solved using the azapi provider.

# -------------------------
# MANAGED PRIVATE ENDPOINTS
# -------------------------

# Create managed private endpoint between Data factory and Storage account for Blob resource
resource "azurerm_data_factory_managed_private_endpoint" "batch_account_storage_blob" {
  name               = "pep-${azurerm_data_factory.main.name}_${azurerm_storage_account.batch.name}-blob"
  data_factory_id    = azurerm_data_factory.main.id
  target_resource_id = azurerm_storage_account.batch.id

  subresource_name = "blob"
}

# Create managed private endpoint between Data factory and Storage account for File resource
resource "azurerm_data_factory_managed_private_endpoint" "batch_account_storage_file" {
  name               = "pep-${azurerm_data_factory.main.name}_${azurerm_storage_account.batch.name}-file"
  data_factory_id    = azurerm_data_factory.main.id
  target_resource_id = azurerm_storage_account.batch.id

  subresource_name = "file"
}

# Approve private endpoints on storage account
## Get information about all private endpoint connections on the storage account
data "azapi_resource" "batch_storage_account_private_endpoint_connection" {
  type                   = "Microsoft.Storage/storageAccounts@2022-09-01"
  resource_id            = azurerm_storage_account.batch.id
  response_export_values = ["properties.privateEndpointConnections."]

  depends_on = [
    azurerm_data_factory_managed_private_endpoint.batch_account_storage_blob,
    azurerm_data_factory_managed_private_endpoint.batch_account_storage_file
  ]
}

locals {

  ## Extract private endpoint connection names
  ### This is done by looking at data.azapi_resource.batch_storage_account_private_endpoint_connection and picking the connection name.
  ### The name of the managed private endpoint is at the end of the description field. This can be used to pick the correct private endpoint connection.
  ### After the approval is done, the description fields changes to whatever we configure in azapi_update_resource.approve_batch_storage_account_*_private_endpoint_connection.
  ### It is important that the logic in the for loop below and the content of the description fields matches to make the Terraform configuration work.

  ## Blob
  storage_account_blob_private_endpoint_connection_name = one([
    for connection in jsondecode(data.azapi_resource.batch_storage_account_private_endpoint_connection.output).properties.privateEndpointConnections
    : connection.name
    if
    endswith(connection.properties.privateLinkServiceConnectionState.description, azurerm_data_factory_managed_private_endpoint.batch_account_storage_blob.name)
  ])

  ## File
  storage_account_file_private_endpoint_connection_name = one([
    for connection in jsondecode(data.azapi_resource.batch_storage_account_private_endpoint_connection.output).properties.privateEndpointConnections
    : connection.name
    if
    endswith(connection.properties.privateLinkServiceConnectionState.description, azurerm_data_factory_managed_private_endpoint.batch_account_storage_file.name)
  ])
}

## Do the actual approval for each of the connections
### Blob
resource "azapi_update_resource" "approve_batch_storage_account_blob_private_endpoint_connection" {
  type      = "Microsoft.Storage/storageAccounts/privateEndpointConnections@2022-09-01"
  name      = local.storage_account_blob_private_endpoint_connection_name
  parent_id = azurerm_storage_account.batch.id

  body = jsonencode({
    properties = {
      privateLinkServiceConnectionState = {
        description = "Approved via Terraform - ${azurerm_data_factory_managed_private_endpoint.batch_account_storage_blob.name}" # To identify which managed private endpoint this connection belongs to we add the managed private endpoint name to the description
        status      = "Approved"
      }
    }
  })

  lifecycle {
    ignore_changes = all # We don't want to touch this after creation
  }
}

### File
resource "azapi_update_resource" "approve_batch_storage_account_file_private_endpoint_connection" {
  type      = "Microsoft.Storage/storageAccounts/privateEndpointConnections@2022-09-01"
  name      = local.storage_account_file_private_endpoint_connection_name
  parent_id = azurerm_storage_account.batch.id

  body = jsonencode({
    properties = {
      privateLinkServiceConnectionState = {
        description = "Approved via Terraform - ${azurerm_data_factory_managed_private_endpoint.batch_account_storage_file.name}" # To identify which managed private endpoint this connection belongs to we add the managed private endpoint name to the description
        status      = "Approved"
      }
    }
  })

  lifecycle {
    ignore_changes = all # We don't want to touch this after creation
  }
}