forked from TrueCloudLab/frostfs-s3-gw
[#680] Drop GetContainer operation from policy converter
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
This commit is contained in:
parent
4d305d0d0f
commit
526ddc1243
2 changed files with 103 additions and 101 deletions
|
@ -1,7 +1,6 @@
|
||||||
package iam
|
package iam
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -13,62 +12,62 @@ import (
|
||||||
const PropertyKeyFilePath = "FilePath"
|
const PropertyKeyFilePath = "FilePath"
|
||||||
|
|
||||||
type nativeOperationInfo struct {
|
type nativeOperationInfo struct {
|
||||||
operations []string
|
operations []string
|
||||||
needTreeWrite bool
|
treeOperations []string
|
||||||
}
|
}
|
||||||
|
|
||||||
var actionToNativeOpMap = map[string]nativeOperationInfo{
|
var actionToNativeOpMap = map[string]nativeOperationInfo{
|
||||||
s3common.S3ActionAbortMultipartUpload: {operations: []string{native.MethodGetContainer, native.MethodDeleteObject, native.MethodHeadObject, native.MethodGetObject, native.MethodPutObject}, needTreeWrite: true},
|
s3common.S3ActionAbortMultipartUpload: {treeOperations: []string{native.MethodGetObject, native.MethodPutObject}, operations: []string{native.MethodDeleteObject, native.MethodHeadObject, native.MethodGetObject, native.MethodPutObject}},
|
||||||
s3common.S3ActionCreateBucket: {operations: []string{native.MethodGetContainer, native.MethodPutContainer, native.MethodSetContainerEACL}, needTreeWrite: true},
|
s3common.S3ActionCreateBucket: {treeOperations: []string{native.MethodGetObject, native.MethodPutObject}, operations: []string{native.MethodPutContainer, native.MethodSetContainerEACL}},
|
||||||
s3common.S3ActionDeleteBucket: {operations: []string{native.MethodGetContainer, native.MethodDeleteContainer, native.MethodSearchObject, native.MethodHeadObject, native.MethodGetObject, native.MethodPutObject}, needTreeWrite: true},
|
s3common.S3ActionDeleteBucket: {treeOperations: []string{native.MethodGetObject, native.MethodPutObject}, operations: []string{native.MethodDeleteContainer, native.MethodSearchObject, native.MethodHeadObject, native.MethodGetObject, native.MethodPutObject}},
|
||||||
s3common.S3ActionDeleteBucketPolicy: {operations: []string{native.MethodGetContainer}},
|
s3common.S3ActionDeleteBucketPolicy: {treeOperations: []string{native.MethodGetObject}},
|
||||||
s3common.S3ActionDeleteObject: {operations: []string{native.MethodGetContainer, native.MethodDeleteObject, native.MethodPutObject, native.MethodHeadObject, native.MethodGetObject, native.MethodRangeObject}, needTreeWrite: true},
|
s3common.S3ActionDeleteObject: {treeOperations: []string{native.MethodGetObject, native.MethodPutObject}, operations: []string{native.MethodDeleteObject, native.MethodPutObject, native.MethodHeadObject, native.MethodGetObject, native.MethodRangeObject}},
|
||||||
s3common.S3ActionDeleteObjectTagging: {operations: []string{native.MethodGetContainer}, needTreeWrite: true},
|
s3common.S3ActionDeleteObjectTagging: {treeOperations: []string{native.MethodGetObject, native.MethodPutObject}},
|
||||||
s3common.S3ActionDeleteObjectVersion: {operations: []string{native.MethodGetContainer, native.MethodDeleteObject, native.MethodPutObject, native.MethodHeadObject, native.MethodGetObject, native.MethodRangeObject}, needTreeWrite: true},
|
s3common.S3ActionDeleteObjectVersion: {treeOperations: []string{native.MethodGetObject, native.MethodPutObject}, operations: []string{native.MethodDeleteObject, native.MethodPutObject, native.MethodHeadObject, native.MethodGetObject, native.MethodRangeObject}},
|
||||||
s3common.S3ActionDeleteObjectVersionTagging: {operations: []string{native.MethodGetContainer}, needTreeWrite: true},
|
s3common.S3ActionDeleteObjectVersionTagging: {treeOperations: []string{native.MethodGetObject, native.MethodPutObject}},
|
||||||
s3common.S3ActionGetBucketACL: {operations: []string{native.MethodGetContainer}},
|
s3common.S3ActionGetBucketACL: {treeOperations: []string{native.MethodGetObject}},
|
||||||
s3common.S3ActionGetBucketCORS: {operations: []string{native.MethodGetContainer, native.MethodGetObject, native.MethodHeadObject}},
|
s3common.S3ActionGetBucketCORS: {treeOperations: []string{native.MethodGetObject}, operations: []string{native.MethodGetObject, native.MethodHeadObject}},
|
||||||
s3common.S3ActionGetBucketLocation: {operations: []string{native.MethodGetContainer}},
|
s3common.S3ActionGetBucketLocation: {treeOperations: []string{native.MethodGetObject}},
|
||||||
s3common.S3ActionGetBucketNotification: {operations: []string{native.MethodGetContainer, native.MethodGetObject, native.MethodHeadObject}}, // not supported
|
s3common.S3ActionGetBucketNotification: {treeOperations: []string{native.MethodGetObject}, operations: []string{native.MethodGetObject, native.MethodHeadObject}}, // not supported
|
||||||
s3common.S3ActionGetBucketObjectLockConfiguration: {operations: []string{native.MethodGetContainer}},
|
s3common.S3ActionGetBucketObjectLockConfiguration: {treeOperations: []string{native.MethodGetObject}},
|
||||||
s3common.S3ActionGetBucketPolicy: {operations: []string{native.MethodGetContainer}},
|
s3common.S3ActionGetBucketPolicy: {treeOperations: []string{native.MethodGetObject}},
|
||||||
s3common.S3ActionGetBucketPolicyStatus: {operations: []string{native.MethodGetContainer}},
|
s3common.S3ActionGetBucketPolicyStatus: {treeOperations: []string{native.MethodGetObject}},
|
||||||
s3common.S3ActionGetBucketTagging: {operations: []string{native.MethodGetContainer}},
|
s3common.S3ActionGetBucketTagging: {treeOperations: []string{native.MethodGetObject}},
|
||||||
s3common.S3ActionGetBucketVersioning: {operations: []string{native.MethodGetContainer}},
|
s3common.S3ActionGetBucketVersioning: {treeOperations: []string{native.MethodGetObject}},
|
||||||
s3common.S3ActionGetLifecycleConfiguration: {operations: []string{native.MethodGetContainer, native.MethodGetObject, native.MethodHeadObject}},
|
s3common.S3ActionGetLifecycleConfiguration: {treeOperations: []string{native.MethodGetObject}, operations: []string{native.MethodGetObject, native.MethodHeadObject}},
|
||||||
s3common.S3ActionGetObject: {operations: []string{native.MethodGetContainer, native.MethodGetObject, native.MethodHeadObject, native.MethodSearchObject, native.MethodRangeObject, native.MethodHashObject}},
|
s3common.S3ActionGetObject: {treeOperations: []string{native.MethodGetObject}, operations: []string{native.MethodGetObject, native.MethodHeadObject, native.MethodSearchObject, native.MethodRangeObject, native.MethodHashObject}},
|
||||||
s3common.S3ActionGetObjectACL: {operations: []string{native.MethodGetContainer}},
|
s3common.S3ActionGetObjectACL: {treeOperations: []string{native.MethodGetObject}},
|
||||||
s3common.S3ActionGetObjectAttributes: {operations: []string{native.MethodGetContainer, native.MethodHeadObject}},
|
s3common.S3ActionGetObjectAttributes: {treeOperations: []string{native.MethodGetObject}, operations: []string{native.MethodHeadObject}},
|
||||||
s3common.S3ActionGetObjectLegalHold: {operations: []string{native.MethodGetContainer}},
|
s3common.S3ActionGetObjectLegalHold: {treeOperations: []string{native.MethodGetObject}},
|
||||||
s3common.S3ActionGetObjectRetention: {operations: []string{native.MethodGetContainer}},
|
s3common.S3ActionGetObjectRetention: {treeOperations: []string{native.MethodGetObject}},
|
||||||
s3common.S3ActionGetObjectTagging: {operations: []string{native.MethodGetContainer}},
|
s3common.S3ActionGetObjectTagging: {treeOperations: []string{native.MethodGetObject}},
|
||||||
s3common.S3ActionGetObjectVersion: {operations: []string{native.MethodGetContainer, native.MethodGetObject, native.MethodHeadObject, native.MethodSearchObject, native.MethodRangeObject, native.MethodHashObject}},
|
s3common.S3ActionGetObjectVersion: {treeOperations: []string{native.MethodGetObject}, operations: []string{native.MethodGetObject, native.MethodHeadObject, native.MethodSearchObject, native.MethodRangeObject, native.MethodHashObject}},
|
||||||
s3common.S3ActionGetObjectVersionACL: {operations: []string{native.MethodGetContainer}},
|
s3common.S3ActionGetObjectVersionACL: {treeOperations: []string{native.MethodGetObject}},
|
||||||
s3common.S3ActionGetObjectVersionAttributes: {operations: []string{native.MethodGetContainer, native.MethodHeadObject}},
|
s3common.S3ActionGetObjectVersionAttributes: {treeOperations: []string{native.MethodGetObject}, operations: []string{native.MethodHeadObject}},
|
||||||
s3common.S3ActionGetObjectVersionTagging: {operations: []string{native.MethodGetContainer}},
|
s3common.S3ActionGetObjectVersionTagging: {treeOperations: []string{native.MethodGetObject}},
|
||||||
s3common.S3ActionListAllMyBuckets: {operations: []string{native.MethodListContainers, native.MethodGetContainer}},
|
s3common.S3ActionListAllMyBuckets: {treeOperations: []string{native.MethodGetObject}, operations: []string{native.MethodListContainers}},
|
||||||
s3common.S3ActionListBucket: {operations: []string{native.MethodGetContainer, native.MethodGetObject, native.MethodHeadObject, native.MethodSearchObject, native.MethodRangeObject, native.MethodHashObject}},
|
s3common.S3ActionListBucket: {treeOperations: []string{native.MethodGetObject}, operations: []string{native.MethodGetObject, native.MethodHeadObject, native.MethodSearchObject, native.MethodRangeObject, native.MethodHashObject}},
|
||||||
s3common.S3ActionListBucketMultipartUploads: {operations: []string{native.MethodGetContainer}},
|
s3common.S3ActionListBucketMultipartUploads: {treeOperations: []string{native.MethodGetObject}},
|
||||||
s3common.S3ActionListBucketVersions: {operations: []string{native.MethodGetContainer, native.MethodGetObject, native.MethodHeadObject, native.MethodSearchObject, native.MethodRangeObject, native.MethodHashObject}},
|
s3common.S3ActionListBucketVersions: {treeOperations: []string{native.MethodGetObject}, operations: []string{native.MethodGetObject, native.MethodHeadObject, native.MethodSearchObject, native.MethodRangeObject, native.MethodHashObject}},
|
||||||
s3common.S3ActionListMultipartUploadParts: {operations: []string{native.MethodGetContainer}},
|
s3common.S3ActionListMultipartUploadParts: {treeOperations: []string{native.MethodGetObject}},
|
||||||
s3common.S3ActionPutBucketACL: {operations: []string{native.MethodGetContainer}, needTreeWrite: true},
|
s3common.S3ActionPutBucketACL: {treeOperations: []string{native.MethodGetObject, native.MethodPutObject}},
|
||||||
s3common.S3ActionPutBucketCORS: {operations: []string{native.MethodGetContainer, native.MethodGetObject, native.MethodPutObject}, needTreeWrite: true},
|
s3common.S3ActionPutBucketCORS: {treeOperations: []string{native.MethodGetObject, native.MethodPutObject}, operations: []string{native.MethodGetObject, native.MethodPutObject}},
|
||||||
s3common.S3ActionPutBucketNotification: {operations: []string{native.MethodGetContainer, native.MethodHeadObject, native.MethodDeleteObject, native.MethodGetObject, native.MethodPutObject}, needTreeWrite: true}, // not supported
|
s3common.S3ActionPutBucketNotification: {treeOperations: []string{native.MethodGetObject, native.MethodPutObject}, operations: []string{native.MethodHeadObject, native.MethodDeleteObject, native.MethodGetObject, native.MethodPutObject}}, // not supported
|
||||||
s3common.S3ActionPutBucketObjectLockConfiguration: {operations: []string{native.MethodGetContainer}, needTreeWrite: true},
|
s3common.S3ActionPutBucketObjectLockConfiguration: {treeOperations: []string{native.MethodGetObject, native.MethodPutObject}},
|
||||||
s3common.S3ActionPutBucketPolicy: {operations: []string{native.MethodGetContainer}},
|
s3common.S3ActionPutBucketPolicy: {treeOperations: []string{native.MethodGetObject}},
|
||||||
s3common.S3ActionPutBucketTagging: {operations: []string{native.MethodGetContainer}, needTreeWrite: true},
|
s3common.S3ActionPutBucketTagging: {treeOperations: []string{native.MethodGetObject, native.MethodPutObject}},
|
||||||
s3common.S3ActionPutBucketVersioning: {operations: []string{native.MethodGetContainer}, needTreeWrite: true},
|
s3common.S3ActionPutBucketVersioning: {treeOperations: []string{native.MethodGetObject, native.MethodPutObject}},
|
||||||
s3common.S3ActionPutLifecycleConfiguration: {operations: []string{native.MethodGetContainer, native.MethodGetObject, native.MethodHeadObject, native.MethodPutObject, native.MethodDeleteObject}, needTreeWrite: true},
|
s3common.S3ActionPutLifecycleConfiguration: {treeOperations: []string{native.MethodGetObject, native.MethodPutObject}, operations: []string{native.MethodGetObject, native.MethodHeadObject, native.MethodPutObject, native.MethodDeleteObject}},
|
||||||
s3common.S3ActionPutObject: {operations: []string{native.MethodGetContainer, native.MethodPutObject, native.MethodGetObject, native.MethodHeadObject, native.MethodRangeObject}, needTreeWrite: true},
|
s3common.S3ActionPutObject: {treeOperations: []string{native.MethodGetObject, native.MethodPutObject}, operations: []string{native.MethodPutObject, native.MethodGetObject, native.MethodHeadObject, native.MethodRangeObject}},
|
||||||
s3common.S3ActionPutObjectACL: {operations: []string{native.MethodGetContainer}}, // not supported
|
s3common.S3ActionPutObjectACL: {}, // not supported
|
||||||
s3common.S3ActionPutObjectLegalHold: {operations: []string{native.MethodGetContainer, native.MethodHeadObject, native.MethodGetObject, native.MethodPutObject}, needTreeWrite: true},
|
s3common.S3ActionPutObjectLegalHold: {treeOperations: []string{native.MethodGetObject, native.MethodPutObject}, operations: []string{native.MethodHeadObject, native.MethodGetObject, native.MethodPutObject}},
|
||||||
s3common.S3ActionPutObjectRetention: {operations: []string{native.MethodGetContainer, native.MethodHeadObject, native.MethodGetObject, native.MethodPutObject}, needTreeWrite: true},
|
s3common.S3ActionPutObjectRetention: {treeOperations: []string{native.MethodGetObject, native.MethodPutObject}, operations: []string{native.MethodHeadObject, native.MethodGetObject, native.MethodPutObject}},
|
||||||
s3common.S3ActionPutObjectTagging: {operations: []string{native.MethodGetContainer}, needTreeWrite: true},
|
s3common.S3ActionPutObjectTagging: {treeOperations: []string{native.MethodGetObject, native.MethodPutObject}},
|
||||||
s3common.S3ActionPutObjectVersionACL: {operations: []string{native.MethodGetContainer}}, // not supported
|
s3common.S3ActionPutObjectVersionACL: {}, // not supported
|
||||||
s3common.S3ActionPutObjectVersionTagging: {operations: []string{native.MethodGetContainer}, needTreeWrite: true},
|
s3common.S3ActionPutObjectVersionTagging: {treeOperations: []string{native.MethodGetObject, native.MethodPutObject}},
|
||||||
s3common.S3ActionPatchObject: {operations: []string{native.MethodGetContainer, native.MethodGetObject, native.MethodHeadObject, native.MethodPatchObject, native.MethodPutObject, native.MethodRangeObject}, needTreeWrite: true},
|
s3common.S3ActionPatchObject: {treeOperations: []string{native.MethodGetObject, native.MethodPutObject}, operations: []string{native.MethodGetObject, native.MethodHeadObject, native.MethodPatchObject, native.MethodPutObject, native.MethodRangeObject}},
|
||||||
s3common.S3ActionPutBucketPublicAccessBlock: {operations: []string{native.MethodGetContainer}, needTreeWrite: true},
|
s3common.S3ActionPutBucketPublicAccessBlock: {treeOperations: []string{native.MethodGetObject, native.MethodPutObject}},
|
||||||
s3common.S3ActionGetBucketPublicAccessBlock: {operations: []string{native.MethodGetContainer}},
|
s3common.S3ActionGetBucketPublicAccessBlock: {treeOperations: []string{native.MethodGetObject}},
|
||||||
}
|
}
|
||||||
|
|
||||||
var containerNativeOperations = map[string]struct{}{
|
var containerNativeOperations = map[string]struct{}{
|
||||||
|
@ -90,7 +89,7 @@ var objectNativeOperations = map[string]struct{}{
|
||||||
native.MethodHashObject: {},
|
native.MethodHashObject: {},
|
||||||
}
|
}
|
||||||
|
|
||||||
var errConditionKeyNotApplicable = errors.New("condition key is not applicable")
|
var treeNativeOperations = []string{native.MethodGetObject, native.MethodPutObject}
|
||||||
|
|
||||||
func ConvertToNativeChain(p s3common.Policy, resolver s3common.NativeResolver) (*chain.Chain, error) {
|
func ConvertToNativeChain(p s3common.Policy, resolver s3common.NativeResolver) (*chain.Chain, error) {
|
||||||
if err := p.Validate(s3common.ResourceBasedPolicyType); err != nil {
|
if err := p.Validate(s3common.ResourceBasedPolicyType); err != nil {
|
||||||
|
@ -109,37 +108,37 @@ func ConvertToNativeChain(p s3common.Policy, resolver s3common.NativeResolver) (
|
||||||
}
|
}
|
||||||
|
|
||||||
action, actionInverted := statement.GetAction()
|
action, actionInverted := statement.GetAction()
|
||||||
nativeActions, treeWrite, err := formNativeActionNames(action)
|
nativeActions, nativeTreeActions, err := formNativeActionNames(action)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ruleAction := chain.Actions{Inverted: actionInverted, Names: nativeActions}
|
|
||||||
if len(ruleAction.Names) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
resource, resourceInverted := statement.GetResource()
|
resource, resourceInverted := statement.GetResource()
|
||||||
groupedResources, treeRes, err := formNativeResourceNamesAndConditions(resource, resolver, getActionTypes(nativeActions))
|
groupedResources, treeRes, err := formNativeResourceNamesAndConditions(resource, resolver, getActionTypes(nativeActions, nativeTreeActions))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
groupedConditions, err := convertToNativeChainCondition(statement.Conditions, resolver)
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, errConditionKeyNotApplicable) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
splitConditions := s3common.SplitGroupedConditions(groupedConditions)
|
|
||||||
|
|
||||||
principals, principalCondFn, err := getNativePrincipalsAndConditionFunc(statement, resolver)
|
principals, principalCondFn, err := getNativePrincipalsAndConditionFunc(statement, resolver)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
engineChain.Rules = append(engineChain.Rules, getTreeRule(treeRes, principals, principalCondFn, treeWrite)...)
|
if len(treeRes) != 0 {
|
||||||
|
engineChain.Rules = append(engineChain.Rules, getTreeRule(treeRes, principals, principalCondFn, nativeTreeActions)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(groupedResources) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
groupedConditions, err := convertToNativeChainCondition(statement.Conditions, resolver)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
splitConditions := s3common.SplitGroupedConditions(groupedConditions)
|
||||||
|
|
||||||
|
ruleAction := chain.Actions{Inverted: actionInverted, Names: nativeActions}
|
||||||
for _, groupedResource := range groupedResources {
|
for _, groupedResource := range groupedResources {
|
||||||
for _, principal := range principals {
|
for _, principal := range principals {
|
||||||
for _, conditions := range splitConditions {
|
for _, conditions := range splitConditions {
|
||||||
|
@ -172,12 +171,7 @@ func ConvertToNativeChain(p s3common.Policy, resolver s3common.NativeResolver) (
|
||||||
return &engineChain, nil
|
return &engineChain, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTreeRule(resources []string, principals []string, principalCondFn s3common.FormPrincipalConditionFunc, needWrite bool) []chain.Rule {
|
func getTreeRule(resources []string, principals []string, principalCondFn s3common.FormPrincipalConditionFunc, treeActions []string) []chain.Rule {
|
||||||
ops := []string{native.MethodGetObject}
|
|
||||||
if needWrite {
|
|
||||||
ops = append(ops, native.MethodPutObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
treeCondition := chain.Condition{
|
treeCondition := chain.Condition{
|
||||||
Op: chain.CondStringNotEquals,
|
Op: chain.CondStringNotEquals,
|
||||||
Kind: chain.KindResource,
|
Kind: chain.KindResource,
|
||||||
|
@ -197,7 +191,7 @@ func getTreeRule(resources []string, principals []string, principalCondFn s3comm
|
||||||
if len(principalTreeConditions) == 0 {
|
if len(principalTreeConditions) == 0 {
|
||||||
return []chain.Rule{{
|
return []chain.Rule{{
|
||||||
Status: chain.Allow,
|
Status: chain.Allow,
|
||||||
Actions: chain.Actions{Names: ops},
|
Actions: chain.Actions{Names: treeActions},
|
||||||
Resources: chain.Resources{Names: resources},
|
Resources: chain.Resources{Names: resources},
|
||||||
Condition: []chain.Condition{treeCondition},
|
Condition: []chain.Condition{treeCondition},
|
||||||
}}
|
}}
|
||||||
|
@ -207,7 +201,7 @@ func getTreeRule(resources []string, principals []string, principalCondFn s3comm
|
||||||
for i, condition := range principalTreeConditions {
|
for i, condition := range principalTreeConditions {
|
||||||
res[i] = chain.Rule{
|
res[i] = chain.Rule{
|
||||||
Status: chain.Allow,
|
Status: chain.Allow,
|
||||||
Actions: chain.Actions{Names: ops},
|
Actions: chain.Actions{Names: treeActions},
|
||||||
Resources: chain.Resources{Names: resources},
|
Resources: chain.Resources{Names: resources},
|
||||||
Condition: []chain.Condition{treeCondition, condition},
|
Condition: []chain.Condition{treeCondition, condition},
|
||||||
}
|
}
|
||||||
|
@ -216,8 +210,8 @@ func getTreeRule(resources []string, principals []string, principalCondFn s3comm
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func getActionTypes(nativeActions []string) ActionTypes {
|
func getActionTypes(nativeActions []string, treeActions []string) ActionTypes {
|
||||||
var res ActionTypes
|
res := ActionTypes{Tree: len(treeActions) != 0}
|
||||||
for _, action := range nativeActions {
|
for _, action := range nativeActions {
|
||||||
if res.Object && res.Container {
|
if res.Object && res.Container {
|
||||||
break
|
break
|
||||||
|
@ -278,7 +272,8 @@ func convertToNativeChainCondition(c s3common.Conditions, resolver s3common.Nati
|
||||||
for i := range gr.Conditions {
|
for i := range gr.Conditions {
|
||||||
switch {
|
switch {
|
||||||
case gr.Conditions[i].Key == condKeyAWSMFAPresent:
|
case gr.Conditions[i].Key == condKeyAWSMFAPresent:
|
||||||
return s3common.GroupedConditions{}, errConditionKeyNotApplicable
|
// MFA property exist only in S3 request (in AccessBox), so native protocol should not process such conditions.
|
||||||
|
continue
|
||||||
case gr.Conditions[i].Key == s3common.CondKeyAWSPrincipalARN:
|
case gr.Conditions[i].Key == s3common.CondKeyAWSPrincipalARN:
|
||||||
gr.Conditions[i].Key = native.PropertyKeyActorPublicKey
|
gr.Conditions[i].Key = native.PropertyKeyActorPublicKey
|
||||||
val, err := formPrincipalKey(gr.Conditions[i].Value, resolver)
|
val, err := formPrincipalKey(gr.Conditions[i].Value, resolver)
|
||||||
|
@ -308,10 +303,11 @@ type GroupedResources struct {
|
||||||
type ActionTypes struct {
|
type ActionTypes struct {
|
||||||
Object bool
|
Object bool
|
||||||
Container bool
|
Container bool
|
||||||
|
Tree bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func formNativeResourceNamesAndConditions(names []string, resolver s3common.NativeResolver, actionTypes ActionTypes) ([]GroupedResources, []string, error) {
|
func formNativeResourceNamesAndConditions(names []string, resolver s3common.NativeResolver, actionTypes ActionTypes) ([]GroupedResources, []string, error) {
|
||||||
if !actionTypes.Object && !actionTypes.Container {
|
if !actionTypes.Object && !actionTypes.Container && !actionTypes.Tree {
|
||||||
return nil, nil, s3common.ErrActionsNotApplicable
|
return nil, nil, s3common.ErrActionsNotApplicable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,7 +352,12 @@ func formNativeResourceNamesAndConditions(names []string, resolver s3common.Nati
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
treeResMap[fmt.Sprintf(native.ResourceFormatNamespaceContainerObjects, bktInfo.Namespace, bktInfo.Container)] = struct{}{}
|
if actionTypes.Tree {
|
||||||
|
treeResMap[fmt.Sprintf(native.ResourceFormatNamespaceContainerObjects, bktInfo.Namespace, bktInfo.Container)] = struct{}{}
|
||||||
|
if !actionTypes.Object && !actionTypes.Container {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if obj == s3common.Wildcard && actionTypes.Object { // this corresponds to arn:aws:s3:::BUCKET/ or arn:aws:s3:::BUCKET/*
|
if obj == s3common.Wildcard && actionTypes.Object { // this corresponds to arn:aws:s3:::BUCKET/ or arn:aws:s3:::BUCKET/*
|
||||||
combined[fmt.Sprintf(native.ResourceFormatNamespaceContainerObjects, bktInfo.Namespace, bktInfo.Container)] = struct{}{}
|
combined[fmt.Sprintf(native.ResourceFormatNamespaceContainerObjects, bktInfo.Namespace, bktInfo.Container)] = struct{}{}
|
||||||
|
@ -440,18 +441,18 @@ func formPrincipalKey(principal string, resolver s3common.NativeResolver) (strin
|
||||||
return key, nil
|
return key, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func formNativeActionNames(names []string) ([]string, bool, error) {
|
func formNativeActionNames(names []string) ([]string, []string, error) {
|
||||||
uniqueActions := make(map[string]struct{}, len(names))
|
uniqueActions := make(map[string]struct{}, len(names))
|
||||||
|
|
||||||
var treeWrite bool
|
var treeActions []string
|
||||||
for _, action := range names {
|
for _, action := range names {
|
||||||
if action == s3common.Wildcard {
|
if action == s3common.Wildcard {
|
||||||
return []string{s3common.Wildcard}, true, nil
|
return []string{s3common.Wildcard}, treeNativeOperations, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
isIAM, err := s3common.ValidateAction(action)
|
isIAM, err := s3common.ValidateAction(action)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if isIAM {
|
if isIAM {
|
||||||
|
@ -459,15 +460,16 @@ func formNativeActionNames(names []string) ([]string, bool, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if action[len(s3common.S3ActionPrefix):] == s3common.Wildcard {
|
if action[len(s3common.S3ActionPrefix):] == s3common.Wildcard {
|
||||||
return []string{s3common.Wildcard}, true, nil
|
return []string{s3common.Wildcard}, treeNativeOperations, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
nativeActions := actionToNativeOpMap[action]
|
nativeActions := actionToNativeOpMap[action]
|
||||||
if nativeActions.needTreeWrite {
|
if len(nativeActions.operations) == 0 && len(nativeActions.treeOperations) == 0 {
|
||||||
treeWrite = true
|
return nil, nil, s3common.ErrActionsNotApplicable
|
||||||
}
|
}
|
||||||
if len(nativeActions.operations) == 0 {
|
|
||||||
return nil, false, s3common.ErrActionsNotApplicable
|
if len(nativeActions.treeOperations) > len(treeActions) {
|
||||||
|
treeActions = nativeActions.treeOperations
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, nativeAction := range nativeActions.operations {
|
for _, nativeAction := range nativeActions.operations {
|
||||||
|
@ -480,5 +482,5 @@ func formNativeActionNames(names []string) ([]string, bool, error) {
|
||||||
res = append(res, key)
|
res = append(res, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
return res, treeWrite, nil
|
return res, treeActions, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,7 +160,7 @@ func TestConverters(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Status: chain.Allow,
|
Status: chain.Allow,
|
||||||
Actions: chain.Actions{Names: []string{native.MethodGetContainer, native.MethodPutObject,
|
Actions: chain.Actions{Names: []string{native.MethodPutObject,
|
||||||
native.MethodGetObject, native.MethodHeadObject, native.MethodRangeObject}},
|
native.MethodGetObject, native.MethodHeadObject, native.MethodRangeObject}},
|
||||||
Resources: chain.Resources{Names: []string{
|
Resources: chain.Resources{Names: []string{
|
||||||
fmt.Sprintf(native.ResourceFormatNamespaceContainerObjects, namespace, mockResolver.containers[bktName]),
|
fmt.Sprintf(native.ResourceFormatNamespaceContainerObjects, namespace, mockResolver.containers[bktName]),
|
||||||
|
@ -257,7 +257,7 @@ func TestConverters(t *testing.T) {
|
||||||
{
|
{
|
||||||
Status: chain.Allow,
|
Status: chain.Allow,
|
||||||
Actions: chain.Actions{Names: []string{
|
Actions: chain.Actions{Names: []string{
|
||||||
native.MethodGetContainer, native.MethodDeleteContainer,
|
native.MethodDeleteContainer,
|
||||||
native.MethodSearchObject, native.MethodHeadObject,
|
native.MethodSearchObject, native.MethodHeadObject,
|
||||||
native.MethodDeleteObject, native.MethodPutObject,
|
native.MethodDeleteObject, native.MethodPutObject,
|
||||||
native.MethodGetObject, native.MethodRangeObject,
|
native.MethodGetObject, native.MethodRangeObject,
|
||||||
|
@ -284,7 +284,7 @@ func TestConverters(t *testing.T) {
|
||||||
{
|
{
|
||||||
Status: chain.Allow,
|
Status: chain.Allow,
|
||||||
Actions: chain.Actions{Names: []string{
|
Actions: chain.Actions{Names: []string{
|
||||||
native.MethodGetContainer, native.MethodDeleteContainer,
|
native.MethodDeleteContainer,
|
||||||
native.MethodSearchObject, native.MethodHeadObject,
|
native.MethodSearchObject, native.MethodHeadObject,
|
||||||
native.MethodDeleteObject, native.MethodPutObject,
|
native.MethodDeleteObject, native.MethodPutObject,
|
||||||
native.MethodGetObject, native.MethodRangeObject,
|
native.MethodGetObject, native.MethodRangeObject,
|
||||||
|
@ -421,8 +421,8 @@ func TestConverters(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Status: chain.Allow,
|
Status: chain.Allow,
|
||||||
Actions: chain.Actions{Names: []string{native.MethodGetContainer, native.MethodDeleteObject, native.MethodPutObject, native.MethodHeadObject, native.MethodGetObject, native.MethodRangeObject}},
|
Actions: chain.Actions{Names: []string{native.MethodDeleteObject, native.MethodPutObject, native.MethodHeadObject, native.MethodGetObject, native.MethodRangeObject}},
|
||||||
Resources: chain.Resources{Names: []string{native.ResourceFormatAllObjects, native.ResourceFormatAllContainers}},
|
Resources: chain.Resources{Names: []string{native.ResourceFormatAllObjects}},
|
||||||
Condition: []chain.Condition{{
|
Condition: []chain.Condition{{
|
||||||
Op: chain.CondStringEquals,
|
Op: chain.CondStringEquals,
|
||||||
Kind: chain.KindRequest,
|
Kind: chain.KindRequest,
|
||||||
|
@ -1752,7 +1752,7 @@ func TestFromActions(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
action: "s3:PutObject",
|
action: "s3:PutObject",
|
||||||
res: []string{native.MethodGetContainer, native.MethodPutObject,
|
res: []string{native.MethodPutObject,
|
||||||
native.MethodGetObject, native.MethodHeadObject, native.MethodRangeObject},
|
native.MethodGetObject, native.MethodHeadObject, native.MethodRangeObject},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -2095,7 +2095,7 @@ func TestMFACondition(t *testing.T) {
|
||||||
require.ElementsMatch(t, expectedConditions, s3Chain.Rules[0].Condition)
|
require.ElementsMatch(t, expectedConditions, s3Chain.Rules[0].Condition)
|
||||||
|
|
||||||
_, err = ConvertToNativeChain(p, newMockUserResolver(nil, nil, ""))
|
_, err = ConvertToNativeChain(p, newMockUserResolver(nil, nil, ""))
|
||||||
require.ErrorIs(t, err, s3common.ErrActionsNotApplicable)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue