[#80] iam: Skip unsupported conditions in native chains #80

Merged
dkirillov merged 2 commits from dkirillov/policy-engine:bugfix/skip_aws_condition_in_native_converters into master 2024-09-04 19:51:23 +00:00
4 changed files with 38 additions and 11 deletions

View file

@ -69,6 +69,8 @@ const (
condKeyAWSPrincipalARN = "aws:PrincipalArn" condKeyAWSPrincipalARN = "aws:PrincipalArn"
condKeyAWSSourceIP = "aws:SourceIp" condKeyAWSSourceIP = "aws:SourceIp"
condKeyAWSPrincipalTagPrefix = "aws:PrincipalTag/" condKeyAWSPrincipalTagPrefix = "aws:PrincipalTag/"
condKeyAWSRequestTagPrefix = "aws:RequestTag/"
condKeyAWSResourceTagPrefix = "aws:ResourceTag/"
userClaimTagPrefix = "tag-" userClaimTagPrefix = "tag-"
) )

View file

@ -224,21 +224,33 @@ func getNativePrincipalsAndConditionFunc(statement Statement, resolver NativeRes
func convertToNativeChainCondition(c Conditions, resolver NativeResolver) ([]GroupedConditions, error) { func convertToNativeChainCondition(c Conditions, resolver NativeResolver) ([]GroupedConditions, error) {
return convertToChainConditions(c, func(gr GroupedConditions) (GroupedConditions, error) { return convertToChainConditions(c, func(gr GroupedConditions) (GroupedConditions, error) {
for i := range gr.Conditions { res := GroupedConditions{
if gr.Conditions[i].Key == condKeyAWSMFAPresent { Conditions: make([]chain.Condition, 0, len(gr.Conditions)),
return GroupedConditions{}, errConditionKeyNotApplicable Any: gr.Any,
} }
if gr.Conditions[i].Key == condKeyAWSPrincipalARN {
for i := range gr.Conditions {
switch {
case gr.Conditions[i].Key == condKeyAWSMFAPresent:
return GroupedConditions{}, errConditionKeyNotApplicable
case gr.Conditions[i].Key == 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)
if err != nil { if err != nil {
return GroupedConditions{}, err return GroupedConditions{}, err
} }
gr.Conditions[i].Value = val gr.Conditions[i].Value = val
res.Conditions = append(res.Conditions, gr.Conditions[i])
case strings.HasPrefix(gr.Conditions[i].Key, condKeyAWSRequestTagPrefix) ||
strings.HasPrefix(gr.Conditions[i].Key, condKeyAWSResourceTagPrefix):
// Tags exist only in S3 requests, so native protocol should not process such conditions.
alexvanin marked this conversation as resolved Outdated

Small comment about the reason we skip these conditions will be nice, e.g.

Tags exist only in S3 requests, so native protocol should not process such conditions.
Small comment about the reason we skip these conditions will be nice, e.g. ``` Tags exist only in S3 requests, so native protocol should not process such conditions. ```
continue
default:
res.Conditions = append(res.Conditions, gr.Conditions[i])
} }
} }
return gr, nil return res, nil
}) })
} }

View file

@ -2,6 +2,7 @@ package iam
import ( import (
"fmt" "fmt"
"strings"
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain" "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
"git.frostfs.info/TrueCloudLab/policy-engine/schema/s3" "git.frostfs.info/TrueCloudLab/policy-engine/schema/s3"
@ -169,16 +170,19 @@ func getS3PrincipalsAndConditionFunc(statement Statement, resolver S3Resolver) (
func convertToS3ChainCondition(c Conditions, resolver S3Resolver) ([]GroupedConditions, error) { func convertToS3ChainCondition(c Conditions, resolver S3Resolver) ([]GroupedConditions, error) {
return convertToChainConditions(c, func(gr GroupedConditions) (GroupedConditions, error) { return convertToChainConditions(c, func(gr GroupedConditions) (GroupedConditions, error) {
for i := range gr.Conditions { for i := range gr.Conditions {
if gr.Conditions[i].Key == condKeyAWSPrincipalARN { switch {
case gr.Conditions[i].Key == condKeyAWSPrincipalARN:
gr.Conditions[i].Key = s3.PropertyKeyOwner gr.Conditions[i].Key = s3.PropertyKeyOwner
val, err := formPrincipalOwner(gr.Conditions[i].Value, resolver) val, err := formPrincipalOwner(gr.Conditions[i].Value, resolver)
if err != nil { if err != nil {
return GroupedConditions{}, err return GroupedConditions{}, err
} }
gr.Conditions[i].Value = val gr.Conditions[i].Value = val
}
if gr.Conditions[i].Key == condKeyAWSMFAPresent { case gr.Conditions[i].Key == condKeyAWSMFAPresent:
gr.Conditions[i].Key = s3.PropertyKeyAccessBoxAttrMFA gr.Conditions[i].Key = s3.PropertyKeyAccessBoxAttrMFA
case strings.HasPrefix(gr.Conditions[i].Key, condKeyAWSResourceTagPrefix):
alexvanin marked this conversation as resolved Outdated

We don't check condKeyAWSRequestTagPrefix unlike native converter because by default it goes to request condition?

We don't check `condKeyAWSRequestTagPrefix` unlike native converter because by default it goes to request condition?

Yes

Yes
gr.Conditions[i].Kind = chain.KindResource
} }
} }

View file

@ -1696,7 +1696,7 @@ func TestTagsConditions(t *testing.T) {
} }
` `
expectedConditions := []chain.Condition{ expectedS3Conditions := []chain.Condition{
{ {
Op: chain.CondStringEquals, Op: chain.CondStringEquals,
Kind: chain.KindRequest, Kind: chain.KindRequest,
@ -1705,7 +1705,7 @@ func TestTagsConditions(t *testing.T) {
}, },
{ {
Op: chain.CondStringEquals, Op: chain.CondStringEquals,
Kind: chain.KindRequest, Kind: chain.KindResource,
Key: fmt.Sprintf(s3.PropertyKeyFormatResourceTag, "owner"), Key: fmt.Sprintf(s3.PropertyKeyFormatResourceTag, "owner"),
Value: "hr-admin", Value: "hr-admin",
}, },
@ -1717,6 +1717,15 @@ func TestTagsConditions(t *testing.T) {
}, },
} }
expectedNativeConditions := []chain.Condition{
{
Op: chain.CondStringEquals,
Kind: chain.KindRequest,
Key: fmt.Sprintf(common.PropertyKeyFormatFrostFSIDUserClaim, "tag-department"),
Value: "hr",
},
}
var p Policy var p Policy
err := json.Unmarshal([]byte(policy), &p) err := json.Unmarshal([]byte(policy), &p)
require.NoError(t, err) require.NoError(t, err)
@ -1724,12 +1733,12 @@ func TestTagsConditions(t *testing.T) {
s3Chain, err := ConvertToS3Chain(p, newMockUserResolver(nil, nil, "")) s3Chain, err := ConvertToS3Chain(p, newMockUserResolver(nil, nil, ""))
require.NoError(t, err) require.NoError(t, err)
require.Len(t, s3Chain.Rules, 1) require.Len(t, s3Chain.Rules, 1)
require.ElementsMatch(t, expectedConditions, s3Chain.Rules[0].Condition) require.ElementsMatch(t, expectedS3Conditions, s3Chain.Rules[0].Condition)
nativeChain, err := ConvertToNativeChain(p, newMockUserResolver(nil, nil, "")) nativeChain, err := ConvertToNativeChain(p, newMockUserResolver(nil, nil, ""))
require.NoError(t, err) require.NoError(t, err)
require.Len(t, nativeChain.Rules, 1) require.Len(t, nativeChain.Rules, 1)
require.ElementsMatch(t, expectedConditions, nativeChain.Rules[0].Condition) require.ElementsMatch(t, expectedNativeConditions, nativeChain.Rules[0].Condition)
} }
func TestMFACondition(t *testing.T) { func TestMFACondition(t *testing.T) {