[#46] iam: Support more s3 to native actions mapping

Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
This commit is contained in:
Denis Kirillov 2024-01-26 15:43:48 +03:00
parent af388779a3
commit 1cdb3e5a4a
2 changed files with 43 additions and 57 deletions

View file

@ -10,15 +10,17 @@ import (
const PropertyKeyFilePath = "FilePath" const PropertyKeyFilePath = "FilePath"
var actionToOpMap = map[string][]string{ var supportedActionToNativeOpMap = map[string][]string{
supportedS3ActionDeleteObject: {native.MethodDeleteObject}, supportedS3NativeActionDeleteObject: {native.MethodDeleteObject},
supportedS3ActionGetObject: {native.MethodGetObject, native.MethodHeadObject, native.MethodSearchObject, native.MethodRangeObject, native.MethodHashObject}, supportedS3NativeActionGetObject: {native.MethodGetObject, native.MethodHeadObject, native.MethodSearchObject, native.MethodRangeObject, native.MethodHashObject},
supportedS3ActionHeadObject: {native.MethodHeadObject, native.MethodSearchObject, native.MethodRangeObject, native.MethodHashObject}, supportedS3NativeActionPutObject: {native.MethodPutObject},
supportedS3ActionPutObject: {native.MethodPutObject}, supportedS3NativeActionListBucket: {native.MethodGetContainer, native.MethodGetObject, native.MethodHeadObject, native.MethodSearchObject, native.MethodRangeObject, native.MethodHashObject},
supportedS3ActionListBucket: {native.MethodGetContainer, native.MethodGetObject, native.MethodHeadObject, native.MethodSearchObject, native.MethodRangeObject, native.MethodHashObject},
supportedS3ActionCreateBucket: {native.MethodPutContainer}, supportedS3NativeActionCreateBucket: {native.MethodPutContainer},
supportedS3ActionDeleteBucket: {native.MethodDeleteContainer}, supportedS3NativeActionDeleteBucket: {native.MethodDeleteContainer},
supportedS3NativeActionListAllMyBucket: {native.MethodListContainers},
supportedS3NativeActionPutBucketACL: {native.MethodSetContainerEACL},
supportedS3NativeActionGetBucketACL: {native.MethodGetContainerEACL},
} }
var containerNativeOperations = map[string]struct{}{ var containerNativeOperations = map[string]struct{}{
@ -41,14 +43,16 @@ var objectNativeOperations = map[string]struct{}{
} }
const ( const (
supportedS3ActionDeleteObject = "s3:DeleteObject" supportedS3NativeActionDeleteObject = "s3:DeleteObject"
supportedS3ActionGetObject = "s3:GetObject" supportedS3NativeActionGetObject = "s3:GetObject"
supportedS3ActionHeadObject = "s3:HeadObject" supportedS3NativeActionPutObject = "s3:PutObject"
supportedS3ActionPutObject = "s3:PutObject" supportedS3NativeActionListBucket = "s3:ListBucket"
supportedS3ActionListBucket = "s3:ListBucket"
supportedS3ActionCreateBucket = "s3:CreateBucket" supportedS3NativeActionCreateBucket = "s3:CreateBucket"
supportedS3ActionDeleteBucket = "s3:DeleteBucket" supportedS3NativeActionDeleteBucket = "s3:DeleteBucket"
supportedS3NativeActionListAllMyBucket = "s3:ListAllMyBuckets"
supportedS3NativeActionPutBucketACL = "s3:PutBucketAcl"
supportedS3NativeActionGetBucketACL = "s3:GetBucketAcl"
) )
type NativeResolver interface { type NativeResolver interface {
@ -342,7 +346,7 @@ func formNativeActionNames(names []string) ([]string, error) {
return []string{Wildcard}, nil return []string{Wildcard}, nil
} }
res = append(res, actionToOpMap[action]...) res = append(res, supportedActionToNativeOpMap[action]...)
} }
return res, nil return res, nil

View file

@ -154,40 +154,6 @@ 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",
@ -222,7 +188,7 @@ func TestConverters(t *testing.T) {
require.Equal(t, expected, s3Chain) require.Equal(t, expected, s3Chain)
}) })
t.Run("valid policy map get action", func(t *testing.T) { t.Run("valid native policy map action", func(t *testing.T) {
p := Policy{ p := Policy{
Version: "2012-10-17", Version: "2012-10-17",
Statement: []Statement{{ Statement: []Statement{{
@ -230,16 +196,19 @@ func TestConverters(t *testing.T) {
AWSPrincipalType: {principal}, AWSPrincipalType: {principal},
}, },
Effect: DenyEffect, Effect: DenyEffect,
NotAction: []string{"s3:GetObject"}, Action: []string{"s3:DeleteObject", "s3:DeleteBucket"},
NotResource: []string{fmt.Sprintf(s3.ResourceFormatS3BucketObject, bktName, objName)}, Resource: []string{
fmt.Sprintf(s3.ResourceFormatS3BucketObject, bktName, objName),
fmt.Sprintf(s3.ResourceFormatS3Bucket, bktName),
},
}}, }},
} }
expected := &chain.Chain{Rules: []chain.Rule{ expected := &chain.Chain{Rules: []chain.Rule{
{ {
Status: chain.AccessDenied, Status: chain.AccessDenied,
Actions: chain.Actions{Inverted: true, Names: actionToOpMap["s3:GetObject"]}, Actions: chain.Actions{Names: []string{native.MethodDeleteObject, native.MethodDeleteContainer}},
Resources: chain.Resources{Inverted: true, Names: []string{ Resources: chain.Resources{Names: []string{
fmt.Sprintf(native.ResourceFormatNamespaceContainerObjects, namespace, mockResolver.containers[bktName]), fmt.Sprintf(native.ResourceFormatNamespaceContainerObjects, namespace, mockResolver.containers[bktName]),
}}, }},
Condition: []chain.Condition{ Condition: []chain.Condition{
@ -257,6 +226,19 @@ func TestConverters(t *testing.T) {
}, },
}, },
}, },
{
Status: chain.AccessDenied,
Actions: chain.Actions{Names: []string{native.MethodDeleteObject, native.MethodDeleteContainer}},
Resources: chain.Resources{Names: []string{
fmt.Sprintf(native.ResourceFormatNamespaceContainer, 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) nativeChain, err := ConvertToNativeChain(p, mockResolver)
@ -660,7 +642,7 @@ func TestComplexNativeConditions(t *testing.T) {
} }
expectedStatus := chain.AccessDenied expectedStatus := chain.AccessDenied
expectedActions := chain.Actions{Names: actionToOpMap["s3:"+action]} expectedActions := chain.Actions{Names: supportedActionToNativeOpMap["s3:"+action]}
expectedResource1 := chain.Resources{Names: []string{nativeResource1}} expectedResource1 := chain.Resources{Names: []string{nativeResource1}}
expectedResource23 := chain.Resources{Names: []string{nativeResource2, nativeResource3}} expectedResource23 := chain.Resources{Names: []string{nativeResource2, nativeResource3}}