Azure Powershell - Applying multiple service endpoints to a subnet - azure

I have coded a powershell script to set an existing subnet to function as a service endpoint for multiple services. However, when I run the command line in the script, it doesn't add a new service endpoint, it just changes the existing one.
I am trying to parameterise this through Jenkins as well, which may be an added complication. I think if I can get the base syntax right then that shouldn't be a problem.
Syntax I am using is:
#Get vnet
$virtualnetwork = Get-AzureRmVirtualNetwork -Name $VN -ResourceGroupName $RG
#Configure service endpoint
Add-AzureRmVirtualNetworkSubnetConfig -Name $SN -AddressPrefix $SAP -
VirtualNetwork $virtualnetwork -ServiceEndpoint $EP
#Set configuration
$virtualnetwork | Set-AzureRmVirtualNetwork

You can use something like this to add as many endpoints as required:
$rgname = "amgar-dtl"
$vnName = "Dtlamgar-dtl"
$sname = "Dtlamgar-dtlSubnet"
$subnetPrefix = "10.0.0.0/20"
#Get vnet
$VirtualNetwork = Get-AzureRmVirtualNetwork -ResourceGroupName $rgname -Name $vnName | Get-AzureRmVirtualNetworkSubnetConfig -Name $sname
#Get existing service endpoints
$ServiceEndPoint = New-Object 'System.Collections.Generic.List[String]'
$VirtualNetwork.ServiceEndpoints | ForEach-Object { $ServiceEndPoint.Add($_.service) }
#Add new service endpoint
Get-AzureRmVirtualNetwork -ResourceGroupName $rgname -Name $vnName | Set-AzureRmVirtualNetworkSubnetConfig -Name $sname -AddressPrefix $subnetPrefix -ServiceEndpoint $ServiceEndPoint.Add("Microsoft.KeyVault") | Set-AzureRmVirtualNetwork
Hope this helps!

Successful syntax is:
#Vnet
$VN = "$ENV:VNET_NAME"
#Resource Group
$RG = "$ENV:RESOURCEGROUP_NAME"
#Subnet
$SN = "$ENV:SUBNET_NAME"
#Subnet Address Prexifx
$SAP = "$ENV:ADDRESS_PREFIX"
#ServiceEndpoint
$EP = "$ENV:SERVICE_ENDPOINT"
Write-Host "Importing the AzureRM module into the PowerShell session"
Import-Module AzureRM
Write-Host "Connect service principle account to Azure RM"
Connect-AzureRmAccount -ServicePrincipal -Credential $CREDS -TenantId $TID -Subscription $SID
#Get vnet
$VirtualNetwork = Get-AzureRmVirtualNetwork -ResourceGroupName $RG -Name $VN | Get-AzureRmVirtualNetworkSubnetConfig -Name $SN
#Get existing service endpoints
$ServiceEndPoint = New-Object 'System.Collections.Generic.List[String]'
$VirtualNetwork.ServiceEndpoints | ForEach-Object { $ServiceEndPoint.Add($_.service) }
$ServiceEndPoint.Add($EP)
#Add new service endpoint
Get-AzureRmVirtualNetwork -ResourceGroupName $RG -Name $VN | Set-AzureRmVirtualNetworkSubnetConfig -Name $SN -AddressPrefix $SAP -ServiceEndpoint $ServiceEndPoint | Set-AzureRmVirtualNetwork
Powershell does not appear to support the command $ServiceEndPoint.Add("Microsoft.KeyVault") with “|”. Once it was executed separately, the script worked.

Here is another version for those looking to process multiple subnets and to validate that the subnet doesn't already have the service endpoint enabled because it will error out if the same service is listed twice when modifying the subnet.
$subscription = "Enter Subscription ID here"
$subnets = #('my-subnet-1','my-subnet-2','my-subnet-3')
$vnetName = "MY-VNET"
$vnetRgName = "MY-VNET-RG"
$newEndpoint = "Microsoft.AzureCosmosDB"
Set-AzContext -Subscription $subscription
foreach($snet in $subnets){
Write-Host "Modifying Service Endpoints for subnet: $snet" -fore red -back white
$virtualNetwork = Get-AzVirtualNetwork -Name $vnetName -ResourceGroupName $vnetRgName | Get-AzVirtualNetworkSubnetConfig -Name $snet
$addrPrefix = $virtualNetwork.AddressPrefix
#Get existing service endpoints
$ServiceEndPoint = New-Object 'System.Collections.Generic.List[String]'
$virtualNetwork.ServiceEndpoints | ForEach-Object { $ServiceEndPoint.Add($_.service) }
if ($ServiceEndPoint -notcontains $newEndPoint){
$ServiceEndPoint.Add($newEndpoint)
}
#Add new service endpoint
Get-AzVirtualNetwork -Name $vnetName -ResourceGroupName $vnetRgName | Set-AzVirtualNetworkSubnetConfig -Name $snet -AddressPrefix $addrPrefix -ServiceEndpoint $ServiceEndPoint | Set-AzVirtualNetwork
}

Related

How to create multiple Subnets in pre-existing Vnet Powershell

