Previously

In the previous article I talked about hosting a simple static html website in an Azure Static Web App and how to set it up in the Azure Portal.

Hosting a simple website in Azure Static Web Apps

Intro & Goal

In this article I want to extend what I did in the previous article. I'm going to talk about Infrastructure as Code and how to deploy your infrastructure using Bicep instead of deploying it manually in the Azure Portal.

Bicep is awesome. And sometimes a pain in the ass. But still awesome.

I'm not talking about the physical part of a persons body but rather a domain-specific language that allows you to deploy Azure Resources in the Cloud. Bicep removes all the tedious work you have to do when using ARM templates, the original Azure deployment language. It's actually an abstraction layer build on top of ARM templates and provides an easy programmable interface that most developers get used to really quickly. I'm not going to dig deeper into ARM templates beacuase I have little experience with it and honestly, it gives me headaches when I look at it. But in case you're interested in what it is and how Bicep relates to it, check out the Azure ARM Documentation.

Last year I really got a deep dive into working with Bicep. It was always on my wishlist and I should have started with it earlier, but then again, time always plays a big role in that. So then I thought, maybe I should apply the practice to my company website https://www.theridion.it, which is a simple use case.

Why IaC?

I-a-What? Another abbreviation to remember? Ah yes, Infrastructure as Code.

IaC is a DevOps practice that allows you to manage and provision your infrastructure through code. And why would anyone do that? Well, it has a lot of advantages over managing your infrastructure manually.

  • First of all, it's code, which means you keep it in a repository. You can keep track of changes and you can easily revert to a previous version. It also serves as documentation for your infrastructure.
  • It's less error prone. Performing manual steps can lead to errors and inconsistencies. When you write your infrastructure as code, it can be reviewed and tested before it's deployed.
  • You can deploy your infrastructure over and over again without having to worry about forgetting a step. It's idempotent, meaning it will always have the same result.
  • It allows you to easily deploy your infrastructure for different scenarios like test environments or recovery after a disaster.
  • Security best practices can be applied from the start to make sure that your infrastructure is secure.
  • It's a lot faster to deploy your infrastructure through code than manually.
  • And the list goes on and on... Do you still need convincing? Be sure to check out the Documentation on Azure.

This doesn't mean you should never use the Azure Portal again, though. Some use case are better suited for the portal. For example, when you want to test something quickly or when you want to deploy a resource without having the hassle of writing code and pipelines.

Azure DevOps Documentation

Check What is infrastructure as code (IaC)? for more details about IaC

Why Bicep then?

Well, Bicep has been on my radar for a while. I first saw it at an awareness session at Techorama Belgium a couple of years ago, when it first came out. It immediately attracted my attention and curiosity. At that time I was working at a client and we were planning on migrating all our Azure ARM templates for the application landscape. But then I left that client, and I never got to put the theory into practice. Fast forward a little bit, and there I am, eye in eye with Bicep.

Are there other solutions to deploy infrastructure? Yes, of course there are. There's also Terraform, and probably more. But I've built up my knowledge in Bicep and I kind of like it so far. So there's no need for me to change again.

Now what are the benefits of Bicep?

  • The learning curve is a lot less steep than ARM templates.
  • The code is definitely a lot more readable than ARM templates.
  • It's less error prone than ARM templates and easier to maintain.
  • You have one entry point which orchestrates the deployment. So you don't have to worry about the complexity of the infrastructure.
  • You can easily validate and preview your changes before executing the deployment.
  • There's a lot of documentation available on the Microsoft Azure website.

Azure Bicep Documentation

Check What is Bicep? for more details about Bicep

Prerequisites

There are a couple of things, which are important, that we need to get out of the way first.

  • An existing Azure subscription of course.

    Azure Account

    Check Build in the cloud with an Azure free account to find out more details about Azure and how to sign up for an account
  • A place where you store your code and pipelines, I'm using Azure DevOps but you can use whatever you want.

    Azure DevOps Documentation

    Check Azure DevOps Documentation for all features provided by Azure DevOps

You also need to install a couple of tools. Make sure you install the following tools to be able to execute everything correctly. I'm including the versions that I have installed at the time of writing the article.

  • Azure CLI (Windows) - version 2.56.0

    Azure CLI

    Check Install Azure CLI on Windows to find out more details about installing Azure CLI
  • Bicep CLI - version 0.24.24

    Azure Bicep Documentation

    Check Install Bicep tools to find out more details about installing Bicep CLI
  • DevOps Azure CLI - version 0.26.0

    Visual Studio Code

    Check Get started with Azure DevOps CLI to find out more details about installing DevOps CLI
  • Visual Studio Code - version 1.85.2

    Visual Studio Code

    Check Install Visual Studio Code to find out more details about installing VisualStudio Code
  • Visual Studio Code - Azure Account Extension - version 0.11.6

    Azure Account Extension

    Check Install Azure Account Extension to find out more details about installing Azure Account Extension
  • Visual Studio Code - Azure Resource Manager (ARM) Tools Extension - version 0.24.24

    Azure Resource Manager (ARM) Tools Extension

    Check Install Azure Resource Manager (ARM) Tools Extension to find out more details about installing Azure Resource Manager (ARM) Tools Extension
  • Visual Studio Code - Bicep Extension - version 0.24.24

    Bicep Extension

    Check Install Bicep Extension to find out more details about installing Bicep Extension
