azureterraformazure-api-managementazure-private-linkazure-private-dns

Apim (private endpoint) named value, keyvault secret 404


I have an apim with a private endpoint. This is my code:

resource "azurerm_private_endpoint" "apim" {
  name                = "${var.organization}-apim-pep-${var.environment}"
  location            = var.azure_location
  resource_group_name = var.resourcegroups.apim.name
  subnet_id           = data.azurerm_subnet.pep.id

  private_service_connection {
    name                           = "apim_private_service_connection"
    private_connection_resource_id = azurerm_api_management.apim.id
    is_manual_connection           = false
    subresource_names              = ["Gateway"]
  }
}

resource "azurerm_api_management" "apim" {
  name                = "${var.organization}-hub-${var.environment}-apim"
  location            = var.azure_location
  resource_group_name = var.resourcegroups.apim.name
  publisher_name      = "${var.organization}-hub-${var.environment}-apim"
  publisher_email     = "email"
  sku_name            = "Developer_1"

  identity {
    type = "SystemAssigned, UserAssigned"
    identity_ids = [
      data.azurerm_user_assigned_identity.apim.id
    ]
  }
}

I cannot resolve keyvault secrets. I get 404 on them. Earlier, when I had vnet integration and no private endpoint, I could resolve them. It is probably a networking issue then. However, I cannot change settings on the vnet because the network is done by azure, underwater (vnet type = 'None' per default). The subnet in which the private endpoint is deployed, has a service endpoint for Microsoft.KeyVault.

Which piece of the puzzle am I missing?


Solution

  • Apim (private endpoint) named value, keyvault secret 404:

    If you cannot change the settings of a created virtual network, you must use a virtual network link resource provider named as azurerm_private_dns_zone_virtual_network_link to establish a network link connection for the keyvault. And also create a azurerm_private_dns_a_record for the key vault and link to the virtual network which is hosting the private endpoint for an API management service.

    Modified terraform code has given below:

    terraform {
      required_providers {
        azurerm = {
          source = "hashicorp/azurerm"
          version = "4.3.0"
        }
      }
    }
    
    provider "azurerm" {
      features{}
     subscription_id="fxxxx014"
    }
    data "azurerm_client_config" "current" {}
    resource "azurerm_resource_group" "example" {
      name     = "examplejahresources"
      location = "West Europe"
    }
    resource "azurerm_api_management" "apim" {
      name                = "newja-apim"
      location            = azurerm_resource_group.example.location
      resource_group_name = azurerm_resource_group.example.name
      publisher_name      = "My Company-apim"
      publisher_email     = "company@terraform.io"
      sku_name            = "Developer_1"
    
      identity {
        type = "SystemAssigned"
      }
    }
    resource "azurerm_virtual_network" "example" {
      name                = "ejanetwork"
      address_space       = ["10.0.0.0/16"]
      location            = azurerm_resource_group.example.location
      resource_group_name = azurerm_resource_group.example.name
    }
    resource "azurerm_subnet" "service" {
      name                 = "jahservice"
      resource_group_name  = azurerm_resource_group.example.name
      virtual_network_name = azurerm_virtual_network.example.name
      address_prefixes     = ["10.0.1.0/24"]
    }
    resource "azurerm_key_vault" "example" {
      name                        = "examplejahkeyvault"
      location                    = azurerm_resource_group.example.location
      resource_group_name         = azurerm_resource_group.example.name
      enabled_for_disk_encryption = true
      tenant_id                   = data.azurerm_client_config.current.tenant_id
      soft_delete_retention_days  = 7
      purge_protection_enabled    = false
    
      sku_name = "standard"
    
      access_policy {
        tenant_id = data.azurerm_client_config.current.tenant_id
        object_id = data.azurerm_client_config.current.object_id
    
        key_permissions = [
          "Get",
        ]
    
        secret_permissions = [
          "Get",
        ]
    
        storage_permissions = [
          "Get",
        ]
      }
    }
    
    resource "azurerm_private_dns_zone" "example" {
      name                = "privatelink.vaultcore.azure.net"
      resource_group_name = azurerm_resource_group.example.name
    }
    
    resource "azurerm_private_dns_zone_virtual_network_link" "example" {
      name                  = "test"
      resource_group_name   = azurerm_resource_group.example.name
      private_dns_zone_name = azurerm_private_dns_zone.example.name
      virtual_network_id    = azurerm_virtual_network.example.id
    }
    resource "azurerm_private_dns_a_record" "example" {
      name                = azurerm_key_vault.example.name
      zone_name           = azurerm_private_dns_zone.example.name
      resource_group_name = azurerm_resource_group.example.name
      ttl                 = 300
      records             = ["10.0.180.17"]
    }
    resource "azurerm_private_endpoint" "apim" {
      name                = "jahendpoint"
      location            = azurerm_resource_group.example.location
      resource_group_name = azurerm_resource_group.example.name
      subnet_id           = azurerm_subnet.service.id
    
      private_service_connection {
        name                           = "apim_private_service_connection"
        private_connection_resource_id = azurerm_api_management.apim.id
        is_manual_connection           = false
        subresource_names              = ["Gateway"]
      }
    }
    resource "azurerm_private_endpoint" "keyvaultep" {
      name                = "jah-kv-pep"
      location            = azurerm_resource_group.example.location
      resource_group_name = azurerm_resource_group.example.name
      subnet_id           = azurerm_subnet.service.id
    
      private_service_connection {
        name                           = "keyvault_private_service_connection"
        private_connection_resource_id = azurerm_key_vault.example.id
        is_manual_connection           = false
        subresource_names              = ["vault"]
      }
    }
    

    Deployment succeeded:

    enter image description here

    enter image description here

    enter image description here

    enter image description here