Azure Application Security Groups — The Bicep!

Aymen Abdelwahed
uleap
Published in
4 min readJul 17, 2024

--

As we steer through the design, implementation, and security hardening of an Azure network infrastructure, we often confront challenges due to the massive number of security control choices available for each of the Azure Services / Resources.

Our focus today is on network security and, more precisely, seeking to simplify it through application security groups (ASGs).

Azure Bicep — Application Security Groups [Image generated by Dall-E]

What are ASGs?

Understanding Application Security Groups is straightforward. They allow us to define network traffic for servers that fit specific resource types, simplifying network management.

Rather than segregating different servers into different subnets based on their type, we can put them in the same subnet and segregate them by their Application Security Group. Thus, it is easier to manage security policies collectively.

For additional details regarding ASG, please refer to an earlier post:

Unleashing the Power of ASGs with Bicep

By harnessing the power of Infrastructure-as-Code, we can implement robust network security controls using Application Security Groups with Private Endpoints. This approach not only simplifies network security management but also enhances its effectiveness, giving you greater control and confidence in your network security controls.

Recommendation — Naming Convention

Before we delve deeper into ASGs with Bicep, we should consider sooner conforming to a standard for the naming convention, even for temporary resources, including proper tagging.

Please refer to the Microsoft Azure naming conventions & recommendations to set proper naming for Azure resources:

㊙ Microsoft Azure — Naming Convention

In this article, we are considering the following naming convention/standard:

# Naming Convention:
<prefix:3>-<purpose:>-<environment:3>-<shortRegion:3>-<index:3>
# e.g. asg-backend-dev-we-001

# Fields details:
- Prefix:3
> We better set the prefix to 'asg', based on Microsoft naming.
- Purpose:
> This is the purpose of the ASG.
- Environment:3
> DTAP Environment
- ShortRegion:3
> Target region for the ASG. ('frc' for France Central, 'we' for West Europe, etc).
- ResourceIndex:3

We will leverage Bicep as Infrastructure-as-Code to implement organizational network security controls using Application Security Groups with Private Endpoints.

Infra As Code — Bicep Approach

To be able to proceed and follow with the next steps, I recommend having the below prerequisites:

- An active Azure Subscription
- Bicep binary (Local or via Azure CloudShell)
- Azure PowerShell or Azure CLI (Local or via Azure CloudShell)
- A Resource Group already provisioned.
- Least-privileges to deploy/destroy resources in a Resource Group.

Well settled!? Let’s do it!

As briefly mentioned earlier, we are authoring a Bicep template that creates an ASG.

FOUR easy steps to follow for a well-written Bicep code:

  • Step 1: Use bicep decorators for Parameters/Input validation and description, as shown below (Even for Outputs)
@description('Required. ASG Purpose. The length must not exceed 64 characters)
@maxLength(64)
param applicationSecurityGroupPurpose

@description('Optiona. Location for resources.')
param location = resourceGroup().location
  • Step 2: When required, use a variable. The below example is used mainly for formatting purposes (conditions could be applied on variables, too)
// Format the ASG Name (Max length is 15 characters)
var applicationSecurityGroupName = ‘asg-${applicationSecurityGroupPurpose}’
..
  • Step 3: Implement resource definition for ASG deployment:
resource applicationSecurityGroup 'Microsoft.Network/applicationSecurityGroups@2023-11-01' = {
name: applicationSecurityGroupName
location: location
tags: tags
}
  • Step 4: Provide sufficient output for further usage (Modules).
@description('The resource ID of the application security group.')
output applicationSecurityGroupId string = applicationSecurityGroup.id

@description('The name of the application security group.')
output applicationSecurityGroupName string = applicationSecurityGroup.name

The final Bicep Configuration file should be like this:

@description(‘Required. ASG Purpose. The length must not exceed 64 characters)
@maxLength(64)
param applicationSecurityGroupPurpose

@description('Optiona. Location for resources.')
param location = resourceGroup().location

resource applicationSecurityGroup 'Microsoft.Network/applicationSecurityGroups@2023-11-01' = {
name: applicationSecurityGroupName
location: location
tags: tags
}

@description('The resource ID of the application security group.')
output applicationSecurityGroupId string = applicationSecurityGroup.id

@description('The name of the application security group.')
output applicationSecurityGroupName string = applicationSecurityGroup.name

Infra As Code — Deploy ASG with Bicep

The last step is to trigger the deployment of the ASG using Bicep:

$deploymentGenName = "ASAAppSecGroupDeployment-((Get-Date).ToUniversalTime()).ToString('MMdd-HHmmssffff')"

# From an Azure DevOps pipeline use:
# $deploymentGenName = "ASAAppSecGroupDeployment-$(Build.BuildID)"

New-AzResourceGroupDeployment -Name $deploymentGenName -c `
-ResourceGroupName rg-xyz `
-TemplateFile ./main.bicep `
-TemplateParameterFile ./default.parameters.json

Bicep/Azure Verified Modules

The Azure community created an initiative trying to consolidate and set standards for what a good Infra-as-Code module should look like, the so-called ‘Azure Verified Modules’, which I recommend checking further.

Associate ASG with Private Endpoint

To associate an Application Security Group with a Private Endpoint, we simply run the Set-AzPrivateEndpoint PowerShell command:


$resourceGroupName = 'rg-backend-dev-we-001'
$privateEndpointName = 'pep-backend-dev-we-001'
$applicationSecurityGroupName = 'asg-backend-dev-we-001'

Write-Host "##[command]Retrieving ASG '$applicationSecurityGroupName'"
$privateEndpointObject = Get-AzPrivateEndpoint -ResourceGroupName $resourceGroupName-Name $privateEndpointName

Write-Host "##[command]Associating the asg '$applicationSecurityGroup' with private endpoint '$($privateEndpointObject.Name)'"
$privateEndpointObject.ApplicationSecurityGroups = $applicationSecurityGroupObject
$privateEndpointObject | Set-AzPrivateEndpoint

To Conlude!

As described above, Azure Application Security Groups (ASG) offer several benefits. However, they also introduce considerable drawbacks. One is that ASGs can be assigned to network resources of a single Virtual Network and can not be used across different regions. Furthermore, ASGs do not provide granular control over outbound traffic from Azure Resources.

These limitations should be considered when designing a network security strategy in Azure or implementing IaC.

--

--

Aymen Abdelwahed
uleap
Editor for

Is a Cloud-Native enthusiast with 14 plus years of experience. He’s continuously immersing himself in the latest technology trends & projects.