I hope I didn't forget anything though.

Bicep Modules

Ok finally, we can start writing Bicep modules. In my use case, my company website is hosted in an Azure Static Web App. And the only additional thing we need, apart from the Azure subscription of course, is a resource group.

So let's start with that. Create a new folder structure .azuredevops/infrastructure or anything else you feel comfortable with. In the infrastructure folder, create a new file called main.bicep and add the following content: main.bicep. I hosted the files on my Github account so you can easily download them, follow along or adapt to your own use case as you see fit.

This file contains the Bicep code to deploy a Resource Group and a Static Web App into that Resource Group.

Create an additional file called main.parameters.json accompanied with the main.bicep file and add the following content: main.parameters.json. This file contains the parameters that are required to deploy the Resource Group and Static Web App. I'm going to keep it simple and hardcode these parameters into the main.parameters.json file. You can adapt the ones that really matter to your specific use case like the resourceGroupName, staticWebAppName and the repositoryUrl.

The only parameter that might pose a problem when hardcoding these parameters is the repositoryToken parameter. This is a Personal Access Token (PAT) that is required to authenticate with Azure DevOps when deploying the Static Web App. It's a secret, so storing this in the code is not a good idea.

In the previous article Hosting a simple website in Azure Static Web Apps, I discussed the PAT that is magically created when deploying an Azure Static Web App from the Azure Portal. But when you are deploying the Bicep from your local machine or from a pipeline, you need to provide the PAT yourself. We'll get to that later.

Azure Bicep Documentation

Check Understand the structure and syntax of Bicep files for more details about Bicep

Azure Bicep Documentation

Check Bicep CLI commands for more details about Bicep CLI

Azure Resource Templates

Check Microsoft.Web staticSites for more details about the StaticSites template

Microsoft Bicep Modules library

You might have noticed in the main.bicep that it's fairly simple. There's just a reference to a Resource Group module and a Static Site module. But then you might be asking, what are these modules and where do they come from? Very good question. These modules are part of a Microsoft Bicep Modules library called Azure Verified Modules. Microsoft did a real good job creating a set of common modules of practically all Azure Resources that you can freely use to deploy your infrastructure.

I do have a small remark though. At the time of writing this article, the AVM library is still under development and not all modules are available yet. Previously, Microsoft had the CARML library and is migrating everything to the AVM library. Not all modules have been migrated yet. But the ones I needed for my use case were already available, lucky me.

So how do you use them? Well, there are different scenario's you can implement.

  • You can reference them using the Microsoft's Public Bicep repository (but still not ready yet either).
  • You can copy all the modules to a dedicated repository, publish them to an Azure Container Registry you own and reference them from there.
  • Or you can download the modules and reference them locally in your code. That's what I'm going to do now. I'm going to keep it simple, I just need 2 modules anyway.
Keep in mind that when you copy or host them yourself, you are also responsible for maintaining them and keeping them up to date. You just need to reference them in your main.bicep file and you're good to go. The only thing you need to do is to provide the required parameters for the module to work. You can find all the required parameters in the documentation of the module. I'm using Static Site module and Resource Group module.

CARML

Check Common Azure Resource Modules Library for more details about CARML

AVM

Check Azure Verified Modules for more details about AVM

AVM - Resource Group

Check Resource Group for more details about Resource Group modules

AVM - Static Site

Check Static Web App for more details about Static Web App modules

Create a Personal Access Token

Now that we have our Bicep code ready, we can almost deploy it. We still need to create a Personal Access Token (PAT) in Azure DevOps first. The following steps were taken:

  1. In Azure DevOps, navigate to User Settings in the top right menu and then select Personal Access Tokens.
  2. Click + New Token and fill in the properties.
  3. Name: fill in an easily identifyable name. I'm using Static-Web-App-TheridionIT-Infrastructure-Deployment-Token.
  4. Organization: Select your Organization.
  5. Expiration: Select a custom defined date as far as possible in the future. Keep in mind that this needs to be monitored afterwards.
  6. Scopes: Select Custom defined and add the following scopes: Build: Read & execute, Code: Full, Variable Groups: Read, create & manage.
  7. Click Create and copy the token somewhere safe. We will use it later. Keep in mind that you won't be able to see it again once you click Close.

