Anton Nikiforov
483a67b170
All checks were successful
DCO action / DCO (pull_request) Successful in 2m13s
Build / Build Components (1.20) (pull_request) Successful in 3m38s
Vulncheck / Vulncheck (pull_request) Successful in 3m13s
Tests and linters / Staticcheck (pull_request) Successful in 6m15s
Build / Build Components (1.21) (pull_request) Successful in 7m11s
Tests and linters / Lint (pull_request) Successful in 9m35s
Tests and linters / Tests (1.21) (pull_request) Successful in 13m56s
Tests and linters / Tests (1.20) (pull_request) Successful in 14m14s
Tests and linters / Tests with -race (pull_request) Successful in 6m2s
Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
97 lines
2.9 KiB
Go
97 lines
2.9 KiB
Go
package ape
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/ape"
|
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
|
"git.frostfs.info/TrueCloudLab/policy-engine/schema/native"
|
|
)
|
|
|
|
var (
|
|
ErrInvalidResource = errors.New("invalid resource name")
|
|
ErrUnsupportedPrefix = errors.New("unsupported resource name prefix")
|
|
ErrInvalidContainerID = errors.New("invalid container id")
|
|
ErrInvalidObjectID = errors.New("invalid object id")
|
|
ErrInvalidNamespace = fmt.Errorf("namespace must match regexp: %s", ape.NamespaceNameRegexp.String())
|
|
)
|
|
|
|
// ValidateResourceName validates resource name components - container and object id, namespace.
|
|
// Also validates matching resource name to templates of policy engine's native scheme.
|
|
func ValidateResourceName(name string) error {
|
|
if after, found := strings.CutPrefix(name, native.ObjectPrefix+"/"); found {
|
|
return validateObjectResourceName(after)
|
|
} else if after, found = strings.CutPrefix(name, native.ContainerPrefix+"/"); found {
|
|
return validateContainerResourceName(after)
|
|
}
|
|
return ErrUnsupportedPrefix
|
|
}
|
|
|
|
// validateObjectResourceName validate name for object.
|
|
// Name should be without prefix `native.ObjectPrefix`.
|
|
func validateObjectResourceName(name string) error {
|
|
if name == "*" {
|
|
return nil
|
|
}
|
|
lexems := strings.Split(name, "/")
|
|
if len(lexems) == 1 && lexems[0] == "*" {
|
|
return nil
|
|
} else if len(lexems) == 2 {
|
|
// len == 2 means format `namespace(root_namespace)/*`
|
|
if lexems[0] != "" && !ape.NamespaceNameRegexp.MatchString(lexems[0]) {
|
|
return ErrInvalidNamespace
|
|
}
|
|
if lexems[1] == "*" {
|
|
return nil
|
|
}
|
|
} else if len(lexems) == 3 {
|
|
// len == 3 means format `namespace(root_namespace)/CID/OID(*)`
|
|
if lexems[0] != "" && !ape.NamespaceNameRegexp.MatchString(lexems[0]) {
|
|
return ErrInvalidNamespace
|
|
}
|
|
var cnr cid.ID
|
|
err := cnr.DecodeString(lexems[1])
|
|
if err != nil {
|
|
return fmt.Errorf("%w: %w", ErrInvalidContainerID, err)
|
|
}
|
|
if lexems[2] == "*" {
|
|
return nil
|
|
}
|
|
var objID oid.ID
|
|
err = objID.DecodeString(lexems[2])
|
|
if err != nil {
|
|
return fmt.Errorf("%w: %w", ErrInvalidObjectID, err)
|
|
}
|
|
return nil
|
|
}
|
|
return ErrInvalidResource
|
|
}
|
|
|
|
// validateContainerResourceName validate resource name for container.
|
|
// Name should be without prefix `native.ContainerPrefix`.
|
|
func validateContainerResourceName(name string) error {
|
|
if name == "*" {
|
|
return nil
|
|
}
|
|
lexems := strings.Split(name, "/")
|
|
if len(lexems) == 1 && lexems[0] == "*" {
|
|
return nil
|
|
} else if len(lexems) == 2 {
|
|
// len == 2 means format `namespace(root_namespace)/CID(*)`
|
|
if lexems[0] != "" && !ape.NamespaceNameRegexp.MatchString(lexems[0]) {
|
|
return ErrInvalidNamespace
|
|
}
|
|
if lexems[1] != "*" {
|
|
var cnr cid.ID
|
|
err := cnr.DecodeString(lexems[1])
|
|
if err != nil {
|
|
return fmt.Errorf("%w: %w", ErrInvalidContainerID, err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
return ErrInvalidResource
|
|
}
|