generated from TrueCloudLab/basic
[#63] iam: Support tag keys #63
3 changed files with 76 additions and 2 deletions
|
@ -9,6 +9,7 @@ import (
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
||||||
|
"git.frostfs.info/TrueCloudLab/policy-engine/schema/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -62,7 +63,11 @@ const (
|
||||||
s3ActionPutObjectVersionTagging = "s3:PutObjectVersionTagging"
|
s3ActionPutObjectVersionTagging = "s3:PutObjectVersionTagging"
|
||||||
)
|
)
|
||||||
|
|
||||||
const condKeyAWSPrincipalARN = "aws:PrincipalArn"
|
const (
|
||||||
|
condKeyAWSPrincipalARN = "aws:PrincipalArn"
|
||||||
|
condKeyAWSPrincipalTagPrefix = "aws:PrincipalTag/"
|
||||||
|
userClaimTagPrefix = "tag-"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// String condition operators.
|
// String condition operators.
|
||||||
|
@ -175,7 +180,7 @@ func convertToChainCondition(c Conditions) ([]GroupedConditions, error) {
|
||||||
group.Conditions[i] = chain.Condition{
|
group.Conditions[i] = chain.Condition{
|
||||||
Op: condType,
|
Op: condType,
|
||||||
Object: chain.ObjectRequest,
|
Object: chain.ObjectRequest,
|
||||||
Key: key,
|
Key: transformKey(key),
|
||||||
Value: converted,
|
Value: converted,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -186,6 +191,15 @@ func convertToChainCondition(c Conditions) ([]GroupedConditions, error) {
|
||||||
return grouped, nil
|
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) {
|
func getConditionTypeAndConverter(op string) (chain.ConditionType, convertFunction, error) {
|
||||||
switch {
|
switch {
|
||||||
case strings.HasPrefix(op, "String"):
|
case strings.HasPrefix(op, "String"):
|
||||||
|
|
|
@ -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) {
|
func requireChainRulesMatch(t *testing.T, expected, actual []chain.Rule) {
|
||||||
require.Equal(t, len(expected), len(actual), "length of chain rules differ")
|
require.Equal(t, len(expected), len(actual), "length of chain rules differ")
|
||||||
|
|
||||||
|
|
|
@ -2,4 +2,6 @@ package common
|
||||||
|
|
||||||
const (
|
const (
|
||||||
PropertyKeyFrostFSIDGroupID = "frostfsid:groupID"
|
PropertyKeyFrostFSIDGroupID = "frostfsid:groupID"
|
||||||
|
|
||||||
|
PropertyKeyFormatFrostFSIDUserClaim = "frostfsid:userClaim/%s"
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue