Azure Native Infrastructure as Code for Advanced Practitioners

pazdedav

David Pazdera

Posted on November 26, 2020

Azure Native Infrastructure as Code for Advanced Practitioners

This post was created for the Festive Tech Calendar 2020 event and it is a narrative to the talk I gave at Infrastructure as Code User Group Oslo meetup.

festive-tech-calendar

The purpose is to demonstrate a complex end-to-end scenario for using advanced capabilities of Azure Resource Manager language (like template specs, deployment scopes, functions) and the new ARM DSL language called Bicep. It also tries to demystify a popular opinion that the ARM language is "just a JSON".

All code samples and other content could be found in my repo on GitHub:

GitHub logo pazdedav / iac-meetup-arm

Repository for Infrastructure as Code meetup, demonstrating a complex end-to-end scenario for using advanced capabilities of Azure Resource Manager language (like templateSpecs, deployment scopes, deploymentScripts) and the new ARM DSL called Bicep.

Story

Our story begins when Contoso Corp. (a fictious company) announces their new business strategy with digital transformation, customer obsession, and lean as key pillars. This had a profound impact on both IT and software development organizations at Contoso. Old habits and fixed mindset are no longer acceptable, there is a high pressure on everybody to invest their time to learn and grow.

Our first protagonist, Meghan is a senior engineer who has been with the company for five years. Mat on the other hand is part of a newly formed Central Cloud Team. In his new Cloud Engineer role, he is focusing on security, compliance, and building a 'secure and compliant' cloud platform that will be used by internal teams. He has a strong infrastructure background with two decades of experience managing networks and server infrastructure.

At the beginning of our story, a new cloud governance model has been defined by key stakeholders. This model is partly a re-write of Contoso's existing security policies (adopted for the cloud) that was combined with new regulatory requirements that were introduced to the industry.

Mat's team has an important task now. They must ensure there are reliable controls and audit capabilities enforced on their entire cloud environment, so all systems, apps, and services deployed to the cloud are compliant from Day 1.

Meghan's team has been developing a new application when this change of policies is announced. There is a growing fear that this new policy framework will slow down their progress and introduce many blockers. These concerns were escalated to VP of App Development and it was decided that the Central Cloud Team need to find out a way to support developers while maintaining the governance model as required by the business and industry regulators.

Apart from our two main protagonists, there are other heroes in this story :) :
true-heroes

Policy as Code

Mat's team was busy defining what controls and audit mechanisms they should use in the new governance model. They have done a few experiments, tested several technologies and platform features on Azure, and they decided to use Azure Policies together with Management Groups to apply them at scale, so they could ensure 'Day 1 compliance' for all new subscriptions as well as the existing ones.

They both defined and assigned all their policies in the Azure Portal but they wanted to adopt 'Policy as code' practice to automate definition and assignment workflows and improve change tracking.

The team learned about a new feature, allowing them to export Azure Policy objects (both definitions and assignments) from the Portal to GitHub repo. This feature also creates:

  • a workflow using GitHub Actions that can automate 'deployments' of any changes made in the repo
  • a GitHub secret for authenticating to Azure using a service principal
  • a service principal that was granted the 'Resource Policy Contributor' role, so it can change policies

Mat's team followed the process from the documentation and exported all their policies and assignments to src/policies/ folder in their repo. The workflow YML file can be found here. The workflow is by default configured to be triggered manually, but this can be changed.

run_log

They also published the list of applied policies in their Wiki to make it more readable for non-technical stakeholders.

wiki_policies

Template Library

Being transparent about what policies are applied in the cloud environment (and how they can impact deployments done by internal teams) is a good start, but the Central Cloud Team wanted to increase productivity of app development teams even more, so they decided to introduce a new service called Template Library.

The goal was simple: provide a repository of reusable, dynamic, and security-hardened resource manager templates, fully compliant with the governance model, so they could be used as artifacts for building more complex deployments.

The idea of having reusable artifacts (single resource 'linked' templates that could be referenced from the main template) isn't new, but there are several challenges for adopting this technique.

