3

I am new at OPA/Rego and I am trying to write a policy to check if an Azure Network Security Group contains all the rules that I define on an array

package sample
default compliant = false
toSet(arr) = {x | x := arr[_]}
checkProperty(rule, index, propertySingular, propertyPlural) = true
{
    object.get(input.properties.securityRules[index].properties, propertySingular, "") == object.get(rule, propertySingular, "")
    count(toSet(object.get(input.properties.securityRules[index].properties, propertyPlural, [])) - toSet(object.get(rule, propertyPlural, []))) == 0
}
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
    checkProperty(rule, i, "sourcePortRange", "sourcePortRanges")
    checkProperty(rule, i, "destinationPortRange", "destinationPortRanges")
    checkProperty(rule, i, "sourceAddressPrefix", "sourceAddressPrefixes")
    checkProperty(rule, i, "destinationAddressPrefix", "destinationAddressPrefixes")
    input.properties.securityRules[i].properties.access == rule.access
    input.properties.securityRules[i].properties.priority == rule.priority
    input.properties.securityRules[i].properties.direction == rule.direction
}
compliant
{
    rules := [
            {
                "name": "name1",
                "provisioningState": "Succeeded",
                "description": "description1",
                "protocol": "*",
                "sourcePortRange": "*",
                "destinationPortRange": "53",
                "destinationAddressPrefix": "*",
                "access": "Allow",
                "priority": 1,
                "direction": "Inbound",
                "sourceAddressPrefixes":
                [
                    "xx.xx.xx.xx",
                    "xx.xx.xx.xx",
                    "xx.xx.xx.xx"
                ],
            },
            {
                "name": "name2",
                "provisioningState": "Succeeded",
                "description": "description2",
                "protocol": "*",
                "sourcePortRange": "*",
                "destinationPortRange": "54",
                "sourceAddressPrefix": "*",
                "access": "Allow",
                "priority": 2,
                "direction": "Outbound",
                "destinationAddressPrefixes":
                [
                    "xx.xx.xx.xx",
                    "xx.xx.xx.xx",
                    "xx.xx.xx.xx"
                ]
            }
        ]
    #checks
    existRule(rules[i])
}

The issue seem to be that when execute existRule(rules[i]) if one of the rules match it returns true, don't mather if other rules doesn't If I replace existRule(rules[i]) with existRule(rules[0]) or existRule(rules[1]), it return true or false depending on if the rule on that position matchs.

Is there any way to get the result of the execution of existRule(rules[i]) for all the elements of the array?

I already tried result := [existRule(rules[i])] but it only return one element with true

1 Answer 1

5

Sure! Use a list comprehension and call the function inside of it, then compare the size of the result to what you had before. Given your example, you would replace existRule(rules[i]) with something like this:

compliantRules := [rule | rule := rules[_]
                          existRule(rule)]
                              
count(compliantRules) == count(rules)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.