terraformterraform-provider-azure

Failing to create azurerm_private_endpoint getting error unexpected status 400 (400 Bad Request) with error: SubscriptionNotRegisteredForFeature:


I am trying to create a private endpoint using terraform and am getting the error. What could I be missing? What I find interesting is the same subscription has got private endpoint resources .

Error: creating Private Endpoint (Subscription: "***" performing CreateOrUpdate: unexpected status 400 (400 Bad Request) with error: SubscriptionNotRegisteredForFeature: Subscription /subscriptions//resourceGroups//providers/Microsoft.Network/subscriptions/ is not registered for feature Microsoft.Network/AllowPrivateEndpoints required to carry out the requested operation. │ │ with module.azurerm_private_endpoint.azurerm_private_endpoint.main, │ on ../../factory/private-endpoint/main.tf line 1, in resource "azurerm_private_endpoint" "main": │ 1: resource "azurerm_private_endpoint" "main" {

main.tf

locals {
  team_name  = "devops"
  stack_name = "devops"

  location_abbreviations = { # map of location abbreviations according to naming conventions
    "southafricanorth" = "san"
    "westeurope"       = "euw"

  }
  resource_group_name = "${local.location_abbreviations[var.location]}-${var.environment}-${local.team_name}-rg-001"


  tags = { # list of tags
    env        = var.environment
    managed_by = "terraform"
    team       = local.team_name
  }
}


data "azurerm_client_config" "current" {}

data "terraform_remote_state" "platform" {
  backend = "azurerm"

  config = {
    subscription_id      = "********"
    resource_group_name  = "******"
    storage_account_name = "******"
    container_name       = "platform"
    key                  = "${var.environment}.tfstate"
  }
}


module "azurerm_resource_group" {
  source                  = "../../factory/resource-group"
  resource_group_name     = local.resource_group_name
  resource_group_location = var.location

}

module "azurerm_application_insights" {

  source                       = "../../factory/application-insights"
  app_insights_name            = "${local.location_abbreviations[var.location]}-${var.environment}-${local.team_name}-ai-001"
  location                     = var.location
  resource_group_name          = local.resource_group_name
  application_type             = "web"
  log_analytics_workspace_name = "${local.location_abbreviations[var.location]}-${var.environment}-${local.team_name}-logwkspace-001"
  tags                         = local.tags
  # Disable IP masking (captures the actual client IP address)
  disable_ip_masking = true
}

module "azurerm_private_endpoint" {
  source                                                    = "../../factory/private-endpoint"
  name                                                      = "${local.location_abbreviations[var.location]}-${var.environment}-lulapay-appInsight-endpoint-001"
  location                                                  = var.location
  resource_group_name                                       = local.resource_group_name
  subnet_id                                                 = data.terraform_remote_state.platform.outputs.private_endpoints_subnet_id
  private_service_connection_name                           = "app-insights-privatelink-dns-zones"
  private_service_connection_is_manual_connection           = false
  private_service_connection_private_connection_resource_id = module.azurerm_application_insights.id
  tags                                                      = local.tags
  private_dns_zone_group_name                               = "application-insights-private-dns-zones"
  private_dns_zone_group_name_private_dns_zone_ids          = [data.terraform_remote_state.platform.outputs.app_insights_privatelink_dns_zone_id]


}

# DNS A Record for Application Insights
resource "azurerm_private_dns_a_record" "example" {
  name                = "lulapay-app-insight-privatelink"
  zone_name           = split("/", trim(data.terraform_remote_state.platform.outputs.app_insights_privatelink_dns_zone_id, "/"))[7]
  resource_group_name = local.resource_group_name
  records             = [module.azurerm_private_endpoint.private_ip]
  ttl                 = 10
}
   

Module

resource "azurerm_private_endpoint" "main" {


  # define endpoint name based on app service name
  name                = var.name
  resource_group_name = var.resource_group_name
  location            = var.location
  subnet_id           = var.subnet_id
  tags                = var.tags
  
   private_dns_zone_group {
    name = var.private_dns_zone_group_name
    private_dns_zone_ids = var.private_dns_zone_group_name_private_dns_zone_ids
  }
  private_service_connection {
    name                           = var.private_service_connection_name
    private_connection_resource_id = var.private_service_connection_private_connection_resource_id
    is_manual_connection           = var.private_service_connection_is_manual_connection
    

  }
}

When a check the feature is still on pending

$ az feature show --namespace Microsoft.Network --name AllowPrivateEndpoints

{
  "id": "/subscriptions/*********/providers/Microsoft.Features/providers/Microsoft.Network/features/AllowPrivateEndpoints",
  "name": "Microsoft.Network/AllowPrivateEndpoints",
  "properties": {
    "state": ***"Pending"***
  },
  "type": "Microsoft.Features/providers/features"
}

Solution

  • For it to work I had to include Azure Monitor Private Link Scope. Then link the private endpoint to that and it worked.

    module "azurerm_application_insights" {
    
      source                       = "../../factory/application-insights"
      app_insights_name            = "${local.location_abbreviations[var.location]}-${var.environment}-${local.team_name}-ai-001"
      location                     = var.location
      resource_group_name          = local.resource_group_name
      application_type             = "web"
      log_analytics_workspace_name = "${local.location_abbreviations[var.location]}-${var.environment}-${local.team_name}-logwkspace-001"
      tags                         = local.tags
      # Disable IP masking (captures the actual client IP address)
      disable_ip_masking = true
    }
    
    resource "azurerm_monitor_private_link_scope" "lulapay-ampls" {
      name                = "${local.location_abbreviations[var.location]}-${var.environment}-${local.team_name}-ampls-endpoint-001"
      resource_group_name = local.resource_group_name
    }
    
    resource "azurerm_monitor_private_link_scoped_service" "lulapay-ampls-scoped" {
      name                = "${local.location_abbreviations[var.location]}-${var.environment}-${local.team_name}-amplsservice-001"
      resource_group_name = local.resource_group_name
      scope_name          = azurerm_monitor_private_link_scope.lulapay-ampls.name
      linked_resource_id  = module.azurerm_application_insights.id
    }
    
    
    module "azurerm_private_endpoint" {
      source                                                    = "../../factory/private-endpoint"
      name                                                      = "${local.location_abbreviations[var.location]}-${var.environment}-lulapay-appInsight-endpoint-001"
      location                                                  = var.location
      resource_group_name                                       = local.resource_group_name
      subnet_id                                                 = data.terraform_remote_state.platform.outputs.private_endpoints_subnet_id
      private_service_connection_name                           = "app-insights-privatelink-dns-zones"
      private_service_connection_is_manual_connection           = false
      private_service_connection_private_connection_resource_id = azurerm_monitor_private_link_scope.lulapay-ampls.id
      private_service_connection_subresource_names              = ["azuremonitor"]
      tags                                                      = local.tags
      private_dns_zone_group_name                               = "application-insights-private-dns-zones"
      private_dns_zone_group_name_private_dns_zone_ids          = [data.terraform_remote_state.platform.outputs.app_insights_privatelink_dns_zone_id]
    
    }
    
    
    resource "azurerm_private_dns_zone" "example" {
      name                = "privatelink.applicationinsights.azure.com"
      resource_group_name = "san-dev-lulapay-rg-001"
    }
    
    # DNS A Record for Application Insights
    resource "azurerm_private_dns_a_record" "example" {
      name                = "lulapay-app-insight-privatelink"
      zone_name           = split("/", trim(azurerm_private_dns_zone.example.id, "/"))[7]
      resource_group_name = local.resource_group_name
      records             = [module.azurerm_private_endpoint.private_ip]
      ttl                 = 10
    }