'REGO: Is it possible to parse a regex group from the regex statement?

Cant find any information about regex groups, but what i want to do is: Filter out a string of all ARN's, extract the AWS Services from the ARN's, is it even possible in REGO?

What i currently have:

output = matches {
    string := "\"Resource\": \"arn:aws:states:::lambda:invoke\",\r\n \"Resource\": \"arn:aws:states:::lambda:invoke\",\r\n \"FunctionName\": \"arn:aws:lambda:eu-central-1:521439441813:function:lkfp-test-hello:$LATEST\"\r\n  xecution\"\r\n  \"Resource\": \"arn:aws:states:::aws-sdk:s3:createBucket\"\r\n    }\r\n  }\r\n}\r\n"
    matches := regex.find_n(`arn:([^:\n]*):([^:\n]*):([^:\n]*):([^:\n]*):(([^:\/\n]*)[:\/])?(?:[^"]|"")*"`, string, -1)
}

What it gives as a result:

{
    "output": [
        "arn:aws:states:::lambda:invoke\"",
        "arn:aws:states:::lambda:invoke\"",
        "arn:aws:lambda:eu-central-1:521439441813:function:lkfp-test-hello:$LATEST\"",
        "arn:aws:states:::aws-sdk:s3:createBucket\""
    ]
}

What do i actually expect:

{
    "output": [
        "states",
        "states",
        "lambda",
        "states"
    ]
}


Solution 1:[1]

apparently changing find_n to find_all_string_submatch_n separates groups.

Solution 2:[2]

The pattern ((?=arn:aws:(states|lambda))) finds what you want in the innermost capturing group. This demonstration is in Python because I don't know rego

import re
string = '"\"Resource\": \"arn:aws:states:::lambda:invoke\",\r\n \"Resource\": \"arn:aws:states:::lambda:invoke\",\r\n \"FunctionName\": \"arn:aws:lambda:eu-central-1:521439441813:function:lkfp-test-hello:$LATEST\"\r\n  xecution\"\r\n  \"Resource\": \"arn:aws:states:::aws-sdk:s3:createBucket\"\r\n    }\r\n  }\r\n}\r\n"'
matches=re.findall(r'((?=arn:aws:(states|lambda)))',string)
for m in matches:
    print(m[1])

output

states
states
lambda
states

Solution 3:[3]

I believe the ARN is constructed with the service in the same place every time. It may be easier to just split the string and grab that place in the array, then use comprehension to stick them all together.

https://www.openpolicyagent.org/docs/latest/policy-language/#array-comprehensions

output = services {
    string := "\"Resource\": \"arn:aws:states:::lambda:invoke\",\r\n \"Resource\": \"arn:aws:states:::lambda:invoke\",\r\n \"FunctionName\": \"arn:aws:lambda:eu-central-1:521439441813:function:lkfp-test-hello:$LATEST\"\r\n  xecution\"\r\n  \"Resource\": \"arn:aws:states:::aws-sdk:s3:createBucket\"\r\n    }\r\n  }\r\n}\r\n"
    matches := regex.find_n(`arn:([^:\n]*):([^:\n]*):([^:\n]*):([^:\n]*):(([^:\/\n]*)[:\/])?(?:[^"]|"")*"`, string, -1)
    services := [service | a := matches[_]
                           b := split(a, ":")
                           service := b[2]
                           ]
}

I've also added it to a playground here: https://play.openpolicyagent.org/p/LB17WoRDWT

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 A K
Solution 2
Solution 3 peteroneilljr