Skip to main content

· 9 min read

An IP Group in Microsoft Azure is a logical container of IP address ranges for private and public addresses.

IP Groups allow you to group and manage IP addresses for Azure Firewall rules in the following ways:

  • As a source address in DNAT rules
  • As a source or destination address in network rules
  • As a source address in application rules

An IP Group can have a single IP address, multiple IP addresses, one or more IP address ranges or addresses and ranges in combination.

The IP Group allows you to define an IP address that can be used in conjunction with Azure Firewall, to allow or deny internal or external traffic from a perspective set of IP addresses.

The following IPv4 address format examples are valid to use in IP Groups:

  • Single address: 10.0.0.0
  • CIDR notation: 10.1.0.0/32
  • Address range: 10.2.0.0-10.2.0.31

By default, the Azure Firewall blocks outbound and inbound traffic; however, you may want to enable (or block) traffic to and from specific countries - there is no built-in geo-filtering with Azure Firewall, as you can use other services, such as the Web Application Gateway and with the Application Gateway and Azure Front Door to block and allow access, and other third party services such as Cloudflare. This script can be adapted for any list of IP ranges; it doesn't need to be country IP addresses.

However, you may want to control access to and from specific countries (or other services) with Azure Firewall - this is where the IP Groups can be effective, and because we won't be editing the Firewall directly - we won't run into issues with delays without having to wait for the Azure Firewall policies to be updated.

To solve the issue of creating the IP groups and finding and keeping the IP groups up-to-date with various countries' IP ranges - I have created a PowerShell function to retrieve supported countries' IP CIDR ranges and create the relevant IP groups.

Azure IP Group - Country IP ranges

With IP Groups, there are a few things to keep in mind:

  • You can have 200 IP Groups per firewall with a maximum of 5000 individual IP addresses or prefixes per each IP Group.

For a country like New Zealand, the 5000 limit for the address ranges is acceptable - but for other countries, like the United States or United Kingdom, this can be an issue, where the total IP ranges can grow to over 20k - to deal with this, the script will create multiple IP Groups, and append a number to the end.

Suppose IPs are manually added to the groups. In that case, they won't be added - the script will add in any different or new IP ranges, ignoring any current IP ranges (this means it won't delete any IP ranges that are removed from the source IP list from IPDeny); however, I recommend that anything added outside of this script is kept in a separate IP group.

As with any script, I recommend this is tested in a test environment first.

Before we run it, we need a few prerequisites.

The function assumes you have connected to Microsoft Azure and your relevant subscription.

Before we import the function, I am going to check if any IP groups already exist quickly (this isn't required) - but it's a good opportunity to check that you are connected to your Azure subscription and that the AzIPGroup cmdlets exist - and whether you have any IP groups already existing.

Get-AzIpGroup

Get-AzIpGroup

I have received no errors or existing IP groups in my subscription, so I will continue importing my function.

The function can be found here:

New-AzCountryIPGroup.p1
function New-AzCountryIPGroup {
<#
.SYNOPSIS
Creates an Azure IP group, with the IP address ranges for various countrues.
The code does the following:
1. It downloads the IP address ranges for the country specified.
2. It checks if the IP Group already exists, if it does, it adds the IP addresses to the existing IP Group.
3. If the total number of IP addresses is less than 5000, it will add the IP addresses to the existing IP Group.
4. If the total number of IP addresses is over 5000, it will create a new IP Group, with the same name as the existing IP Group, and it will add the IP addresses to the new IP Group.
5. If the new IP Group is over 5000, it will create a new IP Group, with the same name as the existing IP Group, and it will add the IP addresses to the new IP Group.
6. It will continue to create new IP Groups until all of the IP addresses are added.

The code can be used to create IP Groups for multiple countries, and if the number of IP addresses is over 5000, it will create multiple IP Groups, with the same name, but with a counter after the name, so that it will be unique.
.EXAMPLE
New-AzCountryIPGroup
New-AzCountryIPGroup -CountryCode NZ -IPGroupName IP -IPGroupRGName NetworkRG -IPGroupLocation AustraliaEast
.AUTHOR
Luke Murray - https://luke.geek.nz/

#>
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true, Position = 0)]
[System.String]
$CountryCode,
[Parameter(Mandatory = $true, Position = 1)]
[Object]
$IPGroupName,
[Parameter(Mandatory = $true, Position = 2)]
[System.String]
$IPGroupRGName,
[Parameter(Mandatory = $true, Position = 3)]
[System.String]
$IPGroupLocation
)


$IPBlocks = Invoke-WebRequest -Uri ('https://www.ipdeny.com/ipblocks/data/aggregated/{0}-aggregated.zone' -f $CountryCode.ToLower())
#Exports the IPBlock content from the HTML request, into a String
$IPBlock = $IPBlocks.Content
#Spilts each IP block, into a seperate object
$ipaddressranges = $IPBlock -split '\s+' -replace '\r?\n\r?', '' | Where-Object { $_ -ne '' }

$Group = Get-AzIpGroup -Name $IPGroupName -ResourceGroupName $IPGroupRGName

if ($ipaddressranges.Length -lt 5000) {

If ($null -eq $Group) {
Write-Host "Group doesn't exist, creating a new IP Group called $IPGroupName in the following Azure Resource Group $IPGroupRGName and location $IPGroupLocation"
$Group = New-AzIpGroup -Name $IPGroupName -ResourceGroupName $IPGroupRGName -Location $IPGroupLocation -Tag @{Country = $CountryCode } -Verbose

If ($null -eq $Group) {
New-AzResourceGroup -Name $IPGroupRGName -Location $IPGroupLocation -Tag @{Country = $CountryCode }
$Group = New-AzIpGroup -Name $IPGroupName -ResourceGroupName $IPGroupRGName -Location $IPGroupLocation -Tag @{Country = $CountryCode } -Verbose

}

ForEach ($ip in $ipaddressranges) {
$Group.IpAddresses.Add($ip)
Write-Host "Adding $ip to $IPGroupName."
}

$Group | Set-AzIPGroup -Verbose

}

else {
Write-Host "Group already exists called:$IPGroupName in the following Azure Resource Group $IPGroupRGName and location $IPGroupLocation. Adding IPs to the group... Please note that this script doesn't check already existing IP addresses, if identical IP addresses exist, it will overrite it, if IP addresses outside of the Country List exist, it will remain in the IP Group - but there is no checking, if there is pre-equisting IP addresses in the IP Group that will raise the Group Limit above 5000. I recommend keeping the Country IP group seperate."
$Group = Get-AzIpGroup -Name $IPGroupName -ResourceGroupName $IPGroupRGName


ForEach ($ip in $ipaddressranges) {
$Group.IpAddresses.Add($ip)
Write-Host "Adding $ip to $IPGroupName"
}

$Group | Set-AzIPGroup -Verbose
}
}

