generated from TrueCloudLab/basic
[#80] iam: Skip unsupported conditions in native chains #80
4 changed files with 38 additions and 11 deletions
|
@ -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-"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
res := GroupedConditions{
|
||||||
|
Conditions: make([]chain.Condition, 0, len(gr.Conditions)),
|
||||||
|
Any: gr.Any,
|
||||||
|
}
|
||||||
|
|
||||||
for i := range gr.Conditions {
|
for i := range gr.Conditions {
|
||||||
if gr.Conditions[i].Key == condKeyAWSMFAPresent {
|
switch {
|
||||||
|
case gr.Conditions[i].Key == condKeyAWSMFAPresent:
|
||||||
return GroupedConditions{}, errConditionKeyNotApplicable
|
return GroupedConditions{}, errConditionKeyNotApplicable
|
||||||
}
|
case gr.Conditions[i].Key == condKeyAWSPrincipalARN:
|
||||||
if 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
|
|||||||
|
continue
|
||||||
|
default:
|
||||||
|
res.Conditions = append(res.Conditions, gr.Conditions[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return gr, nil
|
return res, nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
alexvanin
commented
We don't check We don't check `condKeyAWSRequestTagPrefix` unlike native converter because by default it goes to request condition?
dkirillov
commented
Yes Yes
|
|||||||
|
gr.Conditions[i].Kind = chain.KindResource
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue
Small comment about the reason we skip these conditions will be nice, e.g.