Mat and his team heard about template specs, a new capability in Azure Resource Manager that allows developers to refer to these artifacts in form of ResourceId that could be referenced in the same way as linked templates but without the need to stage them first to e.g. Azure Blob storage or expose them in a public repository.

The team defined the following requirements:

  • all template specs will be stored in our GitHub repo
  • all changes (to already published versions or new versions) will be pushed to Azure using a workflow after a peer review
  • all developers will be granted a Reader role in the Resource Group where all specs are stored
  • develop an automated way to onboard 'service principals' to the Library for teams that use them in their workflows (pipelines)
  • publish a guide for our internal customers on how to use this Library, so they can start using it
  • if a spec uses a JSON object as a parameter, publish a definition on Wiki that explains the structure of the parameters.

Onboarding workflow

The team defined the following workflow, allowing dev teams to onboard their service principal (typically used in Azure DevOps, GitHub Actions, or any other CI/CD pipelines) to the Library:

  1. Create a new branch in the Central Cloud Team's GitHub repo.
  2. Modify contoso-template-library.prod.parameters.json file by adding objectId of your Service Principal as new array member of servicePrincipals parameter value. You can create your SP by using e.g. az ad sp create-for-rbac --name "{sp-name}" --sdk-auth command.
  3. Create a Pull Request and specify your 'projectId' and 'costPollId' in the description.
  4. When the request is reviewed and approved by our team, it will trigger a workflow that will assign a Reader role to your SP in the context of the Resource Group hosting the Template Library.

sp_onboarding_library

The template file - contoso-template-library.template.json - is a good demonstration of several ARM language features:

  • deployment scopes - allowing to create a Resource Group at the subscription level and assign an RBAC role (as a deployment on Resource Group level), all in one template
  • using comments in several places in the file (ARM allows both single-line and multi-line comments)
  • using functions like if, contains, concat, copy, resourceId, guid, etc.

Using template specs

Now we will switch to Meghan and learn how she used the Template Library provided by Mat's team in her workflow.

First, she used the onboarding procedure and added the service principle used by her team to the Library. Her Pull Request was approved, so she could modify her deployment template - serviceOne.template.json - and referenced 'contosoStorage' spec. Her team is using GitHub workflow to deploy the template to Azure.

contosoOne-template

Since her team uses parameter files (one for each environment), she used the information from the Wiki and correctly defined all required parameters.

Experimenting with Bicep

As part of their continuous improvement principle, Mat's team was eager to learn more about project Bicep, a new DSL language that could simplify authoring of ARM JSON templates.

They started with creating a bicep file that matches with the template spec for "contoso compliant storage account".

bicep_storage_example

All bicep files need to be "transpiled" to ARM JSON templates using bicep build command. This requires Bicep CLI that can be downloaded from the project repo (releases).

The team wanted to build a pipeline (a GitHub workflow) that would on "pull" take all bicep files in the repo (and a specific path, e.g. src/bicep/*), transpile them to ARM JSON files, and deploy them as template specs to Azure to their 'Template Library'.

At that time, the template specs required a special version of Resources PowerShell module (stored in a private repo, they had access to), so they tried to develop a custom action that would contain all required binaries (bicep CLI, Az.Resources module), perform all needed steps, and deploy to Azure using AZ CLI.

They are still working on this improvement idea...

Note: There has been a lot of development in both template specs and Bicep. There are several Actions in GitHub Marketplace (from the community) for working with Bicep files. Also, it is no longer required to have a special version of Az.Resources PowerShell module to deploy template specs, and support for Azure CLI was also added.

Resources

Documentation

Meetup video on YouTube

If you want to watch a video, where I presented this story together with several demos, you can watch it from the recording (my part begins at 8:31 and ends at 1:03:38):

Please note, this wasn't a conference-like session, but a local meetup, so the presentation is not very polished!! As a bonus, you can learn about Farmer from Evgeny Borzenin (@EvgenyBorzenin).

💖 💪 🙅 🚩
pazdedav
David Pazdera

Posted on November 26, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related