else {

Write-Host "Azure IP Groups only support IPAddresses of up-to 5000 (the country you have specified is: "$ipaddressranges.Length"), also please make sure the country code matches https://www.ipdeny.com/ipblocks/data/aggregated/"

$counter = [pscustomobject] @{ Value = 0 }
$groupSize = 5000
$groups = $ipaddressranges | Group-Object -Property { [math]::Floor($counter.Value++ / $groupSize) }
$counter = 0
ForEach ($group in $groups) {
$countup = $counter + 1

$azipgroup = Get-AzIpGroup -Name "$IPGroupName$countup" -ResourceGroupName $IPGroupRGName -Verbose


If ($null -eq $azipgroup) {
$countup = $counter + 1
Write-Host "$IPGroupName$countup doesn't exist. Creating... $IPGroupName$countup in the following Resource Group $IPGroupRGName and location $IPGroupLocation."
$azipgroup = New-AzIpGroup -Name "$IPGroupName$countup" -ResourceGroupName $IPGroupRGName -Location $IPGroupLocation -Tag @{Country = $CountryCode } -Verbose -Force
$ipgroup = $group.Group
ForEach ($IP in $ipgroup) {
$azipgroup.IpAddresses.Add($IP)
Write-Host "Adding $ip to $IPGroupName"
}

$azipgroup | Set-AzIPGroup -Verbose
$counter++

}
else {
$ipgroup = $group.Group
ForEach ($IP in $ipgroup) {
$azipgroup.IpAddresses.Add($IP)
Write-Host "Adding $ip to $IPGroupName"
}

$azipgroup | Set-AzIPGroup -Verbose
$counter++
}
}

}
}

Note: Make sure your country matches the supported country shortcodes found here: IPBlock Aggregated. IPDeny is the source for the IP address list.

Once saved to your computer, it's time to import it into your active PowerShell terminal and run it (after you have verified you have connected to the correct Azure subscription).

So I will navigate to the script and import it:

cd D:\git
. .\New-AzCountryIPGroup.ps1
New-AzCountryIPGroup

Import New-AzCountryIPGroup.ps1

The 'New-AzCountryIPGroup' Azure function relies on 4 parameters:

ParametersValues
CountryCodeNZ
IPGroupNameIPGrpNZ
IPGroupRGNameNetworkRG
IPGroupLocationAustraliaEast

Make sure that the values change to your environment; in my example, I am specifying an IP Group and Resource Group that doesn't exist so that the script will create it for me - and the location I will be deploying to will be the Australia East region.

New-AzCountryIPGroup -CountryCode NZ -IPGroupName IPGrpNZ -IPGroupRGName NetworkRG -IPGroupLocation AustraliaEast

New-AzCountryIPGroup

As you can see, the script created an Azure Resource Group and imported the New Zealand IP ranges to a new IP Group...

Not required - but if I rerun it, it will simply override any IP addresses that are the same and add any new addresses to the same IP Group that already exists, as below:

Rerun New-AzCountryIPGroup

The Azure IP Group is visible in the Azure Portal as below:

Azure Portal - Azure IP Group

And a Tag was added to include the country:

Azure IP Group - Tag

As New Zealand was under the 5000 limit, only one IP Group was needed, but if we change the Country Code to the US...

Run New-AzCountryIPGroup - US

It created 5 IP groups, each containing 5000 CIDR IP ranges, with the last containing the remaining IP address ranges.

As you can see, it's reasonably easy to create IP Groups containing a list of IP ranges for multiple countries quickly:

Azure Portal - Azure IP Groups

Note: The script can also be found in my Public Git Repo here, feel free to recommend pull requests if you have anything to add or change.

· 17 min read

Festive Tech Calender - Microsoft Dev Box

It's that time of year again! The time to be jolly and experience the Month of December by looking at the Festive Tech Calendar!

This year the Festive Tech Calendar Team is raising money for the charity @missingpeople.

We believe its important to support charities that do great work. Without fundraising Missing People wouldn’t be able to find vulnerable missing people and reunite families.

If you would like to donate please visit our Just Giving Page

Today, we sent our present and took a peek inside the box - at Microsoft Dev Box!

Overview

Microsoft Dev Box provides self-service access for developers to high-performance, cloud-based workstations preconfigured and ready-to-code for specific projects - all while maintaining security and corporate governance. With Microsoft Dev Box, organizations can:

  • Maximize dev productivity with ready-to-code, self-service Dev Boxes.
  • Central management of workstations running anywhere to maintain greater security, compliance, and cost efficiency.
  • Customize dev boxes with everything developers need for their current projects.

Microsoft Dev Box supports any developer IDE, SDK, or tool that runs on Windows. Developers can target any development workload built from Windows, including desktop, mobile, IoT, and web applications. Microsoft Dev Box even supports building cross-platform apps thanks to Windows Subsystem for Linux and Windows Subsystem for Android. Remote access allows developers to securely access dev boxes from any device, whether it's Windows, macOS, Android, iOS, or a web browser.

High-level Azure Devbox workflow

Microsoft Dev Box is a managed service that enables developers to create on-demand, high-performance, secure, ready-to-code, project-specific workstations in the cloud.

Microsoft Dev Box is available today as a preview from the Azure Portal. During this period, organizations get the first 15 hours of the dev box 8vCPU and 32 GB Memory SKU for free every month, along with the first 365 hours of the dev box Storage SSD 512 GB SKU.

Beyond that, organizations pay only for what they use with a consumption-based pricing model. With this model, organizations are charged per hour depending on the number of Compute and Storage consumed.

To use Microsoft Dev Box, each user must be licensed for Windows 11 or 10 Enterprise, Microsoft Endpoint Manager, and Microsoft Entra ID P1. These licenses are included in M365 F3, E3, E5, A3, A5, Microsoft Business Premium and Microsoft 365 Education benefit plans.

Microsoft Dev Box

Disclaimer: At the time of writing, this service is still in Public Preview, some services and license requirements may change by the time this becomes generally avaliable.

So, where does Microsoft Dev Box fit in?

Microsoft offers a plethora of services, from Azure Virtual Desktop, Windows 365, and now Microsoft Dev Box - where would you use Microsoft Dev Box over another service, such as Windows 365?

General scenarios at a high level are:

ScenarioProduct
Production multi-session, supporting Windows Server and Client OS, Published ApsAzure Virtual Desktop
Production dedicated personal PCs, for shift/party time users - or small environmentsWindows 365
Dev/Test Ondemand Windows machines for Testing and development with custom image supportAzure Dev Box

Microsot Windows Experiances Strategy

Microsoft Dev box can help project and development teams get up and running quickly, independent of what hardware a developer or contractor has, whether they prefer Mac, Windows, or Linux - the Microsoft Dev box can be used to get developers and contractors up and running in a secure environment that supports Intune!

Concepts & Roles
ConceptsNotes
Dev centerA dev center is a collection of projects that require similar settings. Dev centers enable dev infrastructure managers to manage the images and SKUs available to the projects using dev box definitions and configure the networks the development teams consume using network connections.
ProjectsA project is the point of access for the development team members. When you associate a project with a dev center, all the settings at the dev center level will be applied to the project automatically. Each project can be associated with only one dev center.
Dev box definitionA dev box definition specifies a source image and size, including compute size and storage size. You can use a source image from the marketplace, or a custom image.
Network connectionNetwork connections store configuration information like Active Directory join type and virtual network that dev boxes use to connect to network resources.
Dev box poolA dev box pool is a collection of dev boxes that you manage together and to which you apply similar settings.
Dev boxA dev box is a preconfigured ready-to-code workstation that you create through the self-service developer portal. The new dev box has all the tools, binaries, and configuration required for a dev box user to be productive immediately

DevBoxHierarchy

The following are typical Azure Dev Box roles.

RoleResponsibilitiesPermissions
Dev Infra AdminsProviding developer infrastructure and tools to the development teasCan create and manage dev centers, can create projects and define images that are used to create the dev boxes
Project AdminsDoes administrative tasks for the Dev Box solution and assist with day to day tasks.Can create and manage dev box pools across different regions
Dev Box UsersMembers of your development teamsCan self-service and create one or more dev boxes, depending on the projects assigned.

Deployment

Create Dev Center

First, we need to create our Dev Center. A Dev Center allows us to centrally manage our developer environments and enable development teams with self-service capability. Dev Center is used by more than just Microsoft DevBox - an example is Azure Deployment Environments - which allows devs to spin up templated (ARM) application infrastructure quickly - but we will focus on components of Dev Center - used by Microsoft Dev Box.

Please confirm what region you can deploy Dev Box. As this is in Public Preview at the time of writing - only certain regions are supported.

Let's create a standard Dev Box environment in your favourite browser, starting with the Dev Center...

  1. Log in to the Microsoft Azure Portal
  2. Click + Create a resource
  3. Search for: Dev center, select your Dev center and click Create
  4. Microsoft Azure Portal - Dev center
  5. Select the Subscription and ResourceGroup you want to deploy your Dev Center; you can use this opportunity to create a new Resource Group.
  6. Type in the name__ of your DevCenter **(in my example, it is named DevCenter-Devs)
  7. Then select the location (region) in which you want to deploy your DevCenter.
  8. Azure Portal - Create a dev center
  9. Click Review + Create, then Create

Deployment of the Microsoft Dev Center will take a few minutes.

Create Virtual Network

To use Microsoft Dev Boxes - like any Virtual Machine in Azure, you need a Virtual Network! The Dev Boxes can connect to existing Virtual Networks, which could be peered with other VNETs, have connectivity to on-premises - or have standalone secure connectivity through network links! In my demo, I don't currently have a Virtual Network - so I will create a Virtual Network from scratch.

  1. Log in to the Microsoft Azure Portal
  2. Click + Create a resource
  3. Search for: Virtual Network
  4. Create a Virtual Network
  5. Select your Virtual Network name and region (make sure the region aligns with your workloads and Azure DevCenter location)
  6. Azure Portal - Create VNET
  7. Click Next: IP Addresses
  8. I will leave the IP address space the default of 10.1.0.0/16 - but change the default subnet name to devbox-subnet.
  9. Azure Portal - Create VNET
  10. Click Review + create
  11. Click Create

Now that we have our Dev Center and our Virtual Network - it's time to make a Network connection - this connection will be used by Dev Center - to allow our Dev Boxes to connect to the Virtual Network - and to select your Virtual Machine identification (i.e. Microsoft Entra ID, or Hybrid Microsoft Entra ID).

  1. Log in to the Microsoft Azure Portal
  2. Click + Create a resource.
  3. Type in: Network Connection, find and click Create
  4. Create Network Connection
  5. As I will be using Microsoft Entra ID joined Virtual Machines, I will ensure that the Domain join type is: Microsoft Entra ID join.
  6. For the Network connection name, I will select: ProductionVNETAADJConnection
  7. I will select my Virtual Network and subnet, which the Dev Box will be placed into.
  8. Create Azure Network Connection
  9. Click Review + Create, and click Create
  10. Now that we have created the Network connection - it is time to link it to our Dev Center - so it can be used.
  11. Navigate to your Dev Center
  12. Under Dev Box configuration, select Networking
  13. Click + Add
  14. Select your Network connection that has just been created
  15. Azure Dev Center - Link Network Connection
  16. Click Add
  17. The Network Connection will check all the network requirements for the Dev Box service, such as the Azure tenant and Intune configuration (i.e. is there a restriction in Endpoint Management for Windows).
Create Dev box definitions

It's time to create our Dev box definition. The Dev box definition is the type of Virtual Machines -or Dev Boxes that are standard for your environment. A dev box definition will be used to define the image (whether a custom or marketplace image), SKU of virtual machines (Compute + Memory), and available storage. Note that if you want to use a Custom Image - you will need an Azure Compute gallery, and if you decide to go down this route, make sure you check out Azure VM Image Builder to help automate and build your images. You can have multiple definitions per project.

  1. Log in to the Microsoft Azure Portal
  2. Navigate to your Dev center
  3. Navigate to Dev box definitions
  4. Click + Create
  5. For our Image definition name, I will go with Win11-VS
  6. For Images, there are a plethora of images available! For this guide, I will use Visual Studio 2019 Enterprise on Windows 11 Enterprise + Microsoft 365 Apps 22H2 image.
  7. Azure Dev Box definitions
  8. I will select the Latest image version and specify 4vCPU, 16GB of RAM, and a 256 GB SSD drive.
  9. Azure Dev Box definitions
  10. Click Create

You can edit a Dev box definition, change the image, Compute, and storage after it has been created; this could be useful if there are issues with the latest version of the image, you can roll back the version - so people can make their Dev Boxes while the image is worked on.

Create and assign Project

Now that we have our Dev Center and Virtual Network connection - it is time to create a Project. A Project is intended to be task specific - an example being the following user story "As a developer working on a mobile game, I need access to a Windows 11 Development workstation with Visual Studio installed" - so all users working on that mobile game - will get an identical virtual machine setup with all the pre-requisites that the need to start development, a project team working on another mobile game, may need different software or dependencies - so will be part of another project.

  1. Log in to the Microsoft Azure Portal
  2. Navigate to your Dev center
  3. Navigate to Projects
  4. Select + Create
  5. Select your Resource Group
  6. Select your Dev center
  7. Please type in the name of our Project and enter a description.
  8. Azure DevBox - Create Project
  9. You can use Tags to add additional information on billing for the project or the project administrator's contact details - but we will select Review + create and Create
  10. Once the Project has been created, we need to assign assignees to use the project. I will give a DevBox User role to the project so I can make a Dev Box.
  11. Within the Project, click on the Access Control (IAM)
  12. Click + Add
  13. Select Add Role assignment
  14. Select DevCenter Dev Box User
  15. Click Next
  16. Make sure User, Group, or Service principal is selected and click + Select Members.
  17. Ideally, you would assign the Dev Box User role to an Azure AD group - but in my demo, I will select an individual user.
  18. Click Next
  19. Azure Dev Box - Assign Project Members
  20. Once you have confirmed your users have been assigned, click on Review + assign to give your users or groups to the project, allowing them to create Dev Boxes.

Note: I have found it can take 5-10 minutes for access to be granted to the users before they can create Dev Boxes.

Create Dev Box Pool

Now that we have our project and dev box definitions - it's time to create our Dev Box Pool - which is what the Dev Boxes will be made from.

  1. Log in to the Microsoft Azure Portal
  2. Navigate to your Dev center
  3. Navigate to Projects
  4. Navigate to the project you created earlier (i.e. for me, its MobileGameDevelopment)
  5. Click on the Dev box pools
  6. Click on + Create
  7. Azure Dev Box - Create Dev Box Pools
  8. Type in a name - i.e. MobleDevelopmentWin11
  9. Select your Network connection
  10. Select your definition
  11. Select your Creator privileges (i.e. select whether your user will be a standard user or have Local administrator rights on their devbox)
  12. Configure Auto-stop or skip and confirm licensing.
  13. Click Create

After 1-2 minutes, your Dev Box pool has been created.

Create & Connect

Now that your Dev Center, Network, and Dev Box project has been stood up - it's time to Create and connect to your new Dev box! Microsoft Dev Box - offers a few ways to connect to the DevBox; we will go through a few options now.

Create Dev Box

Now it's time to create our Dev Box! To do this, we need to go to the Dev box Developer portal (as a Dev Center Devbox, User)

  1. Navigate to the Microsoft Dev Box portal
  2. Click on + New Dev Box
  3. Enter your name of the DevBox (i.e. what you will name the Virtual Machine and see in the portal - make sure this is meaningful - as you may have more than one Dev Box)
  4. Select your assigned Dev Box Pool, and select your Dev Box definition
  5. Microsoft Dev Box - Create Virtual Machine
  6. Click Create
  7. DevBox - Creating

Note: Dev box creation can take 30-90 minutes. Dev boxes will automatically start upon creation.

Connect Dev Box using Microsoft Dev Box Portal
  1. Navigate to the Microsoft Dev Box portal
  2. Click on the Dev Box you want to connect to.
  3. Select Open in the browser
  4. Azure DevBox - HTML Client
  5. Azure Dev Box /Windows 365 Connection
  6. If prompted, then log in with your credentials.
  7. Azure Dev Box - Sign In
  8. You will now be connected to your new Azure Dev Box!
  9. Azure Dev Box
Connect Dev Box using Remote Desktop Application

Like Azure Virtual Desktop, you can connect to your Dev Box using the Remote Desktop client.

  1. Download and install the Remote Desktop Client
  2. Subscribe to the Azure workspace
  3. As long as the Dev Box has been created, you can see your Dev Box and connect to it directly.
  4. Remote Desktop Client - Microsoft Dev Box

Configuration

We can configure a few extra things for the Azure DevBox environment.

Auto-Stop

As the Dev Box is Pay As You Go, you can ensure that a Dev Box is shut down after hours.

  1. Log in to the Microsoft Azure Portal
  2. Navigate to your Dev center
  3. Navigate to Projects
  4. Navigate to the project you created earlier (i.e. for me, its MobileGameDevelopment)
  5. Click on the Dev box pools
  6. Click on Edit on your pools
  7. Click Enable Auto-stop
  8. Select Yes
  9. Configure your Stop Time and time zone

You may also have multiple pools - selected with the exact Dev box image definition - if your project runs across various timezones, so you can schedule a 7 PM Shutdown in New Zealand and a 7 PM shutdown for those developers in the United States.

Delete or Stop

Not as much as a Configuration item, but more of a quick - howto! As a Dev Box user, you can shut down your Dev Box or delete it from the Microsoft Dev Box portal.

Azure Dev Box - Stop or Delete

Additional Resources

As Microsoft Dev Box is still in Public Preview - at the time of writing - the experience may change before its GA (Generally available).

Documentation

Additional reading on Microsoft Dev Box can be found below:

Azure Bicep

Below are some Azure Bicep samples for Azure Dev Box.

Dev Center
param name string
param location string
param tags object

resource name_resource 'Microsoft.DevCenter/devcenters@2022-08-01-preview' = {
name: name
location: location
tags: tags
identity: {
type: 'none'
}
}
DevBox Host Pool
param projects_MobileGameDevelopment_name string = 'MobileGameDevelopment'

resource projects_MobileGameDevelopment_name_MobleDevelopmentWin10Secure 'Microsoft.DevCenter/projects/pools@2022-09-01-preview' = {
name: '${projects_MobileGameDevelopment_name}/MobleDevelopmentWin10Secure'
location: 'australiaeast'
properties: {
devBoxDefinitionName: 'Win10-VS'
networkConnectionName: 'ProductionVNETAADJConnection'
licenseType: 'Windows_Client'
localAdministrator: 'Disabled'
}
}

resource projects_MobileGameDevelopment_name_MobleDevelopmentWin10Secure_default 'Microsoft.DevCenter/projects/pools/schedules@2022-09-01-preview' = {
parent: projects_MobileGameDevelopment_name_MobleDevelopmentWin10Secure
name: 'default'
properties: {
type: 'StopDevBox'
frequency: 'Daily'
time: '11:15'
timeZone: 'Pacific/Auckland'
state: 'Enabled'
}
}

· 4 min read

Azure is a cloud computing platform that provides a wide range of services and capabilities for building and deploying applications and workloads in the cloud. In contrast, hosting your own datacenter involves setting up and managing a physical infrastructure, including servers, storage, networking, and other components, in a location controlled by the organization.

Azure and hosting your own datacenter are two different approaches for deploying and managing applications and workloads.

There are several key differences between Azure and hosting your own datacenter, including the following:

  • Capital expenditure and operational costs: Azure is a pay-as-you-go service, with no upfront costs or long-term commitments, while hosting your own datacenter involves a significant capital expenditure, and ongoing costs for maintenance, support, and infrastructure upgrades.
  • Scalability and elasticity: Azure provides automatic scalability and elasticity, with the ability to scale up and down on demand, and pay only for the resources that are used, while hosting your own datacenter requires manual scaling and capacity planning, and may result in underutilized or overutilized resources.
  • Security and compliance: Azure provides built-in security and compliance features, with the ability to deploy and manage applications and workloads in a secure and compliant manner, while hosting your own datacenter requires the implementation and maintenance of security and compliance controls, and may expose the organization to security and compliance risks.
  • Integration and interoperability: Azure integrates well with other Azure services and technologies, as well as with on-premises environments, while hosting your own datacenter may require the use of complex integration and interoperability solutions, and may result in vendor lock-in and interoperability challenges.

Overall, Azure and hosting your own datacenter are two different approaches, with different advantages and disadvantages. Azure can provide a more cost-effective, scalable, and secure solution, but may require the adoption of a different operating model and a learning curve, while hosting your own datacenter can provide more control and flexibility, but may require a larger investment and ongoing operational costs.

The total cost of ownership (TCO) of Azure and on-premises can vary depending on several factors, including the specific services and resources that are used, the usage patterns and workloads, the pricing options and discounts, and the cost optimization strategies and techniques that are implemented.

In general, the TCO of Azure can be lower than the TCO of on-premises, for the following reasons:

  • Azure provides a pay-as-you-go pricing model, with no upfront costs or long-term commitments, and the ability to scale up and down on demand, and pay only for the resources that are used. This can help to reduce the overall TCO, compared to the upfront capital expenditure and ongoing operational costs of on-premises infrastructure.
  • Azure provides built-in support and maintenance services, as part of the subscription fees, and the ability to choose from different support and maintenance plans, depending on the specific needs and requirements of the organization. This can help to reduce the TCO, compared to the costs of hiring and maintaining a dedicated IT staff for on-premises infrastructure.
  • Azure provides built-in security and compliance features, and the ability to deploy and manage applications and workloads in a secure and compliant manner. This can help to reduce the TCO, compared to the costs of implementing and maintaining security and compliance controls for on-premises infrastructure.

Overall, the TCO of Azure can be lower than the TCO of on-premises, due to the pay-as-you-go pricing model, the built-in support and maintenance services, and the built-in security and compliance features. However, the actual TCO may vary depending on the specific needs and requirements of the organization, and on the implementation and cost optimization strategies that are used.

· 7 min read

Azure Storage account SFTP functionality has now gone GA (Generally Available) across most regions as part of the GA release - SFTP support for Azure Storage accounts was free while it was in preview - but now that the service is GA - there is an additional charge for SFTP (Secure File Transfer) functionality.

Enabling the SFTP endpoint has a cost of $0.30 per hour. We will start applying this hourly cost on or after December 1, 2022.

This service has worked for me without a hitch for months, but as with most resources in Microsoft Azure - you pay for what you use! Therefore, there may be instances where you do not need SFTP support 24 hours a day, seven days a week! This is where the following Azure Automation runbook can help.

Feel free to check out a previous article on setting up SFTP support for an Azure storage account.

Overview

Using an Azure Automation PowerShell runbook and Schedules (as part of the Azure Automation account) - we can turn on the SFTP endpoint - when we need it and disable it - the rest of the time - which is excellent from a security and cost perspective.

Prerequisites

To do this, we will need an:

  • Azure Automation Account
  • System Managed Identity set with Storage Account Contributor rights
  • PowerShell runbook (supplied below)

For this article, I will assume you already have an Azure Automation account - if you do not - then follow the Microsoft documentation: Create a standalone Azure Automation account.

Deploy & Configure

Now that the Azure Automation account has been configured and set up - we need to add the Runbook, but before we can do that - there are some dependencies. For example, SFTP is a new service that the currently installed Az Modules in the Azure Automation don't have visibility on - so to configure the SFTP service - we need to update 2 Modules to the most recent version.

These modules are:

  • Az.Accounts (≥ 2.10.3)
  • Az.Storage

Az.Accounts are a dependent service of the latest Az.Storage account, so let us import that first.

Update Az.Accounts module
  1. In the Azure Portal, navigate to Azure Automation accounts.
  2. Find your Azure Automation account and, click on it, navigate to Modules (under Shared resources).
  3. Select Browse Gallery
  4. Search for: Az.Accounts
  5. Import Az.Accounts
  6. Click 'Az.Accounts' and select Select.
  7. Set the runtime version to: 5.1 & select import
  8. Wait for 5 minutes while the module imports.
