Im looking for some guidance on how to configure a devops project in terraform. The issue im having is to create an SPN and Client Secret and store the secret in the vault and allow the keyvault to use the secret in the devops project. The same applies to the storage account access key aswell.
Any help would be appreciated!
Error
Error: failed expanding repository resource data (ProjectID: azuredevops_project.adoproj.id, Repository: ADO Native Repo) Error: invalid UUID length: 30
│
│ with azuredevops_git_repository.new_repo,
│ on ado_repo.tf line 1, in resource "azuredevops_git_repository" "new_repo":
│ 1: resource "azuredevops_git_repository" "new_repo" {
│
╵
╷
│ Error: Expanding variable group resource data: Failed to get the Azure Key valut. Erroe: ( code: badRequest, messge: Failed to obtain the Json Web Token(JWT)
using service principal client ID. Exception message: A configuration issue is preventing authentication - check the error message from the server for details.
You can modify the configuration in the application registration portal. See https://aka.ms/msal-net-invalid-client for details. Original exception: AADSTS700
0215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app 'b826b4f8-0e00-493d-b892-d6ffba03f36c'.
│ Trace ID: a08e3154-e688-4379-a6fa-0d4b20b35700
│ Correlation ID: c7a270dd-b770-4a49-9251-fc302f0d191d
│ Timestamp: 2023-04-02 22:59:38Z )
│
│ with azuredevops_variable_group.varGroup,
│ on ado_variables.tf line 1, in resource "azuredevops_variable_group" "varGroup":
│ 1: resource "azuredevops_variable_group" "varGroup" {
│
╵
╷
│ Error: failed waiting for Key Vault Access Policy (Object ID: "248be4d9-230a-4286-b26b-849f1e22d92f") to apply: context deadline exceeded
│
│ with azurerm_key_vault_access_policy.Current,
│ on main.tf line 35, in resource "azurerm_key_vault_access_policy" "Current":
│ 35: resource "azurerm_key_vault_access_policy" "Current" {
│
╵
╷
│ Error: updating Access Policy (Object ID "f19e5047-68a1-4cfa-ae69-3d5d360f98c9" / Application ID "") for Vault: (Name "kv01h" / Resource Group "rg01"): keyvault.VaultsClient#UpdateAccessPolicy: Failure sending request: StatusCode=0 -- Original Error: context deadline exceeded
│
│ with azurerm_key_vault_access_policy.SPNAccess,
│ on main.tf line 41, in resource "azurerm_key_vault_access_policy" "SPNAccess":
│ 41: resource "azurerm_key_vault_access_policy" "SPNAccess" {
Providers
terraform {
required_providers {
azuredevops = {
source = "microsoft/azuredevops"
version = ">= 0.4.0"
}
azurerm = {
source = "hashicorp/azurerm"
version = ">= 3.49.0"
}
}
}
provider "azurerm" {
features {}
}
provider "azuredevops" {
org_service_url = var.AZDO_ORG_SERVICE_URL
personal_access_token = var.AZDO_PERSONAL_ACCESS_TOKEN
}
Main.tf
### RESOURCE GROUP
resource "azurerm_resource_group" "resourcegroup" {
location = "norwayeast"
name = "rg01"
}
### STORAGE ACCOUNT
resource "azurerm_storage_account" "stg" {
name = var.storageAccount_name
resource_group_name = azurerm_resource_group.resourcegroup.name
location = var.location
account_tier = "Standard"
account_replication_type = "LRS"
}
### CONTAINER
resource "azurerm_storage_container" "cont" {
name = var.container_name
storage_account_name = azurerm_storage_account.stg.name
container_access_type = "private"
}
### KeyVault
resource "azurerm_key_vault" "kv" {
name = var.keyvault_name
location = var.location
resource_group_name = azurerm_resource_group.resourcegroup.name
tenant_id = var.tenant_id
sku_name = "standard"
enabled_for_deployment = true
enabled_for_disk_encryption = true
enabled_for_template_deployment = true
purge_protection_enabled = false
}
# Access Policy KV
resource "azurerm_key_vault_access_policy" "Current" {
key_vault_id = azurerm_key_vault.kv.id
tenant_id = var.tenant_id
object_id = data.azurerm_client_config.current.object_id
}
resource "azurerm_key_vault_access_policy" "SPNAccess" {
key_vault_id = azurerm_key_vault.kv.id
tenant_id = azurerm_key_vault.kv.tenant_id
object_id = azuread_service_principal.tfazSPN.object_id
secret_permissions = [
"Get",
"List"
]
storage_permissions = [
"Get",
"List"
]
}
# SPN
resource "azuread_application" "tfazSPN" {
display_name = var.AzureAD_ApplicationName
}
resource "random_string" "password" {
length = 32
special = false
}
resource "random_password" "password" {
length = 32
special = true
override_special = "!@#%&*-_+:?"
}
resource "azuread_service_principal" "tfazSPN" {
application_id = azuread_application.tfazSPN.application_id
}
resource "azuread_service_principal_password" "tfazSPN" {
service_principal_id = azuread_service_principal.tfazSPN.id
end_date = var.AzureAD_SPN_Password_Expiry
}
resource "azurerm_role_assignment" "main" {
principal_id = azuread_service_principal.tfazSPN.id
scope = azurerm_key_vault.kv.id
role_definition_name = "Contributor"
}
Variable Group
resource "azuredevops_variable_group" "varGroup" {
project_id = azuredevops_project.adoproj.id
name = "Terraform Sensitive Variables"
description = "This Variable Group should be linked to an Azure Key Vault"
allow_access = true #Boolean that indicate if this variable group is shared by all pipelines of this project.
key_vault {
name = azurerm_key_vault.kv.name
service_endpoint_id = azuredevops_serviceendpoint_azurerm.AzSPN.id
}
variable {
name = "SASKey"
}
variable {
name = "SPNPwd"
}
variable {
name = "VMAdminPwd"
}
}
Variables
variable "client_secret" {
type = string
default = ""
description = "description"
}
variable "tenant_id" {
type = string
default = "tentant_id"
description = "description"
}
variable "subscription_id" {
type = string
default = "subscription_id"
description = "description"
}
variable "client_id" {
type = string
default = ""
description = "description"
}
variable "object_id" {
type = string
default = ""
description = "description"
}
variable "environment" {
type = string
default = "dev"
description = "description"
}
variable "location" {
type = string
default = "norwayeast"
description = "description"
}
variable "storageAccount_name" {
type = string
default = "tfaz01stg"
description = "description"
}
variable "container_name" {
type = string
default = "cont01"
description = "description"
}
variable "keyvault_name" {
type = string
default = "kv01h"
description = "description"
}
variable "AZDO_PERSONAL_ACCESS_TOKEN" {
type = string
default = "*******"
description = "description"
}
variable "AZDO_ORG_SERVICE_URL" {
type = string
default = "https://dev.azure.com/*****"
description = "description"
}
variable "AZDO_GITHUB_SERVICE_CONNECTION_PAT" {
type = string
default = "***"
description = "description"
}
variable "name" {
type = string
default = ""
description = "description"
}
variable "AzureAD_ApplicationName" {
type = string
default = "tfazSPN"
description = "description"
}
variable "AzureAD_SPN_Password_Expiry" {
type = string
default = "2028-01-01T01:02:03Z"
description = "The End Date which the Password is valid until, formatted as a RFC3339 date string (e.g. 2018-01-01T01:02:03Z)."
}
Tried various commands to implement these resources via terraform but no luck