forked from TrueCloudLab/frostfs-node
[#986] cli: Allow add-rule command to parse new actions
* Introduce Object.* and Container.* actions that span all methods for services. Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
This commit is contained in:
parent
0f064b7962
commit
47d9ce71be
2 changed files with 53 additions and 17 deletions
|
@ -27,6 +27,7 @@ For container it can be represented as:
|
||||||
- `/*` all containers in the `root` namespace
|
- `/*` all containers in the `root` namespace
|
||||||
|
|
||||||
Actions is a regular operations upon FrostFS containers/objects. Like `Object.Put`, `Container.Get` etc.
|
Actions is a regular operations upon FrostFS containers/objects. Like `Object.Put`, `Container.Get` etc.
|
||||||
|
You can use `Object.*`, `Container.*` that implies all actions.
|
||||||
|
|
||||||
In status section it is possible to use `allow`, `deny` or `deny:QuotaLimitReached` actions.
|
In status section it is possible to use `allow`, `deny` or `deny:QuotaLimitReached` actions.
|
||||||
|
|
||||||
|
|
|
@ -102,6 +102,8 @@ func ParseAPEChain(chain *apechain.Chain, rules []string) error {
|
||||||
// allow Object.Get Object.Resource:Department=HR Object.Request:Actor=ownerA *
|
// allow Object.Get Object.Resource:Department=HR Object.Request:Actor=ownerA *
|
||||||
// allow Object.Get any Object.Resource:Department=HR Object.Request:Actor=ownerA *
|
// allow Object.Get any Object.Resource:Department=HR Object.Request:Actor=ownerA *
|
||||||
// allow Object.Get all Object.Resource:Department=HR Object.Request:Actor=ownerA *
|
// allow Object.Get all Object.Resource:Department=HR Object.Request:Actor=ownerA *
|
||||||
|
// allow Object.* *
|
||||||
|
// allow Container.* *
|
||||||
//
|
//
|
||||||
//nolint:godot
|
//nolint:godot
|
||||||
func ParseAPERule(r *apechain.Rule, rule string) error {
|
func ParseAPERule(r *apechain.Rule, rule string) error {
|
||||||
|
@ -112,6 +114,18 @@ func ParseAPERule(r *apechain.Rule, rule string) error {
|
||||||
return parseRuleLexemes(r, lexemes)
|
return parseRuleLexemes(r, lexemes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func unique(inputSlice []string) []string {
|
||||||
|
uniqueSlice := make([]string, 0, len(inputSlice))
|
||||||
|
seen := make(map[string]bool, len(inputSlice))
|
||||||
|
for _, element := range inputSlice {
|
||||||
|
if !seen[element] {
|
||||||
|
uniqueSlice = append(uniqueSlice, element)
|
||||||
|
seen[element] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return uniqueSlice
|
||||||
|
}
|
||||||
|
|
||||||
func parseRuleLexemes(r *apechain.Rule, lexemes []string) error {
|
func parseRuleLexemes(r *apechain.Rule, lexemes []string) error {
|
||||||
if len(lexemes) < 2 {
|
if len(lexemes) < 2 {
|
||||||
return errInvalidStatementFormat
|
return errInvalidStatementFormat
|
||||||
|
@ -131,9 +145,9 @@ func parseRuleLexemes(r *apechain.Rule, lexemes []string) error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var name string
|
var names []string
|
||||||
var actionType bool
|
var actionType bool
|
||||||
name, actionType, err = parseAction(lexeme)
|
names, actionType, err = parseAction(lexeme)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
condition, errCond := parseCondition(lexeme)
|
condition, errCond := parseCondition(lexeme)
|
||||||
if errCond != nil {
|
if errCond != nil {
|
||||||
|
@ -144,7 +158,7 @@ func parseRuleLexemes(r *apechain.Rule, lexemes []string) error {
|
||||||
actionType = condition.Object == apechain.ObjectResource || condition.Object == apechain.ObjectRequest
|
actionType = condition.Object == apechain.ObjectResource || condition.Object == apechain.ObjectRequest
|
||||||
r.Condition = append(r.Condition, *condition)
|
r.Condition = append(r.Condition, *condition)
|
||||||
} else {
|
} else {
|
||||||
r.Actions.Names = append(r.Actions.Names, name)
|
r.Actions.Names = append(r.Actions.Names, names...)
|
||||||
}
|
}
|
||||||
if isObject == nil {
|
if isObject == nil {
|
||||||
isObject = &actionType
|
isObject = &actionType
|
||||||
|
@ -152,6 +166,7 @@ func parseRuleLexemes(r *apechain.Rule, lexemes []string) error {
|
||||||
return errMixedTypesInRule
|
return errMixedTypesInRule
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
r.Actions.Names = unique(r.Actions.Names)
|
||||||
if len(r.Actions.Names) == 0 {
|
if len(r.Actions.Names) == 0 {
|
||||||
return fmt.Errorf("%w:%w", err, errNoActionsInRule)
|
return fmt.Errorf("%w:%w", err, errNoActionsInRule)
|
||||||
}
|
}
|
||||||
|
@ -198,35 +213,55 @@ func parseStatus(lexeme string) (apechain.Status, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseAction(lexeme string) (string, bool, error) {
|
func parseAction(lexeme string) ([]string, bool, error) {
|
||||||
switch strings.ToLower(lexeme) {
|
switch strings.ToLower(lexeme) {
|
||||||
case "object.put":
|
case "object.put":
|
||||||
return nativeschema.MethodPutObject, true, nil
|
return []string{nativeschema.MethodPutObject}, true, nil
|
||||||
case "object.get":
|
case "object.get":
|
||||||
return nativeschema.MethodGetObject, true, nil
|
return []string{nativeschema.MethodGetObject}, true, nil
|
||||||
case "object.head":
|
case "object.head":
|
||||||
return nativeschema.MethodHeadObject, true, nil
|
return []string{nativeschema.MethodHeadObject}, true, nil
|
||||||
case "object.delete":
|
case "object.delete":
|
||||||
return nativeschema.MethodDeleteObject, true, nil
|
return []string{nativeschema.MethodDeleteObject}, true, nil
|
||||||
case "object.search":
|
case "object.search":
|
||||||
return nativeschema.MethodSearchObject, true, nil
|
return []string{nativeschema.MethodSearchObject}, true, nil
|
||||||
case "object.range":
|
case "object.range":
|
||||||
return nativeschema.MethodRangeObject, true, nil
|
return []string{nativeschema.MethodRangeObject}, true, nil
|
||||||
case "object.hash":
|
case "object.hash":
|
||||||
return nativeschema.MethodHashObject, true, nil
|
return []string{nativeschema.MethodHashObject}, true, nil
|
||||||
|
case "object.*":
|
||||||
|
return []string{
|
||||||
|
nativeschema.MethodPutObject,
|
||||||
|
nativeschema.MethodGetObject,
|
||||||
|
nativeschema.MethodHeadObject,
|
||||||
|
nativeschema.MethodDeleteObject,
|
||||||
|
nativeschema.MethodSearchObject,
|
||||||
|
nativeschema.MethodHashObject,
|
||||||
|
}, true, nil
|
||||||
case "container.put":
|
case "container.put":
|
||||||
return nativeschema.MethodPutContainer, false, nil
|
return []string{nativeschema.MethodPutContainer}, false, nil
|
||||||
case "container.delete":
|
case "container.delete":
|
||||||
return nativeschema.MethodDeleteContainer, false, nil
|
return []string{nativeschema.MethodDeleteContainer}, false, nil
|
||||||
case "container.get":
|
case "container.get":
|
||||||
return nativeschema.MethodGetContainer, false, nil
|
return []string{nativeschema.MethodGetContainer}, false, nil
|
||||||
case "container.setcontainereacl":
|
case "container.setcontainereacl":
|
||||||
return nativeschema.MethodSetContainerEACL, false, nil
|
return []string{nativeschema.MethodSetContainerEACL}, false, nil
|
||||||
case "container.getcontainereacl":
|
case "container.getcontainereacl":
|
||||||
return nativeschema.MethodGetContainerEACL, false, nil
|
return []string{nativeschema.MethodGetContainerEACL}, false, nil
|
||||||
|
case "container.list":
|
||||||
|
return []string{nativeschema.MethodListContainers}, false, nil
|
||||||
|
case "container.*":
|
||||||
|
return []string{
|
||||||
|
nativeschema.MethodPutContainer,
|
||||||
|
nativeschema.MethodDeleteContainer,
|
||||||
|
nativeschema.MethodGetContainer,
|
||||||
|
nativeschema.MethodSetContainerEACL,
|
||||||
|
nativeschema.MethodGetContainerEACL,
|
||||||
|
nativeschema.MethodListContainers,
|
||||||
|
}, false, nil
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
return "", false, fmt.Errorf("%w: %s", errUnknownAction, lexeme)
|
return nil, false, fmt.Errorf("%w: %s", errUnknownAction, lexeme)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseResource(lexeme string, isObj bool) (string, error) {
|
func parseResource(lexeme string, isObj bool) (string, error) {
|
||||||
|
|
Loading…
Reference in a new issue