[#46] iam: Shrink rules for wildcard cases

Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
This commit is contained in:
Denis Kirillov 2024-01-26 12:54:39 +03:00
parent 8cc5173d73
commit af388779a3
3 changed files with 81 additions and 19 deletions

View file

@ -101,7 +101,12 @@ func ConvertToNativeChain(p Policy, resolver NativeResolver) (*chain.Chain, erro
for _, groupedResource := range groupedResources { for _, groupedResource := range groupedResources {
for _, principal := range principals { for _, principal := range principals {
for _, conditions := range splitConditions { 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{ r := chain.Rule{
Status: status, Status: status,
@ -220,13 +225,7 @@ func formNativeResourceNamesAndConditions(names []string, resolver NativeResolve
if resource == Wildcard { if resource == Wildcard {
res = res[:0] res = res[:0]
if actionTypes.Object { return append(res, formWildcardNativeResource(actionTypes)), nil
res = append(res, GroupedResources{Names: []string{native.ResourceFormatAllObjects}})
}
if actionTypes.Container {
res = append(res, GroupedResources{Names: []string{native.ResourceFormatAllContainers}})
}
return res, nil
} }
if !strings.HasPrefix(resource, s3ResourcePrefix) { if !strings.HasPrefix(resource, s3ResourcePrefix) {
@ -237,13 +236,7 @@ func formNativeResourceNamesAndConditions(names []string, resolver NativeResolve
s3Resource := strings.TrimPrefix(resource, s3ResourcePrefix) s3Resource := strings.TrimPrefix(resource, s3ResourcePrefix)
if s3Resource == Wildcard { if s3Resource == Wildcard {
res = res[:0] res = res[:0]
if actionTypes.Object { return append(res, formWildcardNativeResource(actionTypes)), nil
res = append(res, GroupedResources{Names: []string{native.ResourceFormatAllObjects}})
}
if actionTypes.Container {
res = append(res, GroupedResources{Names: []string{native.ResourceFormatAllContainers}})
}
return res, nil
} }
if sepIndex := strings.Index(s3Resource, "/"); sepIndex < 0 { if sepIndex := strings.Index(s3Resource, "/"); sepIndex < 0 {
@ -290,6 +283,18 @@ func formNativeResourceNamesAndConditions(names []string, resolver NativeResolve
return res, nil 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) { func formNativePrincipal(principal []string, resolver NativeResolver) ([]string, error) {
res := make([]string, len(principal)) res := make([]string, len(principal))

View file

@ -49,11 +49,16 @@ func ConvertToS3Chain(p Policy, resolver S3Resolver) (*chain.Chain, error) {
for _, principal := range principals { for _, principal := range principals {
for _, conditions := range splitConditions { for _, conditions := range splitConditions {
var principalCondition []chain.Condition
if principal != Wildcard {
principalCondition = []chain.Condition{principalCondFn(principal)}
}
r := chain.Rule{ r := chain.Rule{
Status: status, Status: status,
Actions: ruleAction, Actions: ruleAction,
Resources: ruleResource, Resources: ruleResource,
Condition: append([]chain.Condition{principalCondFn(principal)}, conditions...), Condition: append(principalCondition, conditions...),
} }
engineChain.Rules = append(engineChain.Rules, r) engineChain.Rules = append(engineChain.Rules, r)
} }

View file

@ -154,6 +154,40 @@ func TestConverters(t *testing.T) {
require.Equal(t, expected, nativeChain) 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) { t.Run("valid inverted policy", func(t *testing.T) {
p := Policy{ p := Policy{
Version: "2012-10-17", Version: "2012-10-17",
@ -1190,11 +1224,29 @@ func TestWildcardConverters(t *testing.T) {
err := json.Unmarshal([]byte(policy), &p) err := json.Unmarshal([]byte(policy), &p)
require.NoError(t, err) require.NoError(t, err)
_, err = ConvertToS3Chain(p, newMockUserResolver(nil, nil, "")) s3Expected := &chain.Chain{
require.NoError(t, err) 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.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) { func TestActionParsing(t *testing.T) {