{
  "$type": "site.standard.document",
  "canonicalUrl": "https://johnnyreilly.com/posts/private-bicep-registry-authentication-azureresourcemanagertemplatedeployment",
  "description": "You can deploy Bicep to Azure with the dedicated Azure DevOps task; however authentication to private Bicep registries is not supported.  This post shares a workaround.",
  "path": "/posts/private-bicep-registry-authentication-azureresourcemanagertemplatedeployment",
  "publishedAt": "2023-06-02T00:00:00.000Z",
  "site": "at://did:plc:yy3apqjlms24kso7ahn7lbmb/site.standard.publication/3mova7c4nho2b",
  "tags": [
    "bicep",
    "azure devops"
  ],
  "textContent": "If you deploy Bicep templates to Azure in Azure DevOps, you'll likely use the dedicated Azure DevOps task; the catchily named AzureResourceManagerTemplateDeployment@3. This task has had support for deploying Bicep since early 2022. But whilst vanilla Bicep is supported, there's a use case which isn't supported; private Bicep registries.\n\n\n\n\"Unable to restore the module... Status: 401 (Unauthorized)\"\n\nPrivate Bicep registries are a great way to share Bicep modules across your organisation. We use them in the organisation that I'm part of; it's a good a way to help us move faster and to share common security baselines.\n\nAlas it turns out that the AzureResourceManagerTemplateDeployment@3 task doesn't presently play well with private Bicep registries. This is because it's necessary to authenticate to a private registry before you can consume modules. And that's not supported by the AzureResourceManagerTemplateDeployment@3 task. What does that mean? Well take a look at the following Azure Pipeline:\n\nYou'll note that it passes a Bicep file to the csmFile property. This is the file that will be deployed. But what if that file references modules from a private registry? Well, you'll see an error like this:\n\nAs you can see from the Status: 401 (Unauthorized), we have an authentication problem; the task doesn't know how to authenticate to the private registry.\n\nWorkaround\n\nYou might think, \"oh well that's it then, I can't use private Bicep registries with the AzureResourceManagerTemplateDeployment@3 task\". But you'd be wrong. There's a workaround. Essentially, when the AzureResourceManagerTemplateDeployment@3 task runs, it attempts to restore the modules it needs as a first step to compiling the Bicep in to ARM. But it only does this if it needs to. If we perform the restore manually first, then the task won't need to do it again. That's the trick.\n\nBefore the AzureResourceManagerTemplateDeployment@3 task runs, we can run a task to restore the modules. We can use the AzureCLI@2 task to do this. Here's an example:\n\nWhere service-connection-with-access-to-registry is an Azure Resource Manager service connection using service principal authentication which has access to the private Bicep registry.\n\nSo if the above task runs _prior_ to the AzureResourceManagerTemplateDeployment@3 task, then the modules will be restored and the AzureResourceManagerTemplateDeployment@3 task will be able to compile the Bicep in to ARM and deploy it to Azure. This solves the problem; albeit at the cost of an extra task in the pipeline.\n\nIn the box, in the future?\n\nIt would be tremendous if authentication to private Bicep registries was supported by the AzureResourceManagerTemplateDeployment@3 task. I've raised a feature request for this here. If you'd like to see this too, please do add your voice to the issue.",
  "title": "Private Bicep registry authentication with AzureResourceManagerTemplateDeployment@3"
}