Mark
Mark

Reputation: 560

Adding Azure Web App Service Custom Domain during Devops Deployment

An App Service custom domain requires validation at deployment time which in turn requires a DNS CNAME to point to the new app service name. The app service name is, however, created dynamically, so we do not know the name it will have at deployment time. This https://learn.microsoft.com/en-us/azure/app-service/manage-custom-dns-migrate-domain almost solves the problem but it also requires you to know the app service name prior to deployment.

I have tried an App Gateway instead to sit in front of the App Service and editing the URLs in in a rewrite rule. This partially works but unfortunately, it has a documented bug where if there are many Set-Cookie to rewrite, it rewrites the first and deletes the rest. Therefore, we cannot rewrite headers on the App Gateway (until such time as MS fix the bug) and have instead to send the public URL all the way to the back end App Service, hence why we need the custom domain defined on the App Service itself.

The question is: how do I create a Custom Domain on an App Service the the time of deployment using Azure Devops if I do not know the name of the App Service until it is created?

Upvotes: 5

Views: 2642

Answers (3)

CaptainStealthy
CaptainStealthy

Reputation: 388

I ran into the same issue as you, OP - and like you, I felt it was utterly pointless to attempt applying custom DNS config through a pipeline at all if it was necessary to create the DNS record by hand. What's the point of CI/CD then?!

My company's DNS runs through Cloudflare, so my solution to this problem is...

  • Create an API Token in Cloudflare with permission to manage DNS for the domain in question - stored in Azure Key Vault, and injected into the pipeline with a variable group (via a service connection)
  • Deploy an initial ARM template that contains just the resources, including the App Service(s), without any DNS config applied
  • The initial ARM template declares output variables for the website name, app service plan name, custom domain verification ID, and anything else needed further down in the pipeline
  • I wrote a PowerShell script that takes the output variables from the previous step, and makes REST calls to Cloudflare to check if the CNAME and TXT records exist - if they don't, create them. If they do, update them. (Because maybe something changed!)
  • Deploy a second ARM template that simply applies the custom domain config to any app services it needs to

I have currently got my pipeline to the point where its updating DNS in Cloudflare - I have an error in the second template deployment, because I forgot to pass its parameters, heh.

It's not 100% ideal, but it's a solid workaround, IMO, and requires no manual steps. I'll report back when I'm completely finished with it, and I'm happy to share code snippets at that time if you need them.

EDIT: This solution appears to have worked! I've deployed the app I was working with to two brand new environments that had no resources provisioned at all, and no pre-existing DNS entries. Everything worked perfectly!

EDIT2: I should mention, I went through this process a second time for a different project - but I used Terraform instead, and it was a far smoother experience! No need to mess with PowerShell or nested deployments at all! Everything just worked! :)

Upvotes: 1

Mark
Mark

Reputation: 560

I consider this more of a "workaround of a serious limitation" than a true "answer" because although Microsoft have recently made some changes to the verification process, they do still require verification, which works against the ethos of a CI/CD pipeline. My hope is that in the future, they allow trusted processes to bypass the domain ownership verification. In the meantime, as a workaround, we simply moved the DNS to Microsoft themselves - namely Azure DNS. Azure DNS meets our HA requirements but note that it does not (yet) support DNSSec. Once that was done, we modified our pipeline thus:

  • Deploy App Service (via ARM template in our case but the CLI would suffice)
  • Parse the name via the ARM Output to create a variable from the App Service name (via a bash script in our case)
  • Create a single awverify CNAME record in Azure DNS (using the CLI)
  • Add a 60 second delay task
  • Do all the other pipeline tasks at this point (we have quite a few so it eats up time)
  • Add the custom domain name to the App Service (using the CLI)
  • Upload and bind the SSL certificate (again using the CLI)

In this case, there is enough of a gap between the awverify record and the custom domain name tasks. We have run this pipeline many times and not had a failure (well, not for this reason anyway! ;-) ), so it it possible that the 60 second delay can be lowered. I believe that having it in Azure DNS also helps reduce the delay, though I have not proven this.

Upvotes: 0

Simon Ness
Simon Ness

Reputation: 2540

Maybe there are a couple of options, there is ARM template support or a CLI command. Both of which can be automated from Azure DevOps using either the AzureResourceGroupDeployment@2 task or the AzureCLI@2 task respectively.

Note that when you create an app service it is possible to specify the name as long as it is unique (see CLI ref or the first parameter in the ARM template).

Hope this helps!

Upvotes: 0

Related Questions