[#63] iam: Support tag keys

Support:
* aws:PrincipalTag
* aws:ResourceTag
* aws:Request

Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
This commit is contained in:
Denis Kirillov 2024-04-04 14:18:18 +03:00
parent 42497ad242
commit 67e4595a91
3 changed files with 76 additions and 2 deletions

View file

@ -9,6 +9,7 @@ import (
"unicode/utf8"
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
"git.frostfs.info/TrueCloudLab/policy-engine/schema/common"
)
const (
@ -62,7 +63,11 @@ const (
s3ActionPutObjectVersionTagging = "s3:PutObjectVersionTagging"
)
const condKeyAWSPrincipalARN = "aws:PrincipalArn"
const (
condKeyAWSPrincipalARN = "aws:PrincipalArn"
condKeyAWSPrincipalTagPrefix = "aws:PrincipalTag/"
userClaimTagPrefix = "tag-"
)
const (
// String condition operators.
@ -175,7 +180,7 @@ func convertToChainCondition(c Conditions) ([]GroupedConditions, error) {
group.Conditions[i] = chain.Condition{
Op: condType,
Object: chain.ObjectRequest,
Key: key,
Key: transformKey(key),
Value: converted,
}
}
@ -186,6 +191,15 @@ func convertToChainCondition(c Conditions) ([]GroupedConditions, error) {
return grouped, nil
}
func transformKey(key string) string {
tagName, isTag := strings.CutPrefix(key, condKeyAWSPrincipalTagPrefix)
if isTag {
return fmt.Sprintf(common.PropertyKeyFormatFrostFSIDUserClaim, userClaimTagPrefix+tagName)
}
return key
}
func getConditionTypeAndConverter(op string) (chain.ConditionType, convertFunction, error) {
switch {
case strings.HasPrefix(op, "String"):

View file

@ -1500,6 +1500,64 @@ func TestResourceParsing(t *testing.T) {
}
}
func TestTagsConditions(t *testing.T) {
policy := `
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:PutObjectTagging",
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:PrincipalTag/department": "hr",
"aws:ResourceTag/owner": "hr-admin",
"aws:Request/scope": "*"
}
}
}
]
}
`
expectedConditions := []chain.Condition{
{
Op: chain.CondStringEquals,
Object: chain.ObjectRequest,
Key: "frostfsid:userClaim/tag-department",
Value: "hr",
},
{
Op: chain.CondStringEquals,
Object: chain.ObjectRequest,
Key: "aws:ResourceTag/owner",
Value: "hr-admin",
},
{
Op: chain.CondStringEquals,
Object: chain.ObjectRequest,
Key: "aws:Request/scope",
Value: "*",
},
}
var p Policy
err := json.Unmarshal([]byte(policy), &p)
require.NoError(t, err)
s3Chain, err := ConvertToS3Chain(p, newMockUserResolver(nil, nil, ""))
require.NoError(t, err)
require.Len(t, s3Chain.Rules, 1)
require.ElementsMatch(t, expectedConditions, s3Chain.Rules[0].Condition)
nativeChain, err := ConvertToNativeChain(p, newMockUserResolver(nil, nil, ""))
require.NoError(t, err)
require.Len(t, nativeChain.Rules, 1)
require.ElementsMatch(t, expectedConditions, nativeChain.Rules[0].Condition)
}
func requireChainRulesMatch(t *testing.T, expected, actual []chain.Rule) {
require.Equal(t, len(expected), len(actual), "length of chain rules differ")

View file

@ -2,4 +2,6 @@ package common
const (
PropertyKeyFrostFSIDGroupID = "frostfsid:groupID"
PropertyKeyFormatFrostFSIDUserClaim = "frostfsid:userClaim/%s"
)