Introduction

As organizations continue to embrace cloud technologies, the concept of Infrastructure as Code (IaC) has become a cornerstone of modern cloud management practices. IaC allows developers and IT professionals to manage and provision their cloud resources using machine-readable definition files, much in the same way they would manage application code. But what about your network infrastructure? Enter Networking as Code (NaC), an approach that applies the principles of IaC to network management. In this blog post, we’ll explore the benefits of NaC, using GitHub as a code repository, and how it can help keep your Azure Firewall and Network Security Groups (NSGs) up-to-date and consistent. We’ll also discuss the role of Azure Policy in enforcing security rules across your network infrastructure.

The Power of Networking as Code

Just like IaC, Networking as Code allows you to define and manage your network infrastructure using code. This approach brings several benefits:

  • Consistency: By defining your network infrastructure as code, you can ensure that your network configurations are consistent across different environments. This reduces the risk of configuration drift and makes it easier to manage complex network architectures.
  • Version Control: When you store your network configurations in a code repository like GitHub, you can track changes over time, roll back to previous versions if something goes wrong, and collaborate more effectively with your team.
  • Automation: With NaC, you can automate the deployment and configuration of your network resources, reducing manual effort and the risk of human error.
  • Speed: NaC allows you to quickly spin up and tear down network environments, making it easier to adapt to changing business needs.

Keeping Azure Firewall and NSGs Up-to-Date

Azure Firewall and Network Security Groups (NSGs) are critical components of your Azure network infrastructure. They control the flow of traffic into and out of your network, protecting your resources from unauthorized access and attacks. With Networking as Code, you can ensure that your firewall and NSG configurations are always up-to-date and consistent.

By defining your firewall and NSG rules as code, you can easily update your configurations as your security needs evolve. For example, if you need to block a new range of IP addresses, you can simply update your code and redeploy your firewall or NSG. This ensures that your security measures are always in line with your current threat landscape.

Code Organisation

When diving into Infrastructure as Code (IaC) for networking, one of the first hurdles you’ll face is determining the optimal structure for your configuration. At first glance, it might seem enticing to pour everything into one grand template, but think of the potential chaos: a minor tweak could necessitate modifying this massive file, potentially destabilizing your entire setup. Moreover, we aim to limit the potential fallout from changes. Mistakes made in a test environment shouldn’t ripple into production. Plus, the workflow required to deploy such a gargantuan template would need wide-ranging access across all your subscriptions.

This inevitably leads to the realization that a segmented approach is essential. By breaking the setup into multiple templates – each within its own file or module – not only is manageability improved, but it also offers the flexibility to assign distinct ownership roles (take a cue from GitHub’s codeowners feature). Depending on your organizational strategy, these segmented files might even be housed in separate repositories, especially if you lean towards a multirepo approach. The debate between monorepo versus multirepo setups is extensive, but I’m inclined to champion the merits of multirepo. We’ll delve deeper into the nuances of crossing repository boundaries and the advantages of multirepo shortly.

IaC Tooling

Selecting the right Infrastructure as Code (IaC) tool is paramount in streamlining and optimizing your cloud infrastructure deployment and management. When comparing Azure Resource Manager (ARM) templates with Bicep, Bicep emerges as a clear front-runner for a few compelling reasons. While ARM templates are powerful and versatile, they tend to be verbose, and their JSON syntax can be intricate and cumbersome to manage. Bicep, on the other hand, offers a cleaner, more concise syntax, simplifying the IaC process significantly. It’s essentially a transparent abstraction over ARM, meaning whatever you can do with ARM, you can achieve with Bicep but with greater ease and clarity. While Terraform is another formidable player in the IaC arena with its cross-platform capabilities, my personal tool of choice is Bicep, given its intrinsic alignment with Azure and its developer-friendly syntax.

Rule Collection Groups

When breaking down configurations into separate files, it’s essential to define clear boundaries. Take the Azure Firewall Policy as an instance. Instead of lumping all the rules into one monolithic module, Azure provides the flexibility of Rule Collection Groups (RCGs). This offers the convenience of deploying individual RCGs via distinct ARM, Bicep, or Terraform templates, without redeploying the entire Firewall Policy.