I have the following code which works good for adding a few subnets but I would like for this script to leverage a CSV file to import from and add the subnets into a pre-existing Vnet?
$appssubnet = New-AzVirtualNetworkSubnetConfig -Name servers -AddressPrefix "172.16.1.0/24" -NetworkSecurityGroupId "/subscriptions/xxxxxxxxxx-xxxx-xxxx-xxxxx-xxxxxxxxxxxx/resourceGroups/powershell-grp/providers/Microsoft.Network/networkSecurityGroups/app-nsg1"`
-RouteTableId "/subscriptions/xxxxxxxxxx-xxxx-xxxx-xxxxx-xxxxxxxxxxxx/resourceGroups/powershell-grp/providers/Microsoft.Network/routeTables/powershell-rt"
$serversubnet = New-AzVirtualNetworkSubnetConfig -Name apps -AddressPrefix "172.16.2.0/24" -RouteTableId "/subscriptions/xxxxxxxxxx-xxxx-xxxx-xxxxx-xxxxxxxxxxxx/resourceGroups/powershell-grp/providers/Microsoft.Network/routeTables/powershell-rt"
$dmz = New-AzVirtualNetworkSubnetConfig -Name dmz -AddressPrefix "172.16.3.0/24"
$updatedvnet = New-AzVirtualNetwork -Name "testsubnet" -ResourceGroupName "powershell-grp" -Location "North Europe" -AddressPrefix "172.16.0.0/16" -Subnet $serversubnet, $dmz, $appssubnet -Force:$true
$updatedvnet | Set-AzVirtualNetwork
You can use the below powershell script.
$subnets1 = Import-Csv "C:\Users\v-XXXsXX18\Documents\TestCount.csv"
#$subnets1.subnetName
foreach ($subnet in $subnets1){
$dmz = New-AzVirtualNetworkSubnetConfig -Name $subnet.SubnetName -AddressPrefix $subnet.AddressPrefix
$vnet=Get-AzVirtualNetwork -Name "MyVirtualNetworkTes" -ResourceGroupName "v-raXXXXndtree"
$updatedvnet=Add-AzVirtualNetworkSubnetConfig -Name $dmz.Name -VirtualNetwork $vnet -AddressPrefix $dmz.AddressPrefix
$updatedvnet | Set-AzVirtualNetwork
}
Output--

Fix for the Subnet Missing Required Delegation

I have a Azure Resource Group and it has a vnet. The vnet has a subnet which has two service endpoints configured namely Microsoft.keyVault and Microsoft.Storage and the subnet also has a subnet delegation to Microsoft.Web/serverFarms.
Now I want to add another service endpoint Microsoft.ServiceBus to the same vnet using Azure Powershell. I executed the below code for that.
$virtualNetwork = Get-AzVirtualNetwork -ResourceGroupName $ResourceGroupName
Set-AzVirtualNetworkSubnetConfig -Name $virtualNetwork.Subnets.Name -VirtualNetwork $virtualNetwork -AddressPrefix $virtualNetwork.Subnets.AddressPrefix -ServiceEndpoint "Microsoft.ServiceBus"
$virtualNetwork | Set-AzVirtualNetwork
But the above code is throwing error at the last line of code saying that the Subnet is missing Required Delegation
Subnet requires any of the following delegation(s) [Microsoft.Web/serverFarms] to reference service association link
StatusCode: 400
ReasonPhrase: Bad Request
ErrorCode: SubnetMissingRequiredDelegation
But in portal I see it has the required delegation. How to fix this error?
Even though i have already added these service endpoint in my specific subnet and subnet also has a subnet delegation to Microsoft.Web/serverFarms able to add another service endpoint Microsoft.ServiceBus.
I would suggest you to use the following PowerShell script:
PowerShell Script:
$subscription = "b83c1edXXXXXXX-XXX"
$subnets = #('TestSubnet')
$vnetName = "Vnet1"
$vnetRgName = "X-rasXXXX-XX"
$newEndpoint = "Microsoft.ServiceBus"
Set-AzContext -Subscription $subscription
foreach($snet in $subnets){
Write-Host "Modifying Service Endpoints for subnet: $snet" -fore red -back white
$virtualNetwork = Get-AzVirtualNetwork -Name $vnetName -ResourceGroupName $vnetRgName | Get-AzVirtualNetworkSubnetConfig -Name $snet
$addrPrefix = $virtualNetwork.AddressPrefix
#Get existing service endpoints
$ServiceEndPoint = New-Object 'System.Collections.Generic.List[String]'
$virtualNetwork.ServiceEndpoints | ForEach-Object { $ServiceEndPoint.Add($_.service) }
if ($ServiceEndPoint -notcontains $newEndPoint){
$ServiceEndPoint.Add($newEndpoint)
}
$delegation=$virtualNetwork.Delegations
#Add new service endpoint
Get-AzVirtualNetwork -Name $vnetName -ResourceGroupName $vnetRgName | Set-AzVirtualNetworkSubnetConfig -Name $snet -AddressPrefix $addrPrefix -ServiceEndpoint $ServiceEndPoint -Delegation $delegation | Set-AzVirtualNetwork
}
Reference : Azure Powershell - Applying multiple service endpoints to a subnet

Azure Powershell (Az module) get public IP address

With the new Az module for Azure, does anyone have the syntax for getting the public IP address of an Azure VM using the name?
The commandlet Get-AzPublicIpAddress has no argument for the VM name, only the IP object name
This works, but I'm not using the machine name here, it's the name of the IP object itself:
$CurrentIp = (Get-AzPublicIpAddress -ResourceGroupName 'RG1' -Name 'MyVMname-ip').IpAddress
I can't figure out how to just get it from the VM object i.e. this doesn't work:
Get-AzVM -ResourceGroupName 'RG1' -Name 'MyVMname' | Get-AzPublicIpAddress
As I know, it's impossible to get the VM public IP through just one PowerShell Get-AzPublicIpAddress with the VM name. And the public IP in Azure is an individual resource associated with the network interface, not the VM.
As you see, there no parameter for VM name to get the public IP in that document. But you can get the public IP through a PowerShell script just with the VM name and resource group name. The script shows below:
$vm = Get-AzureRmVM -ResourceGroupName yourRG -Name vmNamme
$nic = $vm.NetworkProfile.NetworkInterfaces[0].Id.Split('/') | select -Last 1
$publicIpName = (Get-AzureRmNetworkInterface -ResourceGroupName yourRG -Name $nic).IpConfigurations.PublicIpAddress.Id.Split('/') | select -Last 1
$publicIpAddress = (Get-AzureRmPublicIpAddress -ResourceGroupName yourRG -Name $publicIpName).IpAddress
Write-Output $vmName $publicIpAddress
Or just one CLI command to get the public IP like this:
az vm show -d -g yourRG -n vmName --query publicIps
I think this is a more thorough answer, as this uses PowerShell Az as the original question intended to use. In addition, it leverages Generic.List[psobject] which is useful for later playing with the data.
$rg = 'RgName'
$Ips = Get-AzNetworkInterface -ResourceGroupName $rg
$vmDetails = New-Object "System.Collections.Generic.List[psobject]"
foreach ($instance in $Ips){
$Vm = ($instance.VirtualMachine).Id.Split('/') | select -Last 1
$PrivateIp = $instance.IpConfigurations.PrivateIpAddress
$PublicIp = (Get-AzPublicIpAddress -ResourceGroupName $rg -Name ($instance.IpConfigurations.publicIpAddress.Id.Split('/') | select -Last 1)).IpAddress
$obj = New-Object psobject -Property #{
ResourceGroupName = $rg
VmName = $vm
PrivateIp = $PrivateIp
PublicIp = $PublicIp
}
$vmDetails.Add($obj)
}
Write-Output $vmDetails
This isn't as straight forward as Az CLI unfortunately but a good script to have regardless for Az modules.
Here's my take on Andrew Harris' answer, it filters out network interfaces not attached to machines and accounts for VMs that don't have a public IP:
function Get-VmIP {
<#
.SYNOPSIS
Returns the IP addresses for all VMs in the current subscription.
#>
[cmdletbinding()]
param()
$Interfaces = Get-AzNetworkInterface
foreach ($Interface in $Interfaces) {
if ($Interface.VirtualMachine) {
$VMName = $Interface.VirtualMachine.Id.split('/')[-1]
$PrivateIP = $Interface.IpConfigurations.PrivateIpAddress
$PublicIP = if ($Interface.IpConfigurations.publicIpAddress) {
Get-AzPublicIpAddress -Name ($instance.IpConfigurations.publicIpAddress.Id.Split('/')[-1]).IpAddress
}
[PSCustomObject]#{
VMName = $VMName
RGName = $Interface.ResourceGroupName
PrivateIP = $PrivateIP
PublicIP = $PublicIP
}
}
}
}
This is a corrected version of the Mark Wragg's script earlier in this thread:
function Get-VmIP {
<#
.SYNOPSIS
Returns the IP addresses for all VMs in the current subscription.
#>
[cmdletbinding()]
param()
$Interfaces = Get-AzNetworkInterface
foreach ($Interface in $Interfaces) {
if ($Interface.VirtualMachine) {
$VMName = $Interface.VirtualMachine.Id.split('/')[-1]
$PrivateIP = $Interface.IpConfigurations.PrivateIpAddress
$PublicIpAddressConfig = $Interface.IpConfigurations.publicIpAddress
$PublicIP = $null
$pconfigname = $null
if ($PublicIpAddressConfig) {
$pconfigname = $PublicIpAddressConfig.Id.Split('/')[-1]
$PublicIP = (Get-AzPublicIpAddress -Name $pconfigname).IpAddress
}
[PSCustomObject]#{
VMName = $VMName
RGName = $Interface.ResourceGroupName
PrivateIP = $PrivateIP
PublicIP = $PublicIP
}
}
}
}
The accepted answer uses AzureRM PowerShell module which is now obsoleted by Az module:
$VM = Get-AzVM -ResourceGroupName $ResourceGroupName -VMName $VMName
$NetworkInterfaceName = $VM.NetworkProfile.NetworkInterfaces[0].Id.Split('/')[-1]
$NetworkInterface = Get-AzNetworkInterface -ResourceGroupName $VM.ResourceGroupName -Name $NetworkInterfaceName
$PublicIpAddressName = $NetworkInterface.IpConfigurations.PublicIpAddress.Id.Split('/')[-1]
$PublicIpAddress = Get-AzPublicIpAddress -ResourceGroupName $VM.ResourceGroupName -Name $PublicIpAddressName
Write-Host "IP: $($PublicIpAddress.IpAddress), FQDN: $($PublicIpAddress.DnsSettings.Fqdn)"
Scope of the script is within an Azure subscription.
Below is the one-liner script which returns Name, PublicIpAllocaitonMethod(It's basically the type of the IP address whether it's a Static or Public IP) and the IpAddress properties of all the Network interfaces in a subscription.
(Get-AzNetworkInterface ).IpConfigurations.PublicIpAddress.Id | Foreach-Object -Process {$_.Split('/')| select -Last 1} | Foreach-Object -Process {Get-AzPublicIpAddress -Name $_} | Format-List Name, PublicIpAllocationMethod,IpAddress
If we remove the last statement Format-List it will display all the properties of the network interfaces that are having public IP addresses.

Associate NSG to Subnets in foreach loop Powershell

I've created a small script which creates subnets, I can then pass them through a loop and create network security groups (nsg) with the name of the subnet + -nsg, but when I try to associate the nsg to the subnet it fails saying the nsg doesn't exist. So i created two small scripts and split the create nsg from the associate nsg, but again same error.
Error:
Set-AzureNetworkSecurityGroupToSubnet : ResourceNotFound : The Network Security Group nsg-test-nsg does not exist.
But this does definitely exist.
The code I have is:
$resource = "rg-subnets"
$vnetName = "vnet-bmg"
$loc = "West Europe"
$vnet = Get-AzureRmVirtualNetwork -ResourceGroupName $resource -Name $vnetName
$sub = (Get-AzureRmVirtualNetworkSubnetConfig -VirtualNetwork $vnet).name
foreach ($subnet in $sub){
New-AzureRmNetworkSecurityGroup -Name $subnet-nsg -ResourceGroupName $resource -Location $loc -Force
Set-AzureNetworkSecurityGroupToSubnet -Name $subnet-nsg -VirtualNetworkName $vnetName -SubnetName $subnet
}
Help! :)
This worked for me,
$resource = "rg-subnets"
$vnetName = "vnet-bmg"
$loc = "West Europe"
$vnet = Get-AzureRmVirtualNetwork -ResourceGroupName $resource -Name $vnetName
$sub = (Get-AzureRmVirtualNetworkSubnetConfig -VirtualNetwork $vnet).name
foreach ($subnet in $sub){
New-AzureRmNetworkSecurityGroup -Name $subnet-nsg -ResourceGroupName $resource -Location $loc -Force
$subnetName = Get-AzureRmVirtualNetworkSubnetConfig -VirtualNetwork $vnet -Name $subnet
$nsg = Get-AzureRmNetworkSecurityGroup -ResourceGroupName $resource -Name "$subnet-nsg"
$subnetName.NetworkSecurityGroup = $nsg
Set-AzureRmVirtualNetwork -VirtualNetwork $vnet -Verbose
}

Not able to connect through Rasdial in azure ARM VPN connection

I am not able connect to VPN using powershell cmdlet. I use 'rasdial' from a build agent to connect to vpn, so that we can trigger automated tests. The whole process is automated.
Earlier same rasdial command - Rasdial "VPNName" was working perfectly fine with classic model (ASM) of vpn. But, after I migrated to ARM, I am facing this issue. However through UI i.e. clicking on buttons to connect to vpn is working fine but our need is to connect through script.
I am getting a message-
This function is not supported on this system.
NB: I am following this post- https://dzone.com/articles/deconstructing-azure-point
The same workaround worked in ASM but not woking in ARM. What can be another workaround or fix for this ?
I am using below script to create and download the VPN package. I am not sure I am missing something in my script which is causing this issue-
$VNetName = "MYVPN"
$SubName = "Subnet-1"
$GWSubName = "GatewaySubnet"
$VNetPrefix1 = "15.3.0.0/16"
$SubPrefix = "15.3.1.0/24"
$GWSubPrefix = "15.3.200.0/26"
$VPNClientAddressPool = "158.17.201.0/24"
$RG = "VMsRG"
$Location = "West Europe"
$DNS = "15.3.0.0"
$GWName = "GateWay"
$GWIPName = "GateWayIP"
$GWIPconfName = "GateWayIPConfig"
$P2SRootCertName = "XXXXX.cer"
$DeployUserName = "atf#hotmail.com"
$DeployUserPassword = "XXXXX"
$Azurepwd = ConvertTo-SecureString $DeployUserPassword -AsPlainText -Force
$AzureCredential = new-object -typename System.Management.Automation.PSCredential -argumentlist $DeployUserName, $Azurepwd
Add-AzureRmAccount -credential $AzureCredential -SubscriptionName Development
New-AzureRmResourceGroup -Name $RG -Location $Location
$fesub = New-AzureRmVirtualNetworkSubnetConfig -Name $SubName -AddressPrefix $SubPrefix
$gwsub = New-AzureRmVirtualNetworkSubnetConfig -Name $GWSubName -AddressPrefix $GWSubPrefix
New-AzureRmVirtualNetwork -Name $VNetName -ResourceGroupName $RG -Location $Location -AddressPrefix $VNetPrefix1 -Subnet $fesub, $gwsub -DnsServer $DNS
$vnet = Get-AzureRmVirtualNetwork -Name $VNetName -ResourceGroupName $RG
$subnet = Get-AzureRmVirtualNetworkSubnetConfig -Name "GatewaySubnet" -VirtualNetwork $vnet
$pip = New-AzureRmPublicIpAddress -Name $GWIPName -ResourceGroupName $RG -Location $Location -AllocationMethod dynamic
$ipconf = New-AzureRmVirtualNetworkGatewayIpConfig -Name $GWIPconfName -Subnet $subnet -PublicIpAddress $pip
$MyP2SRootCertPubKeyBase64 = "XXXXX"
$p2srootcert = New-AzureRmVpnClientRootCertificate -Name "P2SVNETRootCertName" -PublicCertData $MyP2SRootCertPubKeyBase64
New-AzureRmVirtualNetworkGateway -Name $GWName -ResourceGroupName $RG -Location $Location -IpConfigurations $ipconf -GatewayType Vpn -VpnType RouteBased -EnableBgp $false -GatewaySku Standard -VpnClientAddressPool $VPNClientAddressPool -VpnClientRootCertificates $p2srootcert
Get-AzureRmVpnClientPackage -ResourceGroupName $RG -VirtualNetworkGatewayName $GWName -ProcessorArchitecture Amd64
As I am able to connect using GUI. I hope script is doing it's job.
After 4 Months I got a reply from MS (as I raised a ticket for the same).
They told Rasdial is not supported by Azure VPN Client Package till date. Also, Even after deconstructing-the-azure-point-to-site-vpn lacks addition of route which should be taken care by adding the route explicitly.
So as an workaround I did the steps provided in the blog - http://www.diaryofaninja.com/blog/2013/11/27/deconstructing-the-azure-point-to-site-vpn-for-command-line-usage
However the last part of adding the route is a bit complex. So, for adding route I have created my own PS script-
$Subnet = #("10.0.1.0", "10.0.2.0","10.0.3.0")
$VPNClientAddressPool = "x.x.x"
$Mask = "255.255.0.0"
$azureIpAddress = ""
$VPNCmd = "MYVPNName"
Here x.x.x are the 3 octet that can be found in "GateWay - Point-to-site configuration" of the VPN-
$routeExists = route print | findstr $VPNClientAddressPool
if($routeExists)
{
route delete $Subnet
}
rasdial $VPNCmd > $null
$azureIPAddress = ipconfig | findstr $VPNClientAddressPool
if($azureIPAddress -ne $null)
{
$azureIpAddress = $azureIpAddress.Split(": ")
$azureIpAddress = $azureIpAddress[$azureIpAddress.Length-1]
$azureIpAddress = $azureIpAddress.Trim()
route add $Subnet MASK $Mask $azureIPAddress
}
This solved the purpose for me. Basically You just need to take care of the route add part.
Your PowerShell script seems fine (I didn't try the login and resource group pieces, but everything else works from $fesub on.) except for the third line from the bottom. The -Name tag which you currently have as "P2SVNETRootCertName" needs to be the same as your $P2SRootCertName. For more information, refer to Azure documentation: https://azure.microsoft.com/en-us/documentation/articles/vpn-gateway-howto-point-to-site-rm-ps/
As for Rasdial, another StackOverflow post has answered this: Azure Virtual Network Point-to-Site (ex. Azure Connect) autoconnect
-Bridget [MSFT]

Resources