Update Az.Storage module

Note: the Az.The accounts module will need to finish its import before the Az.The storage module is updated.

  1. In the Azure Portal, navigate to Azure Automation accounts.
  2. Find your Azure Automation account and, click on it, navigate to Modules (under Shared resources).
  3. Select Browse Gallery
  4. Search for: Az.Storage
  5. Import  Az.Storage
  6. Click 'Az.Storage' and select Select.
  7. Set the runtime version to: 5.1 & select import
  8. Wait for 5 minutes while the module imports.
Create System Managed Identity

Now that the base Modules have been updated, we need to create a System Managed Identity - this Managed Identity will allow the Azure Automation runbook to authenticate to your Azure resources - and, in our example - make changes, such as Disabling or Enabling the SFTP service. This System Managed Identity will need Storage Account Contributor rights.

  1. In the Azure Portal, navigate to Azure Automation accounts.
  2. Find your Azure Automation account and click on it; click on Identity (under Account Settings)
  3. Select Status to: On and select Save
  4. Click on: Azure role assignments
    1. Select your Scope (in our example, we will go with Storage - to limit what changes this Azure Automation account can make)
    2. Select the Subscription and Storage account Resource on which you want to disable or enable the SFTP service.
    3. For the role, select Storage Account Contributor.
    4. Click Save

You should now see the Azure automation account, listed as having Storage account contributor rights - under your Automation account's Access Control (IAM) blade.

Import Runbook - Set-AzStgFTP.ps1

Now that the AzAccounts, Az.Storage modules have been updated, and the Azure Automation account has been given permission - to enable and disable the SFTP service on the storage account- it's time to import the Runbook that will make this happen.

  1. In the Azure Portal, navigate to Azure Automation accounts.

  2. Find your Azure Automation account and, click on it, navigate to Runbooks (under Process Automation).

  3. Click + Create a Runbook

  4. Enter your runbook name (i.e. Set-AzSFTP)

  5. Select the Runbook type as PowerShell

  6. Select the Runtime version as: 5.1

  7. [Optional] Add a description of what this Runbook does and who to contact.

  8. Click Create

  9. Open the newly created blank Runbook, and select Edit

  10. Copy the following PowerShell script into the Edit pane:

     param
    (
    [Parameter(Mandatory=$true,Position = 0, HelpMessage = 'Enter the Azure Resource Group, that contains your Azure Storage account')]
    [string]
    $resourceGroupName,

    [Parameter(Position = 1, Mandatory = $true, HelpMessage = 'Enter the Azure Storage account name')]
    [string]
    $storageAccountName,

    [Parameter(Mandatory = $true, HelpMessage = '$True = Enable SFTP & $False = Disable SFTP')][ValidateSet('False','True')]
    $enableSftp
    )

    <#
    .SYNOPSIS
    Disables or enables SFTP support on an Azure Storage Account.
    .DESCRIPTION
    Disables or enables SFTP support on an Azure Storage Account. The intention is for this script to be used in Azure Automation, alongside a Schedule to enable or disable SFTP support on an Azure Storage Account.

    .EXAMPLE
    Set-AzStgSFTP -resourceGroupName sftp_prod -storageAccountName sftpprod0 -EnableSFTP $true
    #>


    # Ensures you do not inherit an AzContext in your runbook
    Disable-AzContextAutosave -Scope Process

    Import-Module -Name Az.Storage
    # Connect to Azure with system-assigned managed identity
    $AzureContext = (Connect-AzAccount -Identity).context

    Write-Output -InputObject $AzureContext
    Write-Output -InputObject $AzureContext.Subscription
    Write-Output -InputObject $resourceGroupName
    Write-Output -InputObject $storageAccountName
    Write-Output -InputObject $EnableSFTP
    # set and store context
    $AzureContext = Set-AzContext -SubscriptionName $AzureContext.Subscription -DefaultProfile $AzureContext


    $SetSFTP = [System.Convert]::ToBoolean($enableSftp)

    $SFTPStatusBefore = Get-AzStorageAccount -DefaultProfile $AzureContext -ResourceGroupName $resourceGroupName -Name $storageAccountName | Select-Object -ExpandProperty EnableSftp

    $Status = $SFTPStatusBefore -replace 'True', 'Enabled' -replace 'False', 'Disabled'

    Write-Output -InputObject ('SFTP for {0} currently has SFTP set to: {1} before update.' -f $storageAccountName, $Status)

    Set-AzStorageAccount -DefaultProfile $AzureContext -ResourceGroupName $resourceGroupName -Name $storageAccountName -EnableSftp $SetSFTP


    $SFTPStatusAfter = Get-AzStorageAccount -DefaultProfile $AzureContext -ResourceGroupName $resourceGroupName -Name $storageAccountName | Select-Object -ExpandProperty EnableSftp

    $Status = $SFTPStatusAfter -replace 'True', 'Enabled' -replace 'False', 'Disabled'

    Write-Output -InputObject ('SFTP for {0} currently has SFTP set to: {1} after update.' -f $storageAccountName, $Status)
  11. Click Save

  12. Click Publish

Run Runbook - Set-AzStgFTP

Now that the Runbook is imported, we need to run it.

The Runbook uses the following parameters:

ParametersValues
resourceGroupNameEnter the name of the Azure Resource Group, that contains your Azure Storage account.
storageAccountNameEnter the name of your Azure Storage account.
enableSftpThe following boolean values are accepted: False (Disable SFTP) and True (Enable SFTP).
  1. Next, find your Runbook, and select Start.
  2. Enter your parameters, Resource Group, Storage Account and Enable SFTP.
  3. Start Azure Automation runbook
  4. Click Ok
  5. The Runbook will run, and as you can see - outputs its state Before the Runbook ran and after.
  6. Azure Automation - Run

Once working correctly, you can set up an Azure Automation schedule to trigger the runbook to enable and disable the SFTP when needed only!

· 11 min read

Azure-Firewall-mon is a near real-time Azure Firewall log viewer.

Azure-Firewall-mon provides an alternative_and_opinable 😊 way to access and inspect Azure Firewall logs. The recommended approach for analysing Azure Firewall logs is to set up a Log Analytics Workspace to collect all the data and use Kusto (KQL) queries to check what's happening.