Remember, this PAT is used to authenticate with Azure DevOps when deploying the Static Web App. There's just 1 tiny caveat. The PAT is required as a parameter in the Bicep code. We shouldn't just put it in the code, that's the worst thing you could do. But bare with me, for the sake of simplicity and demonstration, I'm going to do it anyway. I'll explain later how to do it the right way. Copy the token value into the main.parameters.json file in the repositoryToken field and save it. Don't commit it to your repository though, for obvious reasons.

Azure DevOps Documentation

Check Use personal access tokens for more details about Personal Access Tokens (PAT) in Azure DevOps

Deploy the Bicep

There are several ways to deploying your Bicep code. For now, I'm just going to deploy it from my local machine using the Azure CLI. This allows you to validate and test your Bicep code. We're going to move this to a pipeline later. It's a good practice to validate and test your code from your local machine before executing through a pipeline, so you don't waste any resources in Azure DevOps.

First of all, when you finished creating your Bicep file, open up a Windows Powershell terminal and navigate to the infrastructure folder. Make sure you installed the Azure CLI and logged in to your Azure subscription. The commands that follow below can also be found in Github in the readme.md.

You can first validate the Bicep locally using the following command:
az bicep build --file main.bicep

In case there are still errors in your code, you can fix first them and validate again. This command also generates the ARM template that will be used to deploy the infrastructure. You'll see that this is less intuitive than the Bicep code.

Once the validation is successful, you can do a deployment preview using the following command:
az deployment sub what-if --location westeurope --template-file .\main.bicep --parameters .\main.parameters.json --name ($(Get-Date -Format yyMMddhhmmss)+'-test')

The what-if command allows you to preview the deployment without actually deploying it. This isn't always 100% accurate though. When your working with permissions and access roles, it doesn't always reflect the actual situation. But it gives you a good idea of what will be deployed.

If you're happy with the result, you can deploy the infrastructure using the following command:
az deployment sub create --location westeurope --template-file .\main.bicep --parameters .\main.parameters.json --name ($(Get-Date -Format yyMMddhhmmss)+'-test')
As you can see in the Bicep, the scope is set to subscription, this will deploy the infrastructure in Azure at subscription level.

Azure Resource Manager Documentation

Check az deployment sub for more details about deploying to a subscription using the CLI

Verify the deployment

You can wait for the deployment to finish in the Powershell window or you can check the status of the deployment in the Azure Portal. Deployments in Azure is a section you can find at Subscription or Resource Group level in the left menu. They allow to see the status of the deployment and the result. You can also find input and output parameters of the deployment which is really useful for debugging purposes.

When the deployment is successfully finished, you can check the result by navigating to the Static Web App in the Azure Portal and retrieve the URL in the overview section. The website should be up and running if you have a correct index.html file in the repository.

Azure Resource Manager Documentation

Check View deployment history with Azure Resource Manager for more details about the deployments

Conclusion

Infrastructure as Code offers so many advantages over manual deployments. But a lot will depend on the use case and the complexity of your infrastructure. If you're just deploying a simple resource, it might be faster to do it manually in the Azure Portal. For enterprise environments, IaC is a must.

As far as Bicep is concerned, it sure is a big improvement over ARM templates. The learning curve is a less steep and the code is a more readable. It also opens the door for a lot more people to start deploying infrastructure in Azure. I didn't discuss the differences with other IaC solutions like Terraform beacuase I don't have experience with it, but I'm sure they all have their own advantages and disadvantages, just like Bicep.

In terms of deployment, I discussed how to deploy the Bicep code from your local machine using the Azure CLI. This is a good scenario for testing and validating your code. But if you want to have a more robust solution and want to automate your deployments, you should use a pipeline in Azure DevOps, or Actions in Github.

In the previous article Hosting a simple website in Azure Static Web Apps, I also discussed the fact that some things are magically created behind the scenes when deploying an Azure Static Web App from the Azure Portal. Well, in case you're deploying the Bicep from your local machine or a pipeline, it still creates the Library Variable Group and the deployment file. We'll tidy that up in the next article.

In the next article, I'm going to discuss how to create a pipeline in Azure DevOps to deploy the Bicep code. I'm also going to discuss how to create a Library Variable Group in Azure DevOps to safely store the PAT and how to consume it in the pipeline. Beacuase you definitely don't want to store the PAT in your code.

Documentation Reference

Training Material

Next

In the next article I'm going to discuss how to automate the Bicep deployment using a pipeline.

Infrastructure as Code deployment with Bicep - Part 2: Automating using pipelines