Create Azure vnet, subnet and Network security group with application policies with powershell

In a previous post I showed you how to create a resource group. The next thing I want to show you is how to create a vnet, subnet and a network security group with application security rules built in. This will result in a new network where we can place VMs or other objects. I am going to break down each section of this script and explain what is happening. At the end, I will put it all together so you can tweak it and use in your own environment.

Variables

This is the section you will change to fit your resource group, location and subnet preferences.

### Change these to your liking
$LocationName = "westus"
$ResourceGroupName = "Skylar-Testing"
$VnetAddressPrefix = "10.50.0.0/24"
$SubnetAddressPrefix = "10.50.0.0/24"

### Change these only if you don't like my naming convention
$NetworkName = "$ResourceGroupName-vnet"
$SubnetName = "$ResourceGroupName-subnet"

Create Application Security Groups

Application security groups are what you will use to define allow/deny rules based on ports for your VMs. In my example I make 3 groups;

Management-Linux
– I will use this group to attach a rule to allow SSH (Port 22) traffic.

Management-Windows
– I will use this group to attach a rule to allow RDP (Port 3389) traffic.

Web
– I will use this group to attach a rule to allow Web (Ports 80, 443) traffic.

### Create Application security Groups if they dont already exist
try {
    $asgLinux = get-AzApplicationSecurityGroup -Name "Management-Linux" -ResourceGroupName $ResourceGroupName -ErrorAction Stop
}
catch {
    $asgLinux = New-AzApplicationSecurityGroup -Name "Management-Linux" -Location $LocationName -ResourceGroupName $ResourceGroupName
}
try {
    $asgWindows = get-AzApplicationSecurityGroup -Name "Management-Windows" -ResourceGroupName $ResourceGroupName -ErrorAction Stop
}
catch {
    $asgWindows = New-AzApplicationSecurityGroup -Name "Management-Windows" -Location $LocationName -ResourceGroupName $ResourceGroupName  
}
try {
    $asgWeb = get-AzApplicationSecurityGroup -Name "Web" -ResourceGroupName $ResourceGroupName -ErrorAction Stop
}
catch {
    $asgWeb = New-AzApplicationSecurityGroup -Name "Web" -Location $LocationName -ResourceGroupName $ResourceGroupName
}

These are just the groups I am making, your needs may vary and in the next section you will see where the actual rules come into play.

Create Network Security Group (NSG) and apply rules

Here is where we create the actual nsg and apply rules to it. Your rules may vary but I think this is a good start. You might notice that the priority of each rule is set 10 apart. This allows us to add rules in between these few defaults. That way we can override one of these with a rule for a specific situation and put the priority lower than the more strict default rule. Another thing to note on the two management rules. In the code for this example I have the SourceAddresssPrefix set to Internet. This is not best practice for an actual production environment. Ideally you just use this for testing or better yet scope it down to your public IP. It would look something like 0.0.0.0/32 where the 0’s would be your public IP. You can get that easily here.

### Check to see if the NSG already exists and creates if not
try {
    $nsg = get-AzNetworkSecurityGroup -ResourceGroupName $ResourceGroupName -Name "$NetworkName-NSG" -ErrorAction Stop
}
catch {
    ### Security Group rules
    $RDP_Rule = New-AzNetworkSecurityRuleConfig -Name rdp-rule -Description "Allow RDP" `
    -Access Allow -Protocol Tcp -Direction Inbound -Priority 100 `
    -SourceAddressPrefix Internet -SourcePortRange * `
    -DestinationApplicationSecurityGroup $asgWindows -DestinationPortRange 3389

    $HTTP_Rule = New-AzNetworkSecurityRuleConfig -Name http-rule -Description "Allow HTTP" `
    -Access Allow -Protocol Tcp -Direction Inbound -Priority 110 `
    -SourceAddressPrefix Internet -SourcePortRange * `
    -DestinationApplicationSecurityGroup $asgWeb -DestinationPortRange 80

    $HTTPS_Rule = New-AzNetworkSecurityRuleConfig -Name https-rule -Description "Allow HTTPS" `
    -Access Allow -Protocol Tcp -Direction Inbound -Priority 120 `
    -SourceAddressPrefix Internet -SourcePortRange * `
    -DestinationApplicationSecurityGroup $asgWeb -DestinationPortRange 443

    $SSH_Rule = New-AzNetworkSecurityRuleConfig -Name ssh-rule -Description "Allow SSH" `
    -Access Allow -Protocol Tcp -Direction Inbound -Priority 130 `
    -SourceAddressPrefix Internet -SourcePortRange * `
    -DestinationApplicationSecurityGroup $asgLinux -DestinationPortRange 22 

    ### Create Network Security Group
    $nsg = New-AzNetworkSecurityGroup -ResourceGroupName $ResourceGroupName -Location $LocationName -Name "$NetworkName-NSG" -SecurityRules $RDP_Rule,$SSH_Rule,$HTTP_Rule,$HTTPS_Rule

}

