Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
317 views
in Technique[技术] by (71.8m points)

go - Parsing ARN from IAM Policy using Regex

I have the following IAM Policy:

{"Version":"2012-10-17","Statement":[{"Sid":"","Effect":"Allow","Principal":{"AWS":"arn:aws:sts::<account>:assumed-role/custom_role/<role>"},"Action":"sts:AssumeRole","Condition":{"StringEquals":{"sts:ExternalId":"<account>"}}}]}

but the "AWS" portion can also be an array:

"AWS": [
      "arn:aws:sts::<account>:assumed-role/custom_role/<role_1>",
      "arn:aws:sts::<account>:assumed-role/custom_role/<role_2>"
]

What I need is a regex that can parse both structures and return the list of arn:aws:sts as a list of strings... how can I accomplish that using regex in Golang? I tried to use json.Unmarshal but the object structure is different between []string and string

Edit:

I have the following snippet:

re := regexp.MustCompile(`arn:aws:sts::[a-z0-9]*:assumed-role/custom_role/[a-z0-9]-*`)
result := re.FindAll([]byte(arn), 10)
for _, res := range result {
    fmt.Println(string(res))
}


>>> `arn:aws:sts::<account_id>:assumed-role/custom_role/`
question from:https://stackoverflow.com/questions/65854778/parsing-arn-from-iam-policy-using-regex

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Using JSON decoder

You can decode the AWS key directly into a custom type implementing the "json.Unmarshaler" interface and decode both inputs correctly.

Demo

type AWSRoles []string

func (r *AWSRoles) UnmarshalJSON(b []byte) error {
    var s string
    if err := json.Unmarshal(b, &s); err == nil {
        *r = append(*r, s)
        return nil
    }
    var ss []string
    if err := json.Unmarshal(b, &ss); err == nil {
        *r = ss
        return nil
    }
    return errors.New("cannot unmarshal neither to a string nor a slice of strings")
}

type AWSPolicy struct {
    Statement []struct {
        Principal struct {
            AWSRoles AWSRoles `json:"AWS"`
        } `json:"Principal"`
    } `json:"Statement"`
}

Here's a test for it

var testsAWSPolicyParsing = []struct {
    name      string
    input     []byte
    wantRoles []string
}{
    {
        name:      "unique role",
        input:     []byte(`{"Version":"2012-10-17","Statement":[{"Sid":"","Effect":"Allow","Principal":{"AWS":"arn:aws:sts::<account>:assumed-role/custom_role/<role>"},"Action":"sts:AssumeRole","Condition":{"StringEquals":{"sts:ExternalId":"<account>"}}}]}`),
        wantRoles: []string{"arn:aws:sts::<account>:assumed-role/custom_role/<role>"},
    },
    {
        name:  "multiple roles",
        input: []byte(`{"Version":"2012-10-17","Statement":[{"Sid":"","Effect":"Allow","Principal":{"AWS":["arn:aws:sts::<account>:assumed-role/custom_role/<role_1>","arn:aws:sts::<account>:assumed-role/custom_role/<role_2>"]},"Action":"sts:AssumeRole","Condition":{"StringEquals":{"sts:ExternalId":"<account>"}}}]}`),
        wantRoles: []string{
            "arn:aws:sts::<account>:assumed-role/custom_role/<role_1>",
            "arn:aws:sts::<account>:assumed-role/custom_role/<role_2>",
        },
    },
}

func TestParseAWSPolicy(t *testing.T) {
    for _, tc := range testsAWSPolicyParsing {
        t.Run(tc.name, func(t *testing.T) {
            t.Parallel()
            var p AWSPolicy
            err := json.Unmarshal(tc.input, &p)
            if err != nil {
                t.Fatal("unexpected error parsing AWSRoles policy", err)
            }
            if l := len(p.Statement); l != 1 {
                t.Fatalf("unexpected Statement length. want 1, got %d", l)
            }
            if got := p.Statement[0].Principal.AWSRoles; !reflect.DeepEqual(got, tc.wantRoles) {
                t.Fatalf("roles are not the same, got %v, want %v", got, tc.wantRoles)
            }
        })
    }
}

Using a Regex

If you still want to use a regex, this one would parse it as long as:

  • AWS account has only numbers [0-9]
  • the custom role name has only alphanumeric characters and underscores

var awsRolesRegex = regexp.MustCompile("arn:aws:sts::[a-z0-9]+:assumed-role/custom_role/[a-zA-Z0-9_]+")

Demo


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...