
What is Azure DevOps?
“Azure DevOps provides developer services for allowing teams to plan work, collaborate on code development, and build and deploy applications. Azure DevOps supports a collaborative culture and set of processes that bring together developers, project managers, and contributors to develop software. It allows organizations to create and improve products at a faster pace than they can with traditional software development approaches.” — What is Azure DevOps? — Azure DevOps | Microsoft Docs
Azure DevOps is a great tool to use for IaC, as it is for other DevOps use cases. Whilst I’m not going to dive deep into the security aspect of DevOps, it’s important it is considered should you wish to implement it into production.
Whilst automation and “DevOps” brings innovation, it also brings different attack vectors. These may not match your traditional security model. Below is a simple diagram that I created to highlight some of the concerns you may need to address.

Or there is a nice diagram here of potential tools:

You didn’t come here for an explanation though, so let’s run through how to create infrastructure using Azure Devops.
For now, I will assume you’ve created you organisation within Azure DevOps, and can view the portal. You must also be aware that there are several ways to do it. The below is a simple example of one way which may not be ready for production. This is because it’s a manual effort to show some of the stages.
Let’s Begin
Under project settings, you will see Service Connections. Here we need to set one up for Azure Resource Manager:

DevOps will recommend the Automatic Service Principal, but it’s up to you which you chose:

Next we will setup our Repo. First this, I will use the Azure DevOps repo but again, it’s up to you. If this is new, it might be worth transferring to the Devops for now.


Now we have our connections and code, let’s create our Pipelines. Go to Pipelines and create a New Pipeline:

For this example I’m going to use the classic editor:

Once clicked, the GUI will change and you will be able to select your repo. Again, for this example, I’m using the Azure Repo:

Once selected, I want to create with an Empty job:

First things first, let’s add the names and leave the defaults:

Since it’s a windows 2019 server, I’ve called it Windows-Agent (Left).
Now let’s add a Task. Click the + and search for “Arm template”

Find ARM Template Deployment and click Add.
Here we can update our details. The connection references back to the start where we created the service connection. Follow the drops downs and select your options.

Under the template section, we can point to our repo. It does allow us to override now, but instead I’m going to do that within the release.

To show an example, I’ve created a variable called “Location”:

Here, I can add this into the override parameters to set the location. We reference our variables using the format: $(variable).

For deployment mode, I’m going to set it to Validation only
The next step is to Publish, so for this, we add a new task. Search for “publish” and add Publish Pipeline Artifacts:

Here, we can fill in the details pointing to our template:

For the Artifact name, I use another variable called environment, which set’s it to “dev”. You don’t need to do this, I’m just showing more examples of using variables.

Once happy, press save & queue.
[!] If you come across this error, you will need to submit a form for free access to the agent:

After filling out the form, Microsoft granted me access. For me, it took around 48 hours, but some get it much sooner.
Once I ran it again, I passed the validation:

Next, we want to create the Release: Go to Release and create a New pipeline:

Let’s select an Empty job

Once done, we need to add the names:

Under Variables, we want to add the variables we used earlier:

Next, we want to reference our artifact. Click on Add an artifact and find your source (Build pipeline we created earlier). Click Add once populated.

Next, click on your stage so that we can add a job.

Once in, we need to add the same as we did before: ARM Template Deployment as a task:

Once added, let’s populate as we did previously with a name, resource group and subscription (Service connection):

The difference this time is that our source will be the linked artifact:

If you did want to future plan this to break this out into dev & prod, you could use a variable:

For this walkthrough, I’ve been naming the environment variable the same (dev).
Here is where I’m going to add the override parameters I talked about earlier. I had previously copied the list from the “build” pipeline so that I can set them at the release.
The below shows me setting parameters for a storage account. As you can see, I include some variables:

Once you are happy with yours, click save and release:

Normally you would have this triggered, but for now we are kicking it off manually.

Once kicked off, we wait:

If all is good, we will see “Succeed”:

Once you do, head over to the Azure portal and check your resource:

I hope it worked out well for you. Again, this is a simple breakdown of one way you can run IaC using Azure Devops. Of course, for production you would need to modify several stages and ensure you have your security controls enabled. You would also look to automate the deployment perhaps. There are lots of integration points for Azure DevOps which can help move away from needing to distribute licenses per user (Azure Devops). Power Automate being one of them.
If you like my content, please remember to clap 👏 and follow! 😁
If you have any requests or content you wish for me to cover, simply drop my an email at contact@xstag0.com or visit DevSecAsh! 🦌
Leave a Reply