Building your Azure Policies (GitHub Actions) - Part 3

5 minute read

As written in part 1, policies are used to maintain the state. The Azure portal itself contains a lot of OOTB policies, but you also want to create and deploy your own. In this article, we will go over how to deploy the policy definitions using GitHub Actions.

In part 2, we deployed the definitions via Azure DevOps pipelines, and for the Github Actions, we will also use the script file. But in GitHub Actions, there is also another option for managing policy definitions.

Prerequisites

  • Service principal in Azure Active Directory
  • Credentials saved wihtin GitHub
  • Access rights in Azure
  • GitHub workflow

First couple of prerequisites

For this test, we will reuse the principal that we created in part 2 of the series. The credentials for this will be saved within a Github Secret.

GitHub Secret

The information for the authentication is saved within so-called secrets that are encrypted within GitHub that are saved on the organization, repository, or repository environment level. The credential information for the authentication against Azure is saved in JSON format.

{
    "clientId": "[clientId]",
    "clientSecret": "[clientSecret]",
    "subscriptionId": "[subscription id]",
    "tenantId": "[Azure Active Directory Tenant Id]"
}

To save the credential information, you can follow the below steps:

  1. Within the GitHub repository go to settings and then secrets.
GitHub Secrets
  1. Click on “new repository secret”
  2. Fill in a name for the secret and use the json object for the value of the secret.
GitHub Actions Secret

Use the Azure steps within GitHub Actions

With the credentials saved, we can get started with the workflow. Let's create a new workflow in the UI and give it a name and file name and remove the information that is not required. To work with Azure, we will use the so-called Azure steps and start with the login step.

Add the 'azure/login' step and connect it to the correct secret. The YAML snippet is below.

- uses: azure/login@v1
      with:
        creds: $.
        enable-AzPSSession: true 

"Make sure you add 'enable-AzPSSession: true' if you want to make use of Azure PowerShell in the workflow."

In this task, you see the reference to the secret we saved in the previous paragraph.

GitHub Actions and Azure PowerShell

If you want to start from GitHub and deploy your definitions that haven't been deployed to Azure yet, you can reuse the script that we used in part 2 and execute it within GitHub actions via the Azure PowerShell Action.

    - name: Run Azure PowerShell script
      uses: azure/powershell@v1
      with:
        inlineScript: |
          ./scripts/azpolicy.ps1 -Scope "$" -ScopeName "$" -PolicyFolder "$"
        azPSVersion: "latest"

We reference the same script file and supply it with the correct arguments in the task. For your reference, the complete Github Actions file would look like below.

name: Policy - All Policies
on:
  workflow_dispatch:
    inputs:
      remarks:
        description: 'Reason for triggering the workflow run'
        required: false
        default: 'Updating Azure Policies'

env:
  Folder: './deploy'
  Scope: 'ManagementGroup'
  ScopeName: '324f7296-1869-4489-b11e-912351f38ead'

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout
      uses: actions/checkout@v2
    - uses: azure/login@v1
      with:
        creds: $
        enable-AzPSSession: true 
    - name: Run Azure PowerShell script
      uses: azure/powershell@v1
      with:
        inlineScript: |
          ./scripts/azpolicy.ps1 -Scope "$" -ScopeName "$" -PolicyFolder "$"
        azPSVersion: "latest"

GitHub Actions and Manage Policy Task

GitHub actions contain a task (Manage Azure Policy) to manage policy definitions, deploy them to the correct scopes, and manage the assignments. The downside of this task is that it requires the definitions to be deployed on Azure because it references the ids.

To use this, it is best to export the definitions from Azure and work in the below folder hierarchy.

Policy structure

The name of the folders refers to the policy names, and the policy.json files contain the information of the policies. These files are the same as shown in part 1, except they have the id, type, and name properties. The task only needs to reference the policy folder, and you are good to go and manage your policy definitions.

name: Policy - All Policies
on:
  workflow_dispatch:
    inputs:
      remarks:
        description: 'Reason for triggering the workflow run'
        required: false
        default: 'Updating Azure Policies'

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout
      uses: actions/checkout@v2
    - uses: azure/login@v1
      with:
        creds: $
    - name: Create or Update Azure Policies
      uses: azure/manage-azure-policy@v0
      with:      
        paths:  |                  
          policies/**

As you can see in the pipeline file, you may have noticed that this pipeline does not reference the management group. This is because the JSON file contains a reference to the id of the existing policy definition, so it knows where it is deployed.

With this task is, you can also manage your assignments by specifying that in the same folder structure when interested, take a look at the page of the extension.

Of course, this is not a production-grade solution, but it gives you the highlights on how to manage your policy definitions in code and how to deploy them.

To be continued