azure-devopsterraformazure-keyvault

Expanding variable group resource data: failed to get Azure key value.Failed to query service connection API


`Error: Expanding variable group resource data: Failed to get the Azure Key value. Error: ( code: unused, messge: Failed to query service connection API: 'https://ecn-dev-we-hub-kv.vault.azure.net/secrets?api-version=2016-10-01'. Error Message: 'An error occurred while sending the request.' ) │ │
with module.azuredevops.azuredevops_variable_group.example_keyvault_link, │ on azuredevops\main.tf line 38, in resource "azuredevops_variable_group" "example_keyvault_link": │ 38: resource "azuredevops_variable_group" "example_keyvault_link" {

I am trying to create variable group and link keyvaults secrets as variables to variable group. Providing my code below

provider "azuredevops" {
org_service_url = var.org_service_url
personal_access_token = var.personal_access_token
}
data "azuredevops_project" "project" {
name = var.project_name
}

data "azuredevops_serviceendpoint_azurerm" "serviceendpoint" {
project_id            = data.azuredevops_project.project.id
service_endpoint_name = "testing"
}

resource "azuredevops_variable_group" "example" {
project_id   = data.azuredevops_project.project.id
name         = var.variablegroup_name
description  = "Example Variable Group Description"
allow_access = true
depends_on = [
data.azuredevops_serviceendpoint_azurerm.serviceendpoint
]
key_vault {
name                = "${var.prefix}-kv"
service_endpoint_id = data.azuredevops_serviceendpoint_azurerm.serviceendpoint.id
}
variable {
name = "storageAccountKey"
}

variable {
name = "localAdminSecret"
}
}

the problem is when i comment out keyvault part and push changes and run pipeline varibale group gets created and again i have to uncomment the keyvault part and push changes and run pipeline in order to link keyvault secrets to variable group . But when i am trying to achieve creating variable group and linking its secret to variable as a whole code without commenting keyvault part then I am facing this error .

can someone help me resolve the issue


Solution

  • solution to my error was using a null_resource with local-exec to wait for Key Vault readiness, and set depends_on in azuredevops_variable_group to depend on this null_resource .

    In my case , we are using two different modules one for keyvault creation & and another module for variable group creation module name azuredevops.

    I have added null resource in keyvault module

    keyvault/main.tf 
    
    data "azurerm_client_config" "current" {}
    
    data "azurerm_resource_group" "rg-management" {
      name = local.resource_group_management
    }
    
    data "azurerm_storage_account" "sg" {
      name                = var.initstorageccount
      resource_group_name = data.azurerm_resource_group.rg-management.name
    }
    
    # Key Vault Resource
    resource "azurerm_key_vault" "example" {
      name                        = "${var.prefix}-kv5"  # Change the name for the new Key Vault
      location                    = var.location
      resource_group_name         = data.azurerm_resource_group.rg-management.name
      enabled_for_disk_encryption = true
      tenant_id                   = data.azurerm_client_config.current.tenant_id
      soft_delete_retention_days  = 90
      purge_protection_enabled    = true
      sku_name                    = "standard"
    
      access_policy {
        tenant_id       = data.azurerm_client_config.current.tenant_id
        object_id       = data.azurerm_client_config.current.object_id
        secret_permissions = [
          "Set",
          "Get",
          "List",
          "Delete",
          "Backup",
          "Purge",
          "Recover", 
          "Restore"
        ]
        storage_permissions = [
          "Set",
          "Get",
          "List",
          "Delete"
        ]
      }
      access_policy {
        tenant_id       = data.azurerm_client_config.current.tenant_id
        object_id       = var.aad_object_id # Replace with your Azure Active Directory(AAD) object ID
        secret_permissions = ["Set", "Get", "List"]
        storage_permissions = ["Set", "Get", "List"]
      }
    }
    
    # add secrets to the new Key Vault
    resource "azurerm_key_vault_secret" "storage_account_key" {
      name         = "storageAccountKey"
      value        = data.azurerm_storage_account.sg.primary_access_key
      key_vault_id = azurerm_key_vault.example.id
    }
    
    resource "random_password" "password" {
      length = 12
    }
    
    resource "azurerm_key_vault_secret" "localadminsecret" {
      name         = "localAdminSecret"
      value        = random_password.password.result
      key_vault_id = azurerm_key_vault.example.id
    }
    
    
    resource "null_resource" "wait_for_key_vault" {
      provisioner "local-exec" {
        command = "echo 'Waiting for Key Vault readiness' && sleep 60"  # Adjust the sleep duration as needed
      }
      triggers = {
        key_vault_id = azurerm_key_vault.example.id
      }
    }
    
    output it's values in keyvault/output.tf 
    
    keyvault/output.tf
    
    
    
      output "key_vault_ready" {
          value = null_resource.wait_for_key_vault.id
        }
        output "key_vault_id" {
          value = azurerm_key_vault.example.id
        }
    
    adding null resource dependency in azuredevops module while creating variable group resource
    
    azuredevops/main.tf 
    
    provider "azuredevops" {
      org_service_url = var.org_service_url
      personal_access_token = var.personal_access_token
    }
    
    
    data "azuredevops_project" "project" {
      name = var.project_name 
    }
    
    data "azuredevops_serviceendpoint_azurerm" "serviceendpoint" {
      project_id            = data.azuredevops_project.project.id
      service_endpoint_name = var.service_endpoint_name
    }
    
    
    
    resource "azuredevops_variable_group" "example" {
      project_id   = data.azuredevops_project.project.id
      name         = var.variablegroup_name
      description  = "Example Variable Group Description"
      allow_access = true
      depends_on = [ data.azuredevops_serviceendpoint_azurerm.serviceendpoint, 
      var.key_vault_ready ]
      
      key_vault {
        name                = "${var.prefix}-kv5"
        service_endpoint_id = data.azuredevops_serviceendpoint_azurerm.serviceendpoint.id
      }
    
      variable {
        name = "storageAccountKey"
      }
    
      variable {
        name = "localAdminSecret"  
        }
    }
    
    Pass the key_vault_ready output in the Root main.tf:
    
    module "keyvault" {
        source = "./keyvault"
        prefix                =var.prefix
        location              =var.location
        initstorageccount       = var.initstorageccount
        resourceGroupStorage   =var.resourceGroupStorage
        aad_object_id = var.aad_object_id
        }
        
        # # Module for keyvault
        module "azuredevops" {
        source = "./azuredevops"
        prefix                =var.prefix
        org_service_url = var.org_service_url
        project_name = var.project_name
        variablegroup_name = var.variablegroup_name
        personal_access_token = var.personal_access_token
        service_endpoint_name = var.service_endpoint_name
        # service_endpoint_id = var.service_endpoint_id
        key_vault_id=module.keyvault.key_vault_id
        key_vault_ready = module.keyvault.key_vault_ready
        
        }
    

    pipeline execution