I am new at Rego and I am trying to write a policy in order to check if there is a set of rules already created on certain Azure NSGs.
Input test:
{
"name": "<name>",
"id": "<id>",
"etag": "<etag>",
"type": "<resourcetype>",
"location": "<location>",
"properties":
{
"provisioningState": "Succeeded",
"resourceGuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"securityRules":
[
{
"name": "<rule name>",
"id": "<id>",
"etag": "<etag",
"type": "<type>",
"properties":
{
"provisioningState": "Succeeded",
"description": "....",
"protocol": "*",
"sourcePortRange": "*",
"destinationPortRange": "53",
"sourceAddressPrefix": "*",
"access": "Allow",
"priority": 1,
"direction": "Outbound",
"sourcePortRanges": [],
"destinationPortRanges": [],
"sourceAddressPrefixes": [],
"destinationAddressPrefixes":
[
"10.0.0.1",
"10.0.0.2",
"10.0.0.3"
]
}
}
]
{
}
I wrote a custom function in order to check the values. Below is the code that I am testing in The Rego Playground
existRule(rule) = true
{
input.properties.securityRules[i].name == rule.name
input.properties.securityRules[i].properties.provisioningState == rule.provisioningState
input.properties.securityRules[i].properties.description == rule.description
input.properties.securityRules[i].properties.protocol == rule.protocol
input.properties.securityRules[i].properties.access == rule.access
input.properties.securityRules[i].properties.priority == rule.priority
input.properties.securityRules[i].properties.direction == rule.direction
}
rule = {
"name": "name",
"provisioningState": "Succeeded",
"description": "description",
"protocol": "*",
"sourcePortRange": "*",
"destinationPortRange": "1",
"sourceAddressPrefix": "*",
"access": "Allow",
"priority": 1,
"direction": "Outbound",
"destinationAddressPrefix": "",
"sourcePortRanges": [],
"destinationPortRanges": [],
"sourceAddressPrefixes": [],
"destinationAddressPrefixes": [
"10.0.0.1",
"10.0.0.2",
"10.0.0.3",
"10.0.0.4"
]
}
rules
{
existRule(rule)
}
which is working for the properties that I define above, however I am having an issue when trying to compare arrays, particularly in this example with destinationAddressPrefixes I have tried the following:
test1 { input.properties.securityRules[i].properties.destinationAddressPrefixes == rule.destinationAddressPrefixes }
Always returns false
With the following line I can check one destination address from the input against a specific ip, however I can not achive a compare of all the address of the input against the ones of the rule that is defined in the example
onerule {input.properties.securityRules[i].properties.destinationAddressPrefixes[_] == "10.0.0.1"}
test2 {input.properties.securityRules[i].properties.destinationAddressPrefixes[_] == rule.destinationAddressPrefixes[j]}
test3 {input.properties.securityRules[i].properties.destinationAddressPrefixes[j] == rule.destinationAddressPrefixes[k]}
test2 and test3 always return true, even when there is a rule that is not in the input. I also tried and array difference
x := input.properties.securityRules[i].properties.destinationAddressPrefixes - rule.destinationAddressPrefixes
but I get the following error:
rego_type_error: minus: invalid argument(s) have: (any, array<string, string, string, string, string, string, string, string, string, string, string, string, string, string>, ???) want: (any<number, set[any]>, any<number, set[any]>, any<number, set[any]>)
Do you know if it is feasible to achieve what I am looking for? Or is there a different way to make a look of the array and compare the values one by one?
What does rule3400.destinationAddressPrefixes
look like?
If you want to compare for exact equality between two arrays, ==
should suffice.
If all elements are known to be unique and order doesn't matter (which seems to be the case in your example) you could convert the arrays to sets using a set comprehension. This makes it possible to subtract one set from another such as you tried to do with arrays directly.
to_set(arr) = {x | x := arr[_]}
input_prefixes := to_set(input.properties.securityRules[i].properties.destinationAddressPrefixes)
destination_prefixes := to_set(rule3400.destinationAddressPrefixes)
x := input_prefixes - destination_prefixes