简体   繁体   中英

Rego Validation Array Compare

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM