package iam import ( "testing" policyengine "git.frostfs.info/TrueCloudLab/policy-engine" "github.com/stretchr/testify/require" ) func TestConverters(t *testing.T) { t.Run("valid policy", func(t *testing.T) { p := Policy{ Version: "2012-10-17", Statement: []Statement{{ Principal: map[PrincipalType][]string{ AWSPrincipalType: {"arn:aws:iam::111122223333:user/JohnDoe"}, }, Effect: AllowEffect, Action: []string{"s3:PutObject"}, Resource: []string{"arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"}, Conditions: map[string]Condition{ CondStringEquals: { "s3:RequestObjectTag/Department": {"Finance"}, }, }, }}, } expected := &policyengine.Chain{Rules: []policyengine.Rule{ { Status: policyengine.Allow, Actions: policyengine.Actions{Names: p.Statement[0].Action}, Resources: policyengine.Resources{Names: p.Statement[0].Resource}, Any: true, Condition: []policyengine.Condition{ { Op: policyengine.CondStringEquals, Object: policyengine.ObjectRequest, Key: RequestOwnerProperty, Value: "arn:aws:iam::111122223333:user/JohnDoe", }, { Op: policyengine.CondStringEquals, Object: policyengine.ObjectRequest, Key: "s3:RequestObjectTag/Department", Value: "Finance", }, }, }, }} chain, err := p.ToChain() require.NoError(t, err) require.Equal(t, expected, chain) }) t.Run("valid inverted policy", func(t *testing.T) { p := Policy{ Version: "2012-10-17", Statement: []Statement{{ NotPrincipal: map[PrincipalType][]string{ AWSPrincipalType: {"arn:aws:iam::111122223333:user/JohnDoe"}, }, Effect: DenyEffect, NotAction: []string{"s3:PutObject"}, NotResource: []string{"arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"}, }}, } expected := &policyengine.Chain{Rules: []policyengine.Rule{ { Status: policyengine.AccessDenied, Actions: policyengine.Actions{Inverted: true, Names: p.Statement[0].NotAction}, Resources: policyengine.Resources{Inverted: true, Names: p.Statement[0].NotResource}, Any: true, Condition: []policyengine.Condition{ { Op: policyengine.CondStringNotEquals, Object: policyengine.ObjectRequest, Key: RequestOwnerProperty, Value: "arn:aws:iam::111122223333:user/JohnDoe", }, }, }, }} chain, err := p.ToChain() require.NoError(t, err) require.Equal(t, expected, chain) }) t.Run("invalid policy (unsupported principal type)", func(t *testing.T) { p := Policy{ Version: "2012-10-17", Statement: []Statement{{ Principal: map[PrincipalType][]string{ "dummy": {"arn:aws:iam::111122223333:user/JohnDoe"}, }, Effect: AllowEffect, Action: []string{"s3:PutObject"}, Resource: []string{"arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"}, }}, } _, err := p.ToChain() require.Error(t, err) }) t.Run("invalid policy (missing resource)", func(t *testing.T) { p := Policy{ Version: "2012-10-17", Statement: []Statement{{ Principal: map[PrincipalType][]string{ AWSPrincipalType: {"arn:aws:iam::111122223333:user/JohnDoe"}, }, Effect: AllowEffect, Action: []string{"s3:PutObject"}, }}, } _, err := p.ToChain() require.Error(t, err) }) t.Run("check policy conditions", func(t *testing.T) { p := Policy{ Version: "2012-10-17", Statement: []Statement{{ Principal: map[PrincipalType][]string{Wildcard: nil}, Effect: AllowEffect, Action: []string{"s3:PutObject"}, Resource: []string{"arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"}, Conditions: Conditions{ CondStringEquals: {"key1": {"val0", "val1"}}, CondStringNotEquals: {"key2": {"val2"}}, CondStringEqualsIgnoreCase: {"key3": {"val3"}}, CondStringNotEqualsIgnoreCase: {"key4": {"val4"}}, CondStringLike: {"key5": {"val5"}}, CondStringNotLike: {"key6": {"val6"}}, CondDateEquals: {"key7": {"2006-01-02T15:04:05+07:00"}}, CondDateNotEquals: {"key8": {"2006-01-02T15:04:05Z"}}, CondDateLessThan: {"key9": {"2006-01-02T15:04:05+06:00"}}, CondDateLessThanEquals: {"key10": {"2006-01-02T15:04:05+03:00"}}, CondDateGreaterThan: {"key11": {"2006-01-02T15:04:05-01:00"}}, CondDateGreaterThanEquals: {"key12": {"2006-01-02T15:04:05-03:00"}}, CondBool: {"key13": {"True"}}, CondIPAddress: {"key14": {"val14"}}, CondNotIPAddress: {"key15": {"val15"}}, CondArnEquals: {"key16": {"val16"}}, CondArnLike: {"key17": {"val17"}}, CondArnNotEquals: {"key18": {"val18"}}, CondArnNotLike: {"key19": {"val19"}}, }, }}, } expected := &policyengine.Chain{Rules: []policyengine.Rule{ { Status: policyengine.Allow, Actions: policyengine.Actions{Names: p.Statement[0].Action}, Resources: policyengine.Resources{Names: p.Statement[0].Resource}, Any: true, Condition: []policyengine.Condition{ { Op: policyengine.CondStringLike, Object: policyengine.ObjectRequest, Key: RequestOwnerProperty, Value: "*", }, { Op: policyengine.CondStringEquals, Object: policyengine.ObjectRequest, Key: "key1", Value: "val0", }, { Op: policyengine.CondStringEquals, Object: policyengine.ObjectRequest, Key: "key1", Value: "val1", }, { Op: policyengine.CondStringNotEquals, Object: policyengine.ObjectRequest, Key: "key2", Value: "val2", }, { Op: policyengine.CondStringEqualsIgnoreCase, Object: policyengine.ObjectRequest, Key: "key3", Value: "val3", }, { Op: policyengine.CondStringNotEqualsIgnoreCase, Object: policyengine.ObjectRequest, Key: "key4", Value: "val4", }, { Op: policyengine.CondStringLike, Object: policyengine.ObjectRequest, Key: "key5", Value: "val5", }, { Op: policyengine.CondStringNotLike, Object: policyengine.ObjectRequest, Key: "key6", Value: "val6", }, { Op: policyengine.CondStringEquals, Object: policyengine.ObjectRequest, Key: "key7", Value: "1136189045", }, { Op: policyengine.CondStringNotEquals, Object: policyengine.ObjectRequest, Key: "key8", Value: "1136214245", }, { Op: policyengine.CondStringLessThan, Object: policyengine.ObjectRequest, Key: "key9", Value: "1136192645", }, { Op: policyengine.CondStringLessThanEquals, Object: policyengine.ObjectRequest, Key: "key10", Value: "1136203445", }, { Op: policyengine.CondStringGreaterThan, Object: policyengine.ObjectRequest, Key: "key11", Value: "1136217845", }, { Op: policyengine.CondStringGreaterThanEquals, Object: policyengine.ObjectRequest, Key: "key12", Value: "1136225045", }, { Op: policyengine.CondStringEqualsIgnoreCase, Object: policyengine.ObjectRequest, Key: "key13", Value: "True", }, { Op: policyengine.CondStringLike, Object: policyengine.ObjectRequest, Key: "key14", Value: "val14", }, { Op: policyengine.CondStringNotLike, Object: policyengine.ObjectRequest, Key: "key15", Value: "val15", }, { Op: policyengine.CondStringEquals, Object: policyengine.ObjectRequest, Key: "key16", Value: "val16", }, { Op: policyengine.CondStringLike, Object: policyengine.ObjectRequest, Key: "key17", Value: "val17", }, { Op: policyengine.CondStringNotEquals, Object: policyengine.ObjectRequest, Key: "key18", Value: "val18", }, { Op: policyengine.CondStringNotLike, Object: policyengine.ObjectRequest, Key: "key19", Value: "val19", }, }, }, }} chain, err := p.ToChain() require.NoError(t, err) for i, rule := range chain.Rules { expectedRule := expected.Rules[i] require.Equal(t, expectedRule.Actions, rule.Actions) require.Equal(t, expectedRule.Any, rule.Any) require.Equal(t, expectedRule.Resources, rule.Resources) require.Equal(t, expectedRule.Status, rule.Status) require.ElementsMatch(t, expectedRule.Condition, rule.Condition) } }) }