Create vnet and subnet

Now that we have our asg’s and nsg we can create the vnet and associate it with what we created above. This is probably the shortest most straight forward section, but it couldn’t exist without the stuff we just did. Well it could, just wouldn’t have any security and we don’t want that! This section will check and make sure the vnet doesn’t already exist and then it uses all the info from above to create the vnet and the subnet inside. You shouldn’t have to edit this section.

#Check for Network and create if it does not exist
try {
    Get-AzResourceGroup $ResourceGroupName | Get-AzVirtualnetwork -Name $NetworkName -ErrorAction Stop
    Write-Host "Network exists!" -ForegroundColor DarkGreen
}
catch {
    Write-Host "Network does not exist.  It will now be created." -ForegroundColor DarkRed
    ### Create vnet and subnet
    $SingleSubnet = New-AzVirtualNetworkSubnetConfig -Name $SubnetName -AddressPrefix $SubnetAddressPrefix -NetworkSecurityGroup $nsg -ErrorAction Stop
    $Vnet = New-AzVirtualNetwork -Name $NetworkName -ResourceGroupName $ResourceGroupName -Location $LocationName -AddressPrefix $VnetAddressPrefix -Subnet $SingleSubnet -ErrorAction Stop
    Write-Host "Completed!" -ForegroundColor DarkGreen    
}

Put it all together

Here is the script in its entirety. Hopefully the explanation helped. This was kind of weird the first few times I did it.

$LocationName = "westus"
$ResourceGroupName = "Testing42"
$NetworkName = "$ResourceGroupName-vnet"
$VnetAddressPrefix = "10.50.0.0/24"
$SubnetName = "$ResourceGroupName-subnet"
$SubnetAddressPrefix = "10.50.0.0/24"


### Create Application security Groups if they dont already exist
try {
    $asgLinux = get-AzApplicationSecurityGroup -Name "Management-Linux" -ResourceGroupName $ResourceGroupName -ErrorAction Stop
}
catch {
    $asgLinux = New-AzApplicationSecurityGroup -Name "Management-Linux" -Location $LocationName -ResourceGroupName $ResourceGroupName
}
try {
    $asgWindows = get-AzApplicationSecurityGroup -Name "Management-Windows" -ResourceGroupName $ResourceGroupName -ErrorAction Stop
}
catch {
    $asgWindows = New-AzApplicationSecurityGroup -Name "Management-Windows" -Location $LocationName -ResourceGroupName $ResourceGroupName  
}
try {
    $asgWeb = get-AzApplicationSecurityGroup -Name "Web" -ResourceGroupName $ResourceGroupName -ErrorAction Stop
}
catch {
    $asgWeb = New-AzApplicationSecurityGroup -Name "Web" -Location $LocationName -ResourceGroupName $ResourceGroupName
}


