Azure/terraform-azurerm-avm-res-operationalinsights-workspace

[AVM Module Issue]: Private endpoints fail due to wrong id being passed for private_connection_resource_id

richshadman opened this issue ยท 5 comments

Check for previous/existing GitHub issues

  • I have checked for previous/existing GitHub issues

Issue Type?

Bug

(Optional) Module Version

0.2.2

(Optional) Correlation Id

No response

Description

The current version of the module fails when trying to create a private endpoint due to the fact that the workspace resource id is being passed for the private service connection private connection resource id, when it should be a private service link resource id.

Here is the current code in question (main.privateendpoint.tf in this repo):

https://github.com/Azure/terraform-azurerm-avm-res-operationalinsights-workspace/blob/main/main.privateendpoint.tf#L15
image

Here is the example code in the provider documentation showing it should be a private service link resource id:

https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_endpoint#example-usage
image

Here is the output when applied in it's current state (edit to hide sensitive info):

image

Here is a copy of my module (nothing fancy):

module "workspace" {
  source                                             = "Azure/avm-res-operationalinsights-workspace/azurerm"
  version                                            = "0.2.2"
  resource_group_name                                = azurerm_resource_group.this.name
  name                                               = local.names.workspace
  location                                           = data.terraform_remote_state.environment.outputs.region
  log_analytics_workspace_sku                        = var.workspace.sku
  log_analytics_workspace_retention_in_days          = var.workspace.retention_in_days
  enable_telemetry                                   = true
  log_analytics_workspace_internet_ingestion_enabled = false
  log_analytics_workspace_internet_query_enabled     = false
  tags                                               = merge(local.analytics_tags_internal, { name = local.names.workspace })

  diagnostic_settings = {
    default = {
      name                        = "default"
      storage_account_resource_id = module.storage.resource_id

    }
  }

  log_analytics_workspace_identity = {
    type         = "UserAssigned"
    identity_ids = [azurerm_user_assigned_identity.workspace.id]
  }

  private_endpoints = {
    for endpoint, private_ip in local.workspace_endpoints :
    endpoint => {
      subnet_resource_id              = lookup(data.terraform_remote_state.network.outputs.vnet.vnet_subnets_name_id, "snet-monitor")
      location                        = data.terraform_remote_state.environment.outputs.region
      name                            = "pe-${endpoint}-${local.names.workspace}"
      subresource_name                = endpoint
      private_dns_zone_resource_ids   = [for zone in data.terraform_remote_state.network.outputs.subnets["snet-monitor"].private_dns_zones : lookup(data.terraform_remote_state.network.outputs.private_dns_zone, zone).id]
      private_service_connection_name = "psc-${endpoint}-${local.names.workspace}"
      network_interface_name          = "nic-pe-${endpoint}-${local.names.workspace}"
      resource_group_name             = azurerm_resource_group.this.name
      tags                            = merge(local.analytics_tags_internal, { name = "pe-${endpoint}-${local.names.workspace}" })

      ip_configurations = {
        "staticIpConfig" = {
          name               = "staticIpConfig"
          private_ip_address = private_ip
        }
      }
    }
  }

  depends_on = [
    module.storage
  ]
}

And finally, here is a support request from MS on the above issue that pointed me to the root cause (using workspace resource id in place of private service link resource id):

https://learn.microsoft.com/en-us/answers/questions/1106857/feature-allowprivateendpoints-from-provider-namesp

Note that in that issue the error is identical, with the odd formatted resource id (missing the resource group name in the id).

My workaround for now is to omit the private endpoint details from the module and handle it myself, which is not ideal but is workable. If it is possible to get quick turnaround on this issue (hoping that is the case with the information above) then we would be able to implement entirely with the module before going live with this project.

Thank you!

Rich Shadman

@richshadman thanks for the issue. I need to add the Azure Monitor Private Link to the module for PE to work with LAW. Will do that in the next version.

https://learn.microsoft.com/en-us/azure/azure-monitor/logs/private-link-configure

@richshadman I deployed the law module with PE and Azure Monitor Private Link. I need to clean it up and change the module, but that's what the new example will look like. Will deploy out a new version in the coming week. Thanks!

terraform {
  required_version = ">= 1.3.0"
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = ">= 3.7.0, < 4.0.0"
    }
    random = {
      source  = "hashicorp/random"
      version = ">= 3.5.0, < 4.0.0"
    }
  }
}

provider "azurerm" {
  features {}
}

# This ensures we have unique CAF compliant names for our resources.
module "naming" {
  source  = "Azure/naming/azurerm"
  version = "0.3.0"
}

# This picks a random region from the list of regions.
resource "random_integer" "region_index" {
  max = length(local.azure_regions) - 1
  min = 0
}

# This is required for resource modules
resource "azurerm_resource_group" "this" {
  location = local.azure_regions[random_integer.region_index.result]
  name     = module.naming.resource_group.name_unique
}

resource "azurerm_virtual_network" "this" {
  address_space       = ["192.168.0.0/24"]
  location            = azurerm_resource_group.this.location
  name                = module.naming.virtual_network.name_unique
  resource_group_name = azurerm_resource_group.this.name
}

resource "azurerm_subnet" "this" {
  address_prefixes     = ["192.168.0.0/24"]
  name                 = module.naming.subnet.name_unique
  resource_group_name  = azurerm_resource_group.this.name
  virtual_network_name = azurerm_virtual_network.this.name
}

resource "azurerm_private_dns_zone" "this" {
  name = "privatelink.workspace.azure.net"
  resource_group_name = azurerm_resource_group.this.name
}

resource "azurerm_private_dns_zone_virtual_network_link" "name" {
  name = "dnslinktovnet"
  resource_group_name = azurerm_resource_group.this.name
  virtual_network_id = azurerm_virtual_network.this.id
  private_dns_zone_name = azurerm_private_dns_zone.this.name
}

# This is the module call
module "law" {
  source = "../../"
  # source             = "Azure/avm-res-operationalinsights-workspace/azurerm"
  enable_telemetry                          = var.enable_telemetry
  location                                  = azurerm_resource_group.this.location
  resource_group_name                       = azurerm_resource_group.this.name
  name                                      = "thislaworkspace"
  log_analytics_workspace_retention_in_days = 30
  log_analytics_workspace_sku               = "PerGB2018"
  log_analytics_workspace_identity = {
    type = "SystemAssigned"
  }
}

resource "azurerm_monitor_private_link_scope" "this" {
  name                = "law-ampls"
  resource_group_name = azurerm_resource_group.this.name
}

resource "azurerm_monitor_private_link_scoped_service" "this" {
  name                = "law-amplsservice"
  resource_group_name = azurerm_resource_group.this.name
  scope_name          = azurerm_monitor_private_link_scope.this.name
  linked_resource_id  = module.law.resource.id
}

resource "azurerm_private_endpoint" "pe" {
  name = "pe"
  location = azurerm_resource_group.this.location
  resource_group_name = azurerm_resource_group.this.name
  subnet_id = azurerm_subnet.this.id
  private_dns_zone_group {
    name = "law-dns-zone-group"
    private_dns_zone_ids = [ azurerm_private_dns_zone.this.id ]
  }
  private_service_connection {
    name = "connection"
    private_connection_resource_id = azurerm_monitor_private_link_scope.this.id
    subresource_names = [ "azuremonitor" ]
    is_manual_connection = false
  }
}

Thank you for the quick turnaround @cshea-msft ! Much appreciated.

@richshadman released a new version that will fix this issue. Thank you for the problem, i appreciate the help! feel free to share any other feedback.