How to – Migrate Azure Firewall from Classic Rules to Policy

If you have been using Azure Firewall since it went GA, you are most likely using the classic option. This means all rules are managed within the Azure Firewall resource itself. As a result, you’ve most likely noticed the below context menu pop up when accessing your resource:

The fact there is a portal driven option I personally think is great. Often “classic to new” scenarios require a rebuild, or several shell based commands. However, I found the docs a bit light in terms of details.

So this post will provide a bit more context. On the portal, you are presented with two options, migrate the existing rules to a new policy, or, attach an existing policy. Meaning you could build your policy from scratch and simply attach it, with the operation then removing the classic rules entirely.

My preference here is to attach an existing policy, however, I am not going to start from scratch. As part of creating a new firewall policy, on the rule tab, you can import your Azure Firewall rules.

This means you can capture your existing configuration, work on any changes in advance, then simply attach your newly updated policy

Two more clicks, and the Azure Firewall will replace the classic rules config with your policy. And this is the really important part – without any downtime. However, ensure you remember with my choice, I am building the policy in advance, if I make changes to that policy, they will be adhered to once live. So your changes may cause impact, but the operation of switching to policy will not.

That’s it, you’re done! A change such as this to Azure Firewall can be a concern, especially if it is handling all of your environment traffic. But this process is simple and straight forward.

As always, if any questions get in touch! Oh and if you would prefer to do this via Powershell, here are the details.

How To – Manage an NSG Using Bicep and Azure DevOps

In many Azure environments that rely on Virtual Networks, Network Security Groups (NSGs) are still king when it comes to access control. However, this post isn’t going to get into the pros and cons of that approach, that’s possibly an entire series, never mind another post!

This post is simply showing a method for managing your NSGs and rules as IaC. Using Bicep, Github and an Azure DevOps Pipeline.

Now, for anyone new to IaC, there is a learning curve. There is also a tradeoff when it comes to effort. It can often be quicker to deploy resources via portal driven methods. However, there are two fundamental reasons to deploy and manage a resource such as an NSG via IaC.

  • BCP – think version history, backup, DR deployments
  • Security – Managed releases/commits control who can approve and change your NSGs

This post keeps it simple, but the principles can expand to managing a full set of NSGs as required. It also includes deploying an empty NSG, which you wouldn’t in theory need either.

As this uses Bicep, let’s take a look at how it handles NSGs and their rules. The NSG itself is quite a simple resource, in my example I am creating it without any config, similar to when you create one in the portal, no rules included.

resource nsg 'Microsoft.Network/networkSecurityGroups@2021-05-01' = {
  name: nsgName
  location: location
  tags: {
    CreatedOn: date
    Owner: email
  }
  properties: {}   
}

However, you can include security rules here as part of the properties section, details on that here. I have chosen not to, as I would like to manage the rules as separate Bicep files. As a result, I need to understand how Parent and Child resources work in Bicep. With this in mind, I have split my rules into two files, inbound and outbound, as this is the core logic split for ACLs on NSGs. You could do this other ways, an allow file, a deny file etc. but this is the one that works best for my brain 🙂

In terms of the file itself, it becomes a collection of bicep resources, each being a rule itself. This gives you full and immediate granularity. I reference the rule priority in my symbolic name to allow for an order of declaration that makes sense to me, but again, lots of options here and no wrong decision. The below are example from my inbound file. I have declared the direction as a variable, as that will always be the same in this file.

resource nsgRule4000 'Microsoft.Network/networkSecurityGroups/securityRules@2021-05-01' = {
  name: '${nsgName}/IN_VNET_Deny'
  properties: {
    access: 'Deny'
    description: 'Deny default VNET traffic'
    destinationAddressPrefix: 'VirtualNetwork'
    destinationPortRange: '*'
    direction: dir
    priority: 4000
    protocol: '*'
    sourceAddressPrefix: '*'
    sourcePortRange: '*'
  }
}

