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

311 Views Asked by At

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"
    ]
}
3

There are 3 best solutions below

1
On

apparently changing find_n to find_all_string_submatch_n separates groups.

0
On

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

0
On

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