[#63] iam: Support tag keys #63

Merged
fyrchik merged 1 commit from dkirillov/policy-engine:feature/iam-tags into master 2024-04-05 11:22:59 +00:00
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-"
fyrchik marked this conversation as resolved Outdated

To be clear, is this tag- something present in AWS/S3 spec or our addition?

To be clear, is this `tag-` something present in AWS/S3 spec or our addition?

Our addition, to distinguish tags in user claims.

Our addition, to distinguish tags in user claims.
)
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 {
fyrchik marked this conversation as resolved Outdated

What about using https://pkg.go.dev/strings#CutPrefix? (it combines HasPrefix and TrimPrefix)
Or do we expect this switch to grow?

What about using https://pkg.go.dev/strings#CutPrefix? (it combines `HasPrefix` and `TrimPrefix`) Or do we expect this switch to grow?

In the future I expect this switch to grow, but for now I'll change to using CutPrefix

In the future I expect this switch to grow, but for now I'll change to using `CutPrefix`
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, ""))
mbiryukova marked this conversation as resolved Outdated

Should be ConvertToS3Chain?

Should be `ConvertToS3Chain`?

Oh, sure

Oh, sure
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"
)