### Check to see if the NSG already exists and creates if not
try {
    $nsg = get-AzNetworkSecurityGroup -ResourceGroupName $ResourceGroupName -Name "$NetworkName-NSG" -ErrorAction Stop
}
catch {
    ### Security Group rules
    $RDP_Rule = New-AzNetworkSecurityRuleConfig -Name rdp-rule -Description "Allow RDP" `
    -Access Allow -Protocol Tcp -Direction Inbound -Priority 100 `
    -SourceAddressPrefix Internet -SourcePortRange * `
    -DestinationApplicationSecurityGroup $asgWindows -DestinationPortRange 3389

    $HTTP_Rule = New-AzNetworkSecurityRuleConfig -Name http-rule -Description "Allow HTTP" `
    -Access Allow -Protocol Tcp -Direction Inbound -Priority 110 `
    -SourceAddressPrefix Internet -SourcePortRange * `
    -DestinationApplicationSecurityGroup $asgWeb -DestinationPortRange 80

    $HTTPS_Rule = New-AzNetworkSecurityRuleConfig -Name https-rule -Description "Allow HTTPS" `
    -Access Allow -Protocol Tcp -Direction Inbound -Priority 120 `
    -SourceAddressPrefix Internet -SourcePortRange * `
    -DestinationApplicationSecurityGroup $asgWeb -DestinationPortRange 443

    $SSH_Rule = New-AzNetworkSecurityRuleConfig -Name ssh-rule -Description "Allow SSH" `
    -Access Allow -Protocol Tcp -Direction Inbound -Priority 130 `
    -SourceAddressPrefix Internet -SourcePortRange * `
    -DestinationApplicationSecurityGroup $asgLinux -DestinationPortRange 22 

    ### Create Network Security Group
    $nsg = New-AzNetworkSecurityGroup -ResourceGroupName $ResourceGroupName -Location $LocationName -Name "$NetworkName-NSG" -SecurityRules $RDP_Rule,$SSH_Rule,$HTTP_Rule,$HTTPS_Rule

}

#Check for Network and create if it does not exist
try {
    Get-AzResourceGroup $ResourceGroupName | Get-AzVirtualnetwork -Name $NetworkName -ErrorAction Stop
    Write-Host "Network exists!" -ForegroundColor DarkGreen
}
catch {
    Write-Host "Network does not exist.  It will now be created." -ForegroundColor DarkRed
    ### Create vnet and subnet
    $SingleSubnet = New-AzVirtualNetworkSubnetConfig -Name $SubnetName -AddressPrefix $SubnetAddressPrefix -NetworkSecurityGroup $nsg -ErrorAction Stop
    $Vnet = New-AzVirtualNetwork -Name $NetworkName -ResourceGroupName $ResourceGroupName -Location $LocationName -AddressPrefix $VnetAddressPrefix -Subnet $SingleSubnet -ErrorAction Stop
    Write-Host "Completed!" -ForegroundColor DarkGreen    
}
Tagged : / / /

Create an Azure Resource Group with Powershell

Resource groups are a fundamental component of Azure. Your VMs, Networks, Storage account(s), etc. all live in resource groups. Before we run the command we need to figure out WHERE we want to put the resource group. You can do this a few ways; one way is to pick from Microsoft’s website here. Another way is to list them from powershell:

List locations:

#List all Locations
Get-AzLocation

#To filter the list
Get-AzLocation | where {$_.Displayname -like "*west*"}

The info we need to is the Location. Once we have our location, we are ready to create our new resource group. You can do so with the following command. Make sure you are connected to Azure, you can see how to connect here.

Create Resource Group (Single Command):

New-AzResourceGroup -Name "Testing42" -Location "westus"

Create Resource Group (With Error Checking):

This is the same thing as above, just with a try-catch statement for error checking. This is what you would want to use in a larger script to make sure the resource group already existed.

$LocationName = "westus"
$ResourceGroupName = "Testing42"

#Check for resource group and create if it does not exist
try {
    Get-AzResourceGroup -Name $ResourceGroupName -ErrorAction Stop
    Write-Host "Resource group exists.  VM will be placed along side existing resources" -ForegroundColor DarkGreen
}
catch {
    Write-Host "Resource group does not exist.  It will now be created." -ForegroundColor DarkRed
    try {
        New-AzResourceGroup -Name $ResourceGroupName -Location $LocationName -Verbose -ErrorAction Stop        
        Write-Host "Completed!" -ForegroundColor DarkGreen        
    }
    catch {
        Write-Host "Failed to create resource group"
        exit        
    }
}
Creating a resource group

After running the command we get output that it was successful. It takes a minute or two for the resource group to show up in the Azure portal. If we want remove the resource group that can be done with this command.

Remove Resource Group:

Get-AzResourceGroup -Name "Testing42" | Remove-AzResourceGroup
Removing a resource group
Tagged : /