In Azure-Firewall-mon, the idea is to provide an approach much more like Sysinternals Process Monitor or Check Point's SmartView, where there is no queries or dashboards that you need to implement first to get working. Still, all events are available as a log stream. In addition, a full-text search at the top of the page lets you quickly filter the content displayed on the screen, helping you understand what is happening right now (or close to present).

Overview

Azure-Firewall-mon (AFM or Azure Firewall Monitor) is a custom solution (currently in a functional beta) created by an Italian Microsoft Cloud Solution Architect called: Nicola Delfino, its worth mentioning that although a Microsoft CSA makes AFM, IT IS NOT A SUPPORTED MICROSOFT PRODUCT.

Monitoring Azure Firewall can be a pain - with trawling through logs - using the Azure Firewall Workbook - helps fill in the gap - especially around the application and network rule traffic. Still, you may want something more straightforward and designed for real-time traffic to assist with in-the-moment troubleshooting.

Azure-Firewall-mon is an open-source, single Page Application written in Angular and hosted on an Azure WebApp - so to use this, you don't need to deploy to your environment.. add in an Event Hub connection string, and away you go (there is also a demo mode - so you can see what the experience will be like)!

az-firewall-mon landing page az-firewall-mon landing page

We can deploy it to an Azure Static Web App for those who would instead host it in our environment.

"Azure Static Web Apps is a service that automatically builds and deploys full-stack web apps to Azure from a code repository. When you create an Azure Static Web Apps resource, Azure interacts directly with GitHub or Azure DevOps to monitor a branch of your choice. Every time you push commits or accept pull requests into the watched branch, a build is automatically run and your app and API is deployed to Azure."

Azure Static WebApps - Overview

Deployment

Prerequisites

Today, we are going to deploy Azure-Firewall-mon into an Azure Static Web App - to do this; we will need the following prerequisites:

  • A GitHub account
  • An Azure subscription_(with permissions to deploy Event Hub, deploy an Azure Static WebApp, and configure Diagnostics on the Azure Firewall)_
  • Azure Firewall (provisioned)

Note: Also, ensure that your Event Hub is in the same region as your Azure Firewall so that you can use Diagnostics settings. Regarding the Azure Static WebApp - it doesn't matter; this is a global service - and you will be entering the Event Hub listener.

We will use the Azure Portal and a browser to provision the workflow (however, I will have added Azure Bicep to the bottom of the article for reference).

This article - assumes you have basic knowledge of GitHub and Microsoft Azure.

For this demo, I am using a Hub & Spoke Azure topology.

Azure Firewall Monitor - High Level Architecture

Fork the GitHub repository

The first thing we need to do is clone the Azure-Firewall-mon repository; this repository holds the source control of Azure-Firewall-mon. First, however, we need a clone of it - to use in our Static Web App - this will also allow us to pull down and build the latest changes and updates of the Azure-Firewall-mon tool while having the stability of maintaining your version of the device.

  1. In your favourite browser of choice, navigate to: https://github.com/nicolgit/azure-firewall-mon.
  2. Click Fork (top right of the repository)
  3. GitHub - Create a new fork
  4. Click Create fork
  5. You have now created a fork of the 'azure-firewall-mon' repository; when a new update of Azure-Firewall-mon comes out - you can also select 'Sync fork' - to keep your fork up-to-date and trigger a new build.

Create Static Web App and deploy azure-firewall-mon

Now that you have created a fork, it's time to make your Azure Static WebApp!

  1. Navigate to the Azure Portal
  2. Click + Create a resource
  3. Type in: Static Web App
  4. Select and click Create
  5. Create or select a Resource Group
  6. Type in the name of your Static Web App
  7. For the plan type, we will go with Free
  8. Please select your region (this is the staging environment used to create your resource so the Azure Static Web App can then be replicated geographically).
  9. Select Source, as GitHub
  10. Click Sign in with GitHub (and sign in with an account with access to the GitHub Repository fork of azure-firewall-mon created earlier).
  11. Authorise the Azure Static Web Apps to have access to your repositories
  12. Select your organisation and the azure-firewall-mon repository you forked earlier.
  13. Select 'main' for the branch
  14. Under Build Presents, select Angular
  15. For App location, enter "/firewall-mon-app/"
  16. Leave the API location empty
  17. For the Output location, enter: "dist/firewall-mon-app"
  18. Azure Static WebApps - Angular Build
  19. If you navigate to your own forked GitHub repository, you should see a new folder created under .github/workflows - and a new GitHub Actions workflow file!
  20. Create Azure Static WebApp - Angular - Azure Portal
  21. If you select Actions in GitHub, you should see a deployment start.
  22. After roughly 5 minutes, your Azure Static App - will have deployed azure-firewall-mon!
  23. Navigate to your newly created Azure Static App in the Azure Portal
  24. Click Browse
  25. You should now see azure-firewall-mon!
  26. azure-firewall-mon

Note: In GitHub, under Actions and the Build and Deploy Job, you may see a message about Note.js 12 actions being deprecated; you can set the node version to be higher.

Add the step to set the node version below submodules and above the Build and Deploy step:

      - uses: actions/setup-node@v1
with:
node-version: "18.x"

Refer to a copy of my Github Actions file here: AzureStaticWebAppsCICD.yml for a comparison of GitHub action - a setup-node step running on the latest version of 18.

Create Event Hub namespace and shared access policy

Even if you use the externally hosted version of Azure Firewall Monitor, you still need an Event Hub and Namespace to stream the events from our Azure Firewall to the Azure Firewall Monitor.

  1. Navigate to the Azure Portal

  2. Click + Create a resource

  3. Type in: Event Hubs

  4. Select and click Create

  5. Select your subscription and Resource Group;

  6. Type in the Namespace of the event hub (i.e. AzureFirewallMonitor)

  7. Select your location (make sure this is the same region as your Azure Firewall)

  8. Select your Pricing Tier (in this example, I am going with Basic)

  9. Click Review + create

  10. Once the Namespace has been created, it's time to make our Event Hub; navigate to your newly created AzFirewallMonitor namespace.

  11. Under Entitles, click + Event Hub

  12. Under the name, enter the Event Hub name (i.e. AzMonitorCapture)

  13. Leave the defaults (and Message retention to 1 day)

  14. Click Review + Create

  15. Click Create

  16. Create Azure Event Hub

  17. Now that the Event Hub is created, we need to create a Shared access policy; in the Event Hub namespace, click on Shared access policies.

  18. Click + Add

  19. Type in a Policy name(i.e. AzMonitorListener)

  20. Select Send

  21. Click Create

  22. Azure Event Hub - Create shared access policy

    Configure Azure Firewall to stream to Event Hub and run Azure Firewall monitor

    Now that we have an Event Hub configured and a Shared access policy set to Listen - it's time to configure the Azure Firewall to direct logs to the Namespace.

  23. Navigate to the Azure Portal

  24. Navigate to your Azure Firewall

  25. Select Diagnostic Settings

  26. Click + Add diagnostic setting

  27. Azure Firewall - Diagnostic Settings

  28. Type in a Diagnostic setting name (i.e. AzureFirewallMonitor)

  29. Select All Logs

  30. Select Stream to an event hub

  31. Select your subscription, event hub namespace, event hub and policy created earlier.

  32. Azure Firewall - Diagnostic setting

  33. Click Save

  34. Please navigate back to your Event Hub namespace and select your Event Hub entity; now, we need to create a Shared access policy to Listen (for the entity, not the Namespace)

  35. Click Shared access policies, and create a new Shared access policy with Listen.

  36. Copy the Connection string-primary key

  37. Navigate to your newly created Azure Static App in the Azure Portal

  38. Click Browse

  39. You should now see azure-firewall-mon, and enter in the Connection string-primary key copied earlier!

  40. Congratulations you have now set up Azure Firewall Monitor on an Azure Static Web App and can troubleshoot your Azure Firewall quickly in real-time!

  41. Run Azure Firewall Monitor

References: GitHub Action

name: Azure Static Web Apps CI/CD

on:
push:
branches:
- main
pull_request:
types: [opened, synchronize, reopened, closed]
branches:
- main

jobs:
build_and_deploy_job:
if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action != 'closed')
runs-on: ubuntu-latest
name: Build and Deploy Job
steps:
- uses: actions/checkout@v2
with:
submodules: true

- uses: actions/setup-node@v1
with:
node-version: "18.x"
- name: Build And Deploy
id: builddeploy
uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_POLITE_CLIFF_06D4C2810 }}
repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments)
action: "upload"
###### Repository/Build Configurations - These values can be configured to match your app requirements. ######
# For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig
app_location: "/firewall-mon-app/" # App source code path
api_location: "" # Api source code path - optional
output_location: "dist/firewall-mon-app" # Built app content directory - optional

###### End of Repository/Build Configurations ######

close_pull_request_job:
if: github.event_name == 'pull_request' && github.event.action == 'closed'
runs-on: ubuntu-latest
name: Close Pull Request Job
steps:
- name: Close Pull Request
id: closepullrequest
uses: Azure/static-web-apps-deploy@v1
with:
azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_POLITE_CLIFF_06D4C2810 }}
action: "close"

References: Azure Bicep

Below are some Azure Bicep references:

Azure Static Web App
param staticSites_AzFw_Mon_name string = 'AzFw-Mon'

resource staticSites_AzFw_Mon_name_resource 'Microsoft.Web/staticSites@2022-03-01' = {
name: staticSites_AzFw_Mon_name
location: 'Central US'
sku: {
name: 'Free'
tier: 'Free'
}
properties: {
repositoryUrl: 'https://github.com/lukemurraynz/azure-firewall-mon'
branch: 'main'
stagingEnvironmentPolicy: 'Enabled'
allowConfigFileUpdates: true
provider: 'GitHub'
enterpriseGradeCdnStatus: 'Disabled'
}
}
Event Hub
param namespaces_AzFirewallMonitor_name string = 'AzFirewallMonitor'
param location string = resourceGroup().location


resource namespaces_AzFirewallMonitor_name_resource 'Microsoft.EventHub/namespaces@2022-01-01-preview' = {
name: namespaces_AzFirewallMonitor_name
location: 'Australia East'
sku: {
name: 'Basic'
tier: 'Basic'
capacity: 1
}
properties: {
minimumTlsVersion: '1.2'
publicNetworkAccess: 'Enabled'
disableLocalAuth: false
zoneRedundant: true
isAutoInflateEnabled: false
maximumThroughputUnits: 0
kafkaEnabled: false
}
}

resource namespaces_AzFirewallMonitor_name_AzMonitorListner 'Microsoft.EventHub/namespaces/authorizationrules@2022-01-01-preview' = {
parent: namespaces_AzFirewallMonitor_name_resource
name: 'AzMonitorListner'
location: location
properties: {
rights: [
'Listen'
'Send'
]
}
}


resource namespaces_AzFirewallMonitor_name_azmonitorcapture 'Microsoft.EventHub/namespaces/eventhubs@2022-01-01-preview' = {
parent: namespaces_AzFirewallMonitor_name_resource
name: 'azmonitorcapture'
location: location
properties: {
messageRetentionInDays: 1
partitionCount: 2
status: 'Active'
}
}

resource namespaces_AzFirewallMonitor_name_default 'Microsoft.EventHub/namespaces/networkRuleSets@2022-01-01-preview' = {
parent: namespaces_AzFirewallMonitor_name_resource
name: 'default'
location: location
properties: {
publicNetworkAccess: 'Enabled'
defaultAction: 'Allow'
virtualNetworkRules: []
ipRules: []
}
}

resource namespaces_AzFirewallMonitor_name_azmonitorcapture_AzMonitor 'Microsoft.EventHub/namespaces/eventhubs/authorizationrules@2022-01-01-preview' = {
parent: namespaces_AzFirewallMonitor_name_azmonitorcapture
name: 'AzMonitor'
location: location
properties: {
rights: [
'Listen'
]
}
dependsOn: [

namespaces_AzFirewallMonitor_name_resource
]
}

resource namespaces_AzFirewallMonitor_name_azmonitorcapture_Default 'Microsoft.EventHub/namespaces/eventhubs/consumergroups@2022-01-01-preview' = {
parent: namespaces_AzFirewallMonitor_name_azmonitorcapture
name: '$Default'
location: location
properties: {
}
dependsOn: [

namespaces_AzFirewallMonitor_name_resource
]
}