From af388779a37d2a874a8e2f79451a9d1988c58a6b Mon Sep 17 00:00:00 2001 From: Denis Kirillov Date: Fri, 26 Jan 2024 12:54:39 +0300 Subject: [PATCH] [#46] iam: Shrink rules for wildcard cases Signed-off-by: Denis Kirillov --- iam/converter_native.go | 35 ++++++++++++++----------- iam/converter_s3.go | 7 ++++- iam/converter_test.go | 58 ++++++++++++++++++++++++++++++++++++++--- 3 files changed, 81 insertions(+), 19 deletions(-) diff --git a/iam/converter_native.go b/iam/converter_native.go index a28d443..74c2822 100644 --- a/iam/converter_native.go +++ b/iam/converter_native.go @@ -101,7 +101,12 @@ func ConvertToNativeChain(p Policy, resolver NativeResolver) (*chain.Chain, erro for _, groupedResource := range groupedResources { for _, principal := range principals { for _, conditions := range splitConditions { - ruleConditions := append([]chain.Condition{principalCondFn(principal)}, groupedResource.Conditions...) + var principalCondition []chain.Condition + if principal != Wildcard { + principalCondition = []chain.Condition{principalCondFn(principal)} + } + + ruleConditions := append(principalCondition, groupedResource.Conditions...) r := chain.Rule{ Status: status, @@ -220,13 +225,7 @@ func formNativeResourceNamesAndConditions(names []string, resolver NativeResolve if resource == Wildcard { res = res[:0] - if actionTypes.Object { - res = append(res, GroupedResources{Names: []string{native.ResourceFormatAllObjects}}) - } - if actionTypes.Container { - res = append(res, GroupedResources{Names: []string{native.ResourceFormatAllContainers}}) - } - return res, nil + return append(res, formWildcardNativeResource(actionTypes)), nil } if !strings.HasPrefix(resource, s3ResourcePrefix) { @@ -237,13 +236,7 @@ func formNativeResourceNamesAndConditions(names []string, resolver NativeResolve s3Resource := strings.TrimPrefix(resource, s3ResourcePrefix) if s3Resource == Wildcard { res = res[:0] - if actionTypes.Object { - res = append(res, GroupedResources{Names: []string{native.ResourceFormatAllObjects}}) - } - if actionTypes.Container { - res = append(res, GroupedResources{Names: []string{native.ResourceFormatAllContainers}}) - } - return res, nil + return append(res, formWildcardNativeResource(actionTypes)), nil } if sepIndex := strings.Index(s3Resource, "/"); sepIndex < 0 { @@ -290,6 +283,18 @@ func formNativeResourceNamesAndConditions(names []string, resolver NativeResolve return res, nil } +func formWildcardNativeResource(actionTypes ActionTypes) GroupedResources { + groupedNames := make([]string, 0, 2) + if actionTypes.Object { + groupedNames = append(groupedNames, native.ResourceFormatAllObjects) + } + if actionTypes.Container { + groupedNames = append(groupedNames, native.ResourceFormatAllContainers) + } + + return GroupedResources{Names: groupedNames} +} + func formNativePrincipal(principal []string, resolver NativeResolver) ([]string, error) { res := make([]string, len(principal)) diff --git a/iam/converter_s3.go b/iam/converter_s3.go index 5af957a..f4ef7eb 100644 --- a/iam/converter_s3.go +++ b/iam/converter_s3.go @@ -49,11 +49,16 @@ func ConvertToS3Chain(p Policy, resolver S3Resolver) (*chain.Chain, error) { for _, principal := range principals { for _, conditions := range splitConditions { + var principalCondition []chain.Condition + if principal != Wildcard { + principalCondition = []chain.Condition{principalCondFn(principal)} + } + r := chain.Rule{ Status: status, Actions: ruleAction, Resources: ruleResource, - Condition: append([]chain.Condition{principalCondFn(principal)}, conditions...), + Condition: append(principalCondition, conditions...), } engineChain.Rules = append(engineChain.Rules, r) } diff --git a/iam/converter_test.go b/iam/converter_test.go index 0bf917c..e02109e 100644 --- a/iam/converter_test.go +++ b/iam/converter_test.go @@ -154,6 +154,40 @@ func TestConverters(t *testing.T) { require.Equal(t, expected, nativeChain) }) + t.Run("valid native policy with container resources", func(t *testing.T) { + p := Policy{ + Version: "2012-10-17", + Statement: []Statement{{ + Principal: map[PrincipalType][]string{ + AWSPrincipalType: {principal}, + }, + Effect: AllowEffect, + Action: []string{"s3:PutObject"}, + Resource: []string{resource}, + }}, + } + + expected := &chain.Chain{Rules: []chain.Rule{ + { + Status: chain.Allow, + Actions: chain.Actions{Names: []string{native.MethodPutObject}}, + Resources: chain.Resources{Names: []string{fmt.Sprintf(native.ResourceFormatNamespaceContainerObjects, namespace, mockResolver.containers[bktName])}}, + Condition: []chain.Condition{ + { + Op: chain.CondStringEquals, + Object: chain.ObjectRequest, + Key: native.PropertyKeyActorPublicKey, + Value: mockResolver.users[user], + }, + }, + }, + }} + + nativeChain, err := ConvertToNativeChain(p, mockResolver) + require.NoError(t, err) + require.Equal(t, expected, nativeChain) + }) + t.Run("valid inverted policy", func(t *testing.T) { p := Policy{ Version: "2012-10-17", @@ -1190,11 +1224,29 @@ func TestWildcardConverters(t *testing.T) { err := json.Unmarshal([]byte(policy), &p) require.NoError(t, err) - _, err = ConvertToS3Chain(p, newMockUserResolver(nil, nil, "")) - require.NoError(t, err) + s3Expected := &chain.Chain{ + Rules: []chain.Rule{{ + Status: chain.Allow, + Actions: chain.Actions{Names: []string{Wildcard}}, + Resources: chain.Resources{Names: []string{Wildcard}}, + }}, + } - _, err = ConvertToNativeChain(p, newMockUserResolver(nil, nil, "")) + s3Chain, err := ConvertToS3Chain(p, newMockUserResolver(nil, nil, "")) require.NoError(t, err) + require.Equal(t, s3Expected, s3Chain) + + nativeExpected := &chain.Chain{ + Rules: []chain.Rule{{ + Status: chain.Allow, + Actions: chain.Actions{Names: []string{Wildcard}}, + Resources: chain.Resources{Names: []string{native.ResourceFormatAllObjects, native.ResourceFormatAllContainers}}, + }}, + } + + nativeChain, err := ConvertToNativeChain(p, newMockUserResolver(nil, nil, "")) + require.NoError(t, err) + require.Equal(t, nativeExpected, nativeChain) } func TestActionParsing(t *testing.T) {