8 min to read.
Abstract
Virtual machines should be connected to an
approved virtual network - This default Azure policy is fantastic. This policy
checks if a VM is part of approved VNET; else it shows compliance message.
However it only offers VMs to be checked against
single VNET name. In reality, we have flood of Azure VNETs across multiple
Azure subscriptions.
So we need a policy that can check all Azure
VMs against “multiple azure Virtual Networks”.
This article talks about creating a
policy that allows to provision Azure VMs inside only allowed list of VNETs.
The Challenge
This policy will be built as custom. I want
to do below –
Evaluate every NIC
against the VNET names present in input parameter. Refer yellow and green highlight below. I need to –
1.
Loop using for or for-each
2.
Dynamically get values of all items present in a parameter after
performing “split” on the input string.
"mode": "All",
"policyRule": {
"if": {
"allOf": [
{
"field": "type",
"equals": "Microsoft.Network/networkInterfaces"
},
{
"not": {
"field": "Microsoft.Network/networkInterfaces/ipconfigurations[*].subnet.id",
"contains": "[parameters('virtualNetworkIds')]"
}
}
]
},
"then": {
"effect": "[parameters('effect')]"
}
},
"parameters": {
"effect": {
"type": "String",
"metadata": {
"displayName": "Effect",
"description": "The effect determines what happens when the policy rule is evaluated to match"
},
"allowedValues": [
"Audit",
"Deny",
"Disabled"
],
"defaultValue": "Audit"
},
"virtualNetworkIds": {
"type": "String",
"metadata": {
"displayName": "Virtual network Names",
"description": "Resource name of the virtual network. Example: Add , separated multiple values."
}
}
}
}
The input parameter to this policy will be
more than one names of VNETs. Unfortunately in Azure policy I could not find a
way to iterate over input parameters by using for-each loop construct.
There is a Current function available
however it can be used only when we are using Count and Where function. Also these
functions are used over Field property, used as an array. These functions cant
be used when input parameter is not an array.
Therefore we need a way to iterate over input parameters array and comparing every parameter
value with one subnet id Field highlighted as green above.
Solution
If we see the outcome of below line - "Microsoft.Network/networkInterfaces/ipconfigurations[*].subnet.id",
It will be resolved to id format of subnet similar
to below - "/subscriptions/SubId/resourceGroups/rg--net/providers/Microsoft.Network/virtualNetworks/vnet-01/subnets/default"
So we just need to use expertise string
functions lie split, combine, concat etc. in a such a way that we take out only
VENT name from above string. Therefore lets write code to covert to string and
then split so as to get VNET name. Final code is as below –
"[split(string(field('Microsoft.Network/networkInterfaces/ipconfigurations[*].subnet.id')),'/')[8]]"
Creating Custom Policy
Login to Azure portal -> In middle top search
box type “Policies” -> Select Definitions -> Create New. Then add values
as shown below. The name of the policy I have given as “Azure Resources should
be connected to an approved virtual networks”. Code of policy to be added under
section “POLICY RULE” can be taken from github link shared below.
Also whenever we create custom policy always
get it added in new Category as “My Custom Policies”. Do not add any Role
Assignment. Then save to finish policy creation wizard. [click to get better view.]
Open the newly created policy and click on
Assign. [click to get better view].
On the Basics tab, make “policy enforcement”
option as disabled. We want to just view the report of azure resources not
deployed in approved VNET. If we enforce policy means it will not allow to provision
new resources in any of the VNET other
than listed in parameters tab below. For testing purpose I disabled
policy enforcement.
Under “Remediation” tab uncheck the option “create
a managed identity”.
On Parameters tab, make sure that you add
names of all VNETs against which you want to evaluate azure resources is added
in below shown format only. Then Click on “Save” button for VNET names added
and click on “Review and Create” to complete assignment process.
Output
Virtual Machines
I could see that Virtual Machines not listed
under the VNETs I added as parameter. Refer screenshots [click to get better view] –
Same policy will also be automatically applied
on Azure App Service configured with private endpoint. Refer below output –
Full and final working policy is present at
this Github link –
Important –
This policy will not work for Azure
Kubernetes Service, VM Scale Sets as their NIC resource provider format is
different. However this policy should work as is for all types of private
endpoints where NIC is create with resource provider format of Microsoft.Network/networkInterfaces/.
I have not tested with other types of private
endpoint. Please test it and add your experience in comments.
Conclusion
Hope this article helped you to build custom
policy and helped to achieve your compliance and governance. Let me know your
views in comments section below to improve and what are your thoughts on this
approach.
Happy Azure Governance!!
A humble request!
Internet is creating a lot of digital
garbage. If you feel this a quality blog and someone will definitely get
benefited, don't hesitate to hit share button present below. Your one share
will save many precious hours of a developer. Thank you.
Next Related Posts
Azure
Virtual Machines – real world frequently asked questions – not easily answered.
Start
stop multiple Azure VMs on schedule and save cost!
Azure
Migration frequently asked questions, not easily answered!