resource nsgRule3000 'Microsoft.Network/networkSecurityGroups/securityRules@2021-05-01' = {
  name: '${nsgName}/IN_Ping_ALLOW'
  properties: {
    access: 'Allow'
    description: 'Allow PING from VNET'
    destinationAddressPrefix: 'VirtualNetwork'
    destinationPortRange: '*'
    direction: dir
    priority: 3000
    protocol: 'Icmp'
    sourceAddressPrefix: 'VirtualNetwork'
    sourcePortRange: '*'
  }
}

Once your files, structure, and rules are created; congratulations! You now have one of the more cumbersome resources for management addressed as code. Giving you quick RTO should it be needed, human readable documentation of your NSG rules, and version history.

How you then control who can edit rules/files by using releases or pull requests etc is up to you and your workflow. But think about including logic to require approvals or at least reviews.

The files I have used as examples are here, again they keep things very simple so if there are questions, get in touch!

How to – Build a Test Azure Network with Bicep

So first, what is Bicep? If you haven’t heard of it, I have to ask – how!? Microsoft’s new deployment language for Azure has made waves since its launch. Continuously improving and taking in a tonne of community feedback it is an interesting offering from Microsoft. To be honest, at first I wasn’t convinced by Bicep. I was slightly confused as to why it was needed. I had put in the time to understand and use ARM templates. I don’t find them super confusing, but I do understand they can be frustrating and quite complex.

That exact point is what Bicep aims to simplify. It uses declarative syntax to deploy Azure resources. This provides concise syntax, reliable type safety, and support for code reuse. Bicep is a transparent abstraction over ARM template JSON and doesn’t lose any of the JSON template capabilities. In plain English, that means that Bicep hides the complexity of ARM templates. Perhaps think of it like shorthand templates 🙂

During deployment, the Bicep CLI converts a Bicep file into ARM template JSON. This means that Bicep has full feature alignment out of the box with all resource types, API versions, and properties that are valid in an ARM template.

This simplicity, combined with a common need to create a small IaaS test area is what lead me to create this post. Below I am going to outline a version of the deployment I use to create a quick and simple test environment. All documented and deployed via Bicep.

First up, what will this environment contain? I’m including resources I find helpful with configurations I find I most commonly need. I am leaving out certain resources that are less cost effective or frequently required (DDoS Standard for example), and I will allow for a conditional deployment of some that I just don’t want to wait on every time. I am looking at you Virtual Network Gateway 🙂

  • Virtual Network
    • Bastion, Gateway, Firewall, Windows, Linux – subnets
  • Windows VM – Server 2019
  • Ubuntu VM – 20.04-LTS
  • Azure Bastion
  • Azure Firewall – Standard | Premium – Conditional based on Parameter
  • VNG – Conditional based on Parameter

So why does Bicep help me with the above? Genuinely I just never got time to create the same in ARM. When working on learning some Bicep I decided to use it as an opportunity to create something useful for myself.

All of the above is written in Bicep and stored in a public repo here. This includes a YAML Pipeline that can allow you test and if successful, deploy the environment to Azure using Azure DevOps. For more on that test stage, see my other post here.

You can see a high-level of the resources that can be deployed below, which I have pulled from the Visualiser function on VS Code:

Without the VNG included, you should see the entire environment built in under seven minutes.

Adding the VNG however will increase this most commonly to at least 20 minutes.

As always, if there are any questions or feedback, get in touch! Happy Bicep-ing! 💪

How to – Control Azure DDoS Plan Deployment using Azure Policy

Recently I saw that there was an update released for an Azure Network Security Demo. This is an excellent lab, with a well maintained repo and several services you can really make use of.

However, I noticed that it includes Azure DDoS Protecting on the Standard tier and does not carry a warning relative to the cost due to pricing model. This is the number one prohibitive factor I see with customers when discussing enabling DDoS Standard. While the resources provisioned as a whole are by no means “cheap” DDoS is the only one that carries a monthly as opposed to hourly rate.

