Azure Application Security Groups — The Bicep!
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).
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:
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.