However, a word of caution is in order: Azure Firewall has a documented limit of supporting up to 60 RCGs per policy. So, if your policy can be segmented into 60 or fewer blocks, you’re set. Consider a scenario where you’re managing 20 applications, each with a test and production environment. This setup would utilize 40 RCGs, allowing each application environment to manage its respective RCG independently.

Yet, challenges arise when managing expansive organizations with hundreds of applications. Here, RCGs might encapsulate multiple applications, often termed as a “Line of Business.” Although Rule Collections (RCs) can still cater to individual app environments, changes to any RC mean you’ll need to consolidate all relevant RCs within an RCG template before deployment.

Empower Through GitHub Actions!

Application teams ought to have autonomy over their code, encompassing the essential data needed to deploy the Network Security Group (NSG) and firewall rules vital for their application’s functionality. The era of a centralized firewall administration, attempting to govern all rules without genuine insights into their purpose or necessity, is behind us.

However, expecting application administrators to be network gurus is unrealistic. This is where safeguarding mechanisms, capable of identifying and rectifying errors prior to deployment, become invaluable. Enter GitHub actions.

By safeguarding your code branches, mandatory pull requests become the gatekeeper before any code merge. This not only facilitates a review process by designated code owners but also institutes systematic checks to ensure the new configurations are both valid and adhere to compliance standards.

Such checks can seamlessly integrate using GitHub actions, readily available on the GitHub Action Marketplace. Take the azure/arm-deploy action for instance. It can be set in ‘Validate deployment’ mode, ensuring your templates are structurally sound:

      - uses: azure/arm-deploy@v1
        name: Preliminary validation for shared infrastructure
        with:
          resourceGroupName: ${{ secrets.AZURE_RG }}
          template: ./shared/bicep/azfwpolicy.bicep
          deploymentMode: Validate

Streamlining Deployments with Concurrency Groups

Parallel deployment operations can be tricky with Azure resources; at best, simultaneous attempts might get blocked, and at worst, they could lead to resources landing in a ‘Failed’ state. Thankfully, GitHub provides an elegant solution in the form of concurrency groups, ensuring deployments follow a sequential pattern. A glimpse at how this feature is harnessed can be seen in the deploy_azfw_bicep.yml:

jobs:
  deploy-azfw-policy:
    concurrency:
      group: deploy_azfw

This configuration ensures that only one deployment within the deploy_azfw concurrency group is active at any given moment. If another deployment arises (perhaps due to back-to-back pull request merges), it patiently queues up, awaiting the completion of the ongoing deployment.

Universal NSG Rules

Azure Network Security Groups (NSGs) often require standardized configurations. These are typically defined by centralized IT teams to block known insecure protocols or sculpt NSGs in a specific manner.

For instance, I often advocate for embedding a definitive “deny” rule in NSGs, rather than relying solely on default settings. Here’s why: the preset rule that permits internal traffic within an NSG can unintentionally evolve into a blanket “permit all” if it’s coupled with a User Defined Route (UDR) for 0.0.0.0/0 attached to the subnet of a Virtual Machine.

While this might not seem alarming since the UDR typically redirects all traffic to a firewall for further filtering, this open-door rule remains a point of contention for me. To rectify this, integrate an unequivocal “deny” at the tail-end of each NSG, ensuring it takes precedence before default rules kick in.

Several strategies can tackle this challenge. Note that the Azure Virtual Network Manager (AVNM) isn’t your ally here, as AVNM administrative rules take effect before any custom NSG directives. One approach is leveraging Azure Policy. For example, Guillaume Beaud’s insightful demonstration introduces an RDP rule with a static priority for every NSG. You can adapt this framework to embed the explicit “deny” rule as needed.

Conclusion

Networking as Code is a powerful approach to network management in the cloud. By treating your network infrastructure as code, you can ensure consistency, leverage version control, automate deployments, and adapt quickly to changing needs. Moreover, by using tools like GitHub and Azure Policy, you can keep your Azure Firewall and NSGs up-to-date and enforce critical security rules across your network infrastructure. As organizations continue to embrace the cloud, embracing Networking as Code will be key to managing and securing their network resources effectively.

About the author