Don’t get me wrong, this isn’t a negative post about DDoS Standard, I think it’s a good service. Take a look at the below benefits it offers over the Basic offer:

Azure DDoS Protection Service Comparison

Also a list of the features and functionality it can provide is here on Docs.

But as I said, the cost is prohibitive, but what does that mean? Well take a look at the breakout of how the service is charged, vs something like Azure Firewall (also included in the lab).

Notice the main difference? It’s how the run rate is calculated. Firewall is per hour and DDoS is per month. This is restrictive, especially on a platform advertised often as “per-minute billing”. However, if you need the services offered, at least at you have a set price. The main challenge is for companies willing to pilot this and being met with this cost. Similarly, labs that include it for a demo that you may only need for a day or even a couple of hours.

Hat tip to Peter De Tender who spotted a change on the FAQs that if only the service is only active for a portion of time, you will receive a pro-rated bill. I haven’t seen this yet in practice, but if it’s public information you should be able to count on it!

So, based on cost alone, perhaps it is justification to block DDoS Standard from being deployed in your subscription? If that is your requirement, it is easily met via Azure Policy. The built-in policy below is perfect for this job

You can then simply choose the DDoS options as your parameters and prevent the service from being activated and avoid a cost shock!

Conversely, regardless of cost, perhaps you need it as part of a compliance or regulatory requirement. If so, Azure Policy can help here too! There are two built-in policies relative to DDoS enablement, however, if you need it to remediate rather than just audit, choose the below policy, ensuring you have a DDoS Plan created in advance.

The final point to note here is that DDoS is recommended as part of the Azure Security Benchmark if you are using Azure Security Center on the Defender tier. It requires Standard to be enabled to meet the control requirement, so be cautious and aware of committing to adhering to this standard!

As always, if there are any questions or feedback please get in touch! And remember, keep using #AZNet for your Azure Networking content!

How to – ARM Template Test Toolkit on Azure DevOps

If you work with ARM templates and Azure DevOps, you know that there is already tight integration between the two. Giving you a pretty simple method of deploying a template via a YAML Pipeline just by plugging in a few details. However, as your pipelines progress in complexity, or perhaps importance, the need for additional services like triggers, filters, and testing becomes apparent.

Having familiarity with ARM templates most likely means you are aware of the test toolkit, if not, here is a link to the docs page explaining what it is, how it works etc.

This post presumes you have knowledge of ARM Template deployment, Azure DevOps Pipelines, and a Project and Repo setup. However, as with any code on a blog, please be careful, use a sandbox first, I cannot help with your production environment. 🙂 If you’re new to this, there is a good tutorial here by Microsoft.

So, with your ARM template ready to go, you can deploy in a single task from a Pipeline. However, if this fails it can cause problems. Generally, more complex Pipelines will include the use of Stages and Jobs. In this example, we’re going to use a multi-stage Pipeline that will validate, test, report test results and if all successful, deploy our ARM template to Azure.

All of the below is included in a public Github repo here – https://github.com/wedoazure/blogAZNet

First, let’s take a look at the pipeline at a high level

This breaks out as follows:

  • Two stages – Test and Deploy
  • Two jobs in Test
  • A single job in Deploy

Within each job we may have multiple tasks and we will see that a bit later.

First up, lets look at the first job in the Test Stage, “testARM”. This job includes multiple tasks, with some built-in tasks and some imported. The first thing to address here is the task that is imported.

This takes the ARM Template Test Toolkit and allows you to import the functionality to Azure DevOps. My personal experience is with Sam Cogan’s build linked here, although there may be others. Once imported you can then use via the task assistant:

An added bonus, the extension supports both ARM and Bicep file testing. I have both included in the repo but this focusses on ARM. You can check the repo for Bicep details, or get in touch!

So with our task imported, let’s look at our code:

First up, we’re going to validate the template using the built ARM deploy task, switching deployment mode to validation.

