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 }