Deny Public IPs on VM Nic

By | March 8, 2019

I was looking for a sample Azure policy to deny the assignment of a public up to an Azure VM Nic. I found this blog post that seemed to fit the bill, but as a I was testing I started to run into issues. I would add a second IP on the same Nic and then enable Public IP. this operation would succeed every time.

I found a post on Azure Policy Aliases that led me in the right direction. From the blog:

“Several of the aliases that are available have a version that appears as a ‘normal’ name and another that has [*] attached to it. For example:

  • Microsoft.Storage/storageAccounts/networkAcls.ipRules
  • Microsoft.Storage/storageAccounts/networkAcls.ipRules[*]

The first example is used to evaluate the entire array, where the [*] alias evaluates each element of the array.”

networkAcls.ipRules[*].value – Checks each value property in the ipRules array.

 

  • As an array, each element will be processed.

    • “127.0.0.1” != “127.0.0.1” evaluates as false.
    • “127.0.0.1” != “192.168.1.1” evaluates as true.
    • At least one value property in the ipRules array evaluated as false, so the evaluation will stop.”

What we learn from this is that the alias with the [*] will expand the array and test each value against the condition. In this case not equals 127.0.0.1. The entire line will only evaluate to true if all of the array values evaluate to true against the condition (logical AND).

Going back to my issue, if only one of the IP addresses on the Nic has a public ip associated with it, the line evaluates to false due to the two values being ANDed together. Building out the possible outcomes, you can see in Table 1 that there is only one combination (both have public ips) where the policy evaluates to true and the deny kicks in. If we switch the ‘exists’ to false, in Table 2 you see that only one combination (both do not have public IPs) where the policy evaluates to true. In Table 3 we keep the ‘exists’ as false and put a not in front. This results in two combinations that result in true (either P or Q exclusively have a public IP). If we look at all of the tables,  we want to evaluate to true if P has a public IP, if Q has a public IP, or if both P & Q have a public IP. We can combine Table 1 and Table 3 to achieve this. The resulting formula is (P & Q = 1) || (!(P & Q = 0)). We have the existing block from the policy that we found on the web, we then use ANYOF to say that either the original block or our new bock needs to evaluate as true. The new block has the NOT in front of the block and we evaluate each value in array against ‘exists’ as false.

The policy is below.

P=First IP
Q=Second IP

Table 1. exists=true (P & Q = 1)

P Q (P&Q=1)
1 0 -> 0
0 1 -> 0
1 1 -> 1
0 0 -> 0

Table 2. exists=false  (P & Q = 0)

P Q   (P&Q=0)
1 0 -> 0
0 1 -> 0
1 1 -> 0
0 0 -> 1

Table 3. (not (exists=false)) !(P&Q=0)

P Q   (P&Q=0)  !(P&Q=0)
1 0 -> 0 -> 1
0 1 -> 0 -> 1
1 1 -> 0 -> 0
0 0 -> 1 -> 0

Resulting Formula

(P & Q = 1) || (!(P & Q = 0))

 

Leave a Reply

Your email address will not be published. Required fields are marked *