Terraform on Azure not creating certificate as PKCS12

125 Views Asked by At

I'm trying to create a Terraform script which will by driven by a yml pipeline in Azure DevOps. It needs to create a pfx self signed certificate to be used for certificate based authentication. The script below will create a certificate, but it doesn't seem to create a pfx even though I've set the secret_properties content type.

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "=3.89.0"
    }
  }

}

provider "azurerm" {
  features {
    # key_vault {
    #   purge_soft_deleted_certificates_on_destroy = true
    #   recover_soft_deleted_certificates          = true
    # }
  }
}

# Required so that the tenant_id element can be dynamically added
data "azurerm_client_config" "current" {}

resource "azurerm_resource_group" "mtc-rg" {
  name     = "mtc-resources"
  location = "Australia Southeast"
  tags = {
    environment = "dev"
  }
}

resource "azurerm_key_vault" "mtc-keyv" {
  name                = "mtc-keyvault"
  location            = azurerm_resource_group.mtc-rg.location
  resource_group_name = azurerm_resource_group.mtc-rg.name
  tenant_id           = data.azurerm_client_config.current.tenant_id
  sku_name            = "standard"

  soft_delete_retention_days = 90
  purge_protection_enabled   = true # <------ TODO

  access_policy {
    tenant_id = data.azurerm_client_config.current.tenant_id
    object_id = "<< user object_id here >>"

    certificate_permissions = [
      "Create",
      "Delete",
      "List",
      "Get"
    ]
  }
}

resource "azurerm_key_vault_certificate" "mtc-cert" {
  name         = "snoogans"
  key_vault_id = azurerm_key_vault.mtc-keyv.id

  certificate_policy {
    issuer_parameters {
      name = "Self"
    }

    key_properties {
      exportable = true
      key_type   = "RSA"
      key_size   = 2048
      reuse_key  = false
    }

    secret_properties {
      content_type = "application/x-pkcs12"
    }

    lifetime_action {
      action {
        action_type = "AutoRenew"
      }

      trigger {
        days_before_expiry = 30
      }
    }

    x509_certificate_properties {
      # Adjust the subject, validity period, etc., as needed
      subject            = "CN=SomeSubject"
      validity_in_months = 60

      key_usage = [
        "digitalSignature",
        "keyEncipherment",
      ]

      # serverAuth OID = 1.3.6.1.5.5.7.3.1
      extended_key_usage = ["1.3.6.1.5.5.7.3.1"]
    }
  }

  depends_on = [
    azurerm_key_vault.mtc-keyv,
  ]

}

I've been running azure cli scripts after running the tf to download the certificate so I can export the public key and encode as base 64 to provide to the team who manage the department's token server. I require this certificate to be pfx so my .NET Core REST API can fetch the certificate from Azure and generate a jwt (requiring the private key) which is then passed with an auth request to the token server which then verifies the jwt with the previously exported public key.

So, after downloading the certificate from azure I can't export as it's apparently in the wrong format. I checked in the Azure Portal KeyVault and I can see the option to download the pfx is disabled.

enter image description here

Can anyone see in my tf what I'm missing?

1

There are 1 best solutions below

1
Vinay B On BEST ANSWER

I tried to create certificate as PKCS12 on azure key vault using terraform and I was able to provision the requirement successfully

You have mostly configured the script correctly, using the secret_properties block to set the content type to application/x-pkcs12, which is the MIME type for PFX files.

One possible reason why the download as PFX option is disabled in Azure Portal is that the certificate's private key is either unavailable or not marked as exportable. You have specified exportable = true under key_properties in your Terraform code, which should make the private key exportable. However, if the problem persists, you can try the following steps:

  1. Permissions: The Terraform script should run with a service principal or a user who has the right permissions to generate and export keys and certificates from the Key Vault.

  2. Azure CLI or SDK: To fetch the certificate using Azure CLI or any SDK, you need to use the correct commands and have the appropriate permissions.

My terraform configruation:

provider "azurerm" {
  features {}
}

data "azurerm_client_config" "current" {}

resource "azurerm_resource_group" "example" {
  name     = "mtcvk-resources"
  location = "east us"
}

resource "azurerm_key_vault" "example" {
  name                        = "mtcvk-keyvault"
  location                    = azurerm_resource_group.example.location
  resource_group_name         = azurerm_resource_group.example.name
  tenant_id                   = data.azurerm_client_config.current.tenant_id
  sku_name                    = "standard"
  soft_delete_retention_days  = 90
  purge_protection_enabled    = true

  access_policy {
    tenant_id           = data.azurerm_client_config.current.tenant_id
    object_id           = "enter your user or SP object ID"
    key_permissions     = ["Create", "Get", "Delete", "List", "Update", "Import", "Backup", "Restore", "Recover"]
    secret_permissions  = ["Set", "Get", "Delete", "List", "Recover", "Backup", "Restore"]
    certificate_permissions = ["Create", "Delete", "Get", "List", "Update", "ManageContacts", "GetIssuers", "ListIssuers", "SetIssuers", "DeleteIssuers"]

  }
}

resource "azurerm_key_vault_certificate" "example" {
  name         = "snoogans"
  key_vault_id = azurerm_key_vault.example.id

  certificate_policy {
    issuer_parameters {
      name = "Self"
    }

    key_properties {
      exportable = true
      key_type   = "RSA"
      key_size   = 2048
      reuse_key  = false
    }

    secret_properties {
      content_type = "application/x-pkcs12"
    }

    lifetime_action {
      action {
        action_type = "AutoRenew"
      }

      trigger {
        days_before_expiry = 30
      }
    }

    x509_certificate_properties {
      subject            = "CN=SomeSubject"
      validity_in_months = 60
      key_usage          = ["digitalSignature", "keyEncipherment"]
      extended_key_usage = ["1.3.6.1.5.5.7.3.1"]
    }
  }
}

Output:

enter image description here

enter image description here

enter image description here

enter image description here