NightOwl888
NightOwl888

Reputation: 56909

Get the latest version of a certificate from an Azure key vault in an ARM template

Creating an ARM template that needs to install an SSL certificate that is located inside of an Azure key vault. If I specify the certificate with the thumbprint, it works fine:

https://contoso.vault.azure.net/secrets/web01-test-contoso-com/968bf207451149d3aceb390065af9d3a

But as a certificate is on a ticking clock, this hard-codes a dependency that can go stale into the ARM template. I would rather just specify the latest version (like it shows in the portal). However, I haven't found any documentation that shows how to do that or even mentions if it is possible.

I ran a couple of experiments using:

https://contoso.vault.azure.net/secrets/web01-test-contoso-com

and

https://contoso.vault.azure.net/secrets/web01-test-contoso-com/latest

But in both cases, I got the same error message:

message '{
   "error": {
     "code": "InvalidParameter",
     "message": "https://contoso.vault.azure.net/secrets/web01-test-contoso-com/latest is 
 not a valid versioned Key Vault Secret URL. It should be in the format 
 https://<vaultEndpoint>/secrets/<secretName>/<secretVersion>.",
     "target": "certificateUrl"
   }
}'

So my question is: How can I reference the certificate in a way that I get the latest version?

For clarity, I am using the URL in the secrets section of the ARM template for a VM as follows, which gets the certificate from the Azure key vault and installs it into the Windows certificate store.

"secrets": [
    {
      "sourceVault": {
        "id": "[resourceId(parameters('keyVaultResourceGroupName'), 'Microsoft.KeyVault/vaults', parameters('keyVaultName'))]"
      },
      "vaultCertificates": [
        {
          "certificateUrl": "https://contoso.vault.azure.net/secrets/web01-test-contoso-com/latest",
          "certificateStore": "My"
        }
      ]
    }
]

NOTE: I would find it odd that you can specify the latest version of an OS to install, but you cannot specify to install the latest version of a certificate.

Upvotes: 10

Views: 3751

Answers (4)

Mani Raj
Mani Raj

Reputation: 21

secretUriWithVersion worked. bicep equivalent script:

resource regionalKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = {
  name: keyVaultName
}

resource serviceFabricClusterCert 'Microsoft.KeyVault/vaults/secrets@2021-06-01-preview' existing = {
  name: certificateName
  parent: regionalKeyVault
}

vaultCertificates: [
{
certificateStore: certificateStore
certificateUrl: serviceFabricClusterCert.properties.secretUriWithVersion
} ```

Upvotes: 1

oderibas
oderibas

Reputation: 2104

It is possible, contrary to what accepted answer says . Define variable with secret's resource id like this, for example:

"mySecretResourceId": "[concat(resourceGroup().id,'/providers/Microsoft.KeyVault/vaults/', variables('keyVaultName'), '/secrets/', 'my-secret-name')]"

then you can use it in your template as following:

"certificateUrl": "[reference(variables('mySecretResourceId'), '2018-02-14').secretUriWithVersion]"

Upvotes: 7

Mr. NoNe
Mr. NoNe

Reputation: 51

According to @4c74356b41's aswer I did it by my self in python script.

      data = json.loads(kv_auth_response.content)
      #
      ## Lets find youngest vesrion of certificate
      #
      if len(data['value']) > 0:
         for x in range(len(data['value'])):
             if x == 0:
                youngest = data['value'][x]['attributes']['exp']
                cert_url = data['value'][x]
             if data['value'][x]['attributes']['exp'] > youngest:
                youngest = data['value'][x]['attributes']['exp']
                cert_url = data['value'][x]
         arry = cert_url['id'].split('/')
...
         cert_version = arry[len(arry)-1]

At the first step of the loop, value of expire date is assigned to the "youngest" variable. In the next steps script compares expire date with it and assigns when the condition is met. After loop script splits with "yougests" cert_url and assigns last part of array to "cert_version" variable.

Full view of this problem you can see in my script to BYOC for custom domain. Link: https://github.com/przemika/azure-byoc-for-custom-domain/blob/master/start-byoc.py

Upvotes: 0

4c74356b41
4c74356b41

Reputation: 72191

There is no direct\easy way of doing this. Key Vault isnt exactly arm template friendly.

As juunas proposed you can write a script or use custom script extension to pull that data directly from key vault using managed service identity, for example.

Upvotes: 1

Related Questions