stages:
  - stage: Test
    jobs:
      - job: 'testARM'
        pool:
          vmimage: windows-latest
        steps:
          - task: AzureResourceManagerTemplateDeployment@3
            inputs:
              deploymentScope: 'Resource Group'
              azureResourceManagerConnection: 'Your Connection'
              subscriptionId: 'XXXXXXXXXXXXXXXXXXXXXXXXX'
              action: 'Create Or Update Resource Group'
              resourceGroupName: 'rg_staging'
              location: 'North Europe'
              templateLocation: 'Linked artifact'
              csmFile: 'virtualNetworks/vnet-ne.json'
              csmParametersFile: 'virtualNetworks/vnet-ne.parameters.json'
              deploymentMode: 'Validation'
              deploymentName: 'ARM-Validation'

This is a lightning quick test to ensure everything is OK with your template. Next, we’re going to use our imported task to run multiple checks against the template using the approved toolkit. This needs to run on a Windows pool by the way!

          - task: RunARMTTKTests@1
            inputs:
              templatelocation: '$(System.DefaultWorkingDirectory)\virtualNetworks'
              resultLocation: '$(System.DefaultWorkingDirectory)\testResults'
              allTemplatesMain: true
          
          - task: PublishTestResults@2
            inputs:
              testResultsFormat: 'NUnit'
              testResultsFiles: '$(System.DefaultWorkingDirectory)\testResults\*-armttk.xml'
            condition: always()

Note we have two tasks here, the first runs the tests and outputs the results. The second is a built-in task to publish your results to Azure DevOps, giving users a graphical representation in the portal as well as test history. The condition ensures the publish task will complete regardless of the previous task failing.

Next, we move onto the second job of our Test Stage.

- job: 'validateARM'
        pool:
          vmimage: windows-latest
        steps:
          - task: AzurePowerShell@5
            inputs:
              azureSubscription: 'Your SC'
              ScriptType: 'InlineScript'
              Inline: |
                $Parameters = @{
                  ResourcegroupName     = "rg_iac"
                  Templatefile          = ".\virtualNetworks\vnet-ne.json"
                  TemplateParameterfile = ".\virtualNetworks\vnet-ne.parameters.json"
                  Mode                  = 'Incremental'
                 }
                $Result = Get-AzResourceGroupDeploymentWhatIfResult @Parameters
                $Result
              azurePowerShellVersion: 'LatestVersion'

This runs an Azure Powershell task, submitting your template using the built in “What If Result” cmdlet. I really like this one, it outputs a full detail of changes etc. If you haven’t tried it with an ARM template you really should. Below is a sample output from my pipeline:

Now, if all the above passes, the Pipeline will move onto the next Stage, Deploy. I’ve added a DependsOn to ensure this is the case. If the Test Stage doesn’t complete, this Stage will be skipped.

  - stage: Deploy
    dependsOn: Test
    jobs:
      - job: "deployARM"
        pool:
          vmimage: windows-latest
        steps:
          - task: AzureResourceManagerTemplateDeployment@3
            inputs:
              deploymentScope: 'Resource Group'
              azureResourceManagerConnection: 'Your SC'
              subscriptionId: 'XXXXXXXXXXXXXXXXXXXXXX'
              action: 'Create Or Update Resource Group'
              resourceGroupName: 'rg_iac'
              location: 'North Europe'
              templateLocation: 'Linked artifact'
              csmFile: 'virtualNetworks/vnet-ne.json'
              csmParametersFile: 'virtualNetworks/vnet-ne.parameters.json'
              deploymentMode: 'Incremental'
              deploymentName: 'vnet-deploy-ado'

This again uses the built in ARM deployment task with a deployment mode of Incremental. The logic here is that if all of my Test Stage passes, I have a high percentage chance of my template deploying fully without issue.

The above has worked well for me in testing and with some variations in production environments. Feel free to experiment as needed here. One thing I have learned is there is an ever evolving set of methods and best practices. Alignment, in my opinion, should be to what works for you.

As always, if there are any questions or suggestions, get in touch!