forked from TrueCloudLab/policy-engine
[#26] schema: Add resource name validation method
Close #26 Signed-off-by: Airat Arifullin <aarifullin@yadro.com>
This commit is contained in:
parent
156018bcba
commit
e4e381b8a4
3 changed files with 162 additions and 0 deletions
20
docs/resource.md
Normal file
20
docs/resource.md
Normal file
|
@ -0,0 +1,20 @@
|
|||
# Resource
|
||||
|
||||
From the point of the access policy engine, a resource is an object to which a request is being performed.
|
||||
This can be an object in a container within a namespace, or all objects in a container,
|
||||
or all containers within the root namespace etc.
|
||||
|
||||
A resource can be viewed from two sides:
|
||||
- As part of a [request](../pkg/resource/resource.go). In this case a resource has a name and properties.
|
||||
- As part of rule [chain](../pkg/chain/chain.go): a resource has just a name.
|
||||
|
||||
## Resource name
|
||||
|
||||
A resource name must have a such format that can be processed by a chain router that matches a request
|
||||
either with local overrides or with rules within policy contract to get if this request is allowed to be performed.
|
||||
The main idea of this format is for the chain router to match by full name (`native:object//cnrID/objID`) or
|
||||
wildcard (`native:object//cnrID/*`).
|
||||
|
||||
Check out formats that are defined in the schema: [native formats](../schema/native/consts.go), [s3 formats](../schema/s3/consts.go).
|
||||
You should validate a resource name using [util](../schema/native/util/validation.go) before instantiating a request or
|
||||
before putting it to either to local override storage or the policy contract storage.
|
45
schema/native/util/validation.go
Normal file
45
schema/native/util/validation.go
Normal file
|
@ -0,0 +1,45 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/policy-engine/schema/native"
|
||||
)
|
||||
|
||||
var nativePatterns = []string{
|
||||
native.ResourceFormatNamespaceObjects, native.ResourceFormatNamespaceContainerObjects,
|
||||
native.ResourceFormatNamespaceContainerObject, native.ResourceFormatRootObjects,
|
||||
native.ResourceFormatRootContainerObjects, native.ResourceFormatRootContainerObject,
|
||||
native.ResourceFormatAllObjects, native.ResourceFormatNamespaceContainer,
|
||||
native.ResourceFormatNamespaceContainers, native.ResourceFormatRootContainer,
|
||||
native.ResourceFormatRootContainers, native.ResourceFormatAllContainers,
|
||||
}
|
||||
|
||||
func match(resource, pattern string) bool {
|
||||
rTokens := strings.Split(resource, "/")
|
||||
pToken := strings.Split(pattern, "/")
|
||||
|
||||
if len(rTokens) != len(pToken) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := range rTokens {
|
||||
if pToken[i] == "%s" {
|
||||
continue
|
||||
}
|
||||
if pToken[i] != rTokens[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func IsNativeResourceNameValid(resource string) bool {
|
||||
for _, pattern := range nativePatterns {
|
||||
if match(resource, pattern) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
97
schema/native/util/validation_test.go
Normal file
97
schema/native/util/validation_test.go
Normal file
|
@ -0,0 +1,97 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
expected bool
|
||||
resource string
|
||||
}{
|
||||
{
|
||||
name: "ResourceFormatNamespaceObjects",
|
||||
expected: true,
|
||||
resource: "native:object/RootNamespace/*",
|
||||
},
|
||||
{
|
||||
name: "ResourceFormatNamespaceContainerObjects",
|
||||
expected: true,
|
||||
resource: "native:object/RootNamespace/BzQw5HH3feoxFDD5tCT87Y1726qzgLfxEE7wgtoRzB3R/*",
|
||||
},
|
||||
{
|
||||
name: "ResourceFormatNamespaceContainerObject",
|
||||
expected: true,
|
||||
resource: "native:object/RootNamespace/BzQw5HH3feoxFDD5tCT87Y1726qzgLfxEE7wgtoRzB3R/AeZa5HH3feoxFDD5tCT87Y1726qzgLfxEE7wgtoRzB4E",
|
||||
},
|
||||
{
|
||||
name: "ResourceFormatRootObjects",
|
||||
expected: true,
|
||||
resource: "native:object//*",
|
||||
},
|
||||
{
|
||||
name: "ResourceFormatRootContainerObjects",
|
||||
expected: true,
|
||||
resource: "native:object//BzQw5HH3feoxFDD5tCT87Y1726qzgLfxEE7wgtoRzB3R/*",
|
||||
},
|
||||
{
|
||||
name: "ResourceFormatRootContainerObject",
|
||||
expected: true,
|
||||
resource: "native:object//BzQw5HH3feoxFDD5tCT87Y1726qzgLfxEE7wgtoRzB3R/AeZa5HH3feoxFDD5tCT87Y1726qzgLfxEE7wgtoRzB4E",
|
||||
},
|
||||
{
|
||||
name: "ResourceFormatAllObjects",
|
||||
expected: true,
|
||||
resource: "native:object/*",
|
||||
},
|
||||
{
|
||||
name: "ResourceFormatNamespaceContainer",
|
||||
expected: true,
|
||||
resource: "native:container/RootNamespace/BzQw5HH3feoxFDD5tCT87Y1726qzgLfxEE7wgtoRzB3R",
|
||||
},
|
||||
{
|
||||
name: "ResourceFormatNamespaceContainers",
|
||||
expected: true,
|
||||
resource: "native:container/RootNamespace/*",
|
||||
},
|
||||
{
|
||||
name: "ResourceFormatRootContainers",
|
||||
expected: true,
|
||||
resource: "native:container//*",
|
||||
},
|
||||
{
|
||||
name: "ResourceFormatAllContainers",
|
||||
expected: true,
|
||||
resource: "native:container/*",
|
||||
},
|
||||
{
|
||||
name: "Invalid resource 1",
|
||||
expected: false,
|
||||
resource: "native:::container/*",
|
||||
},
|
||||
{
|
||||
name: "Invalid resource 2",
|
||||
expected: false,
|
||||
resource: "native:container/RootNamespace/w5HH3feoxFDD5tCTtoRzB3R/Bz726qzgLfxEE7wgtoRzB3R/RootNamespace",
|
||||
},
|
||||
}
|
||||
|
||||
func TestIsNativeResourceNameValid(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
require.Equal(t, test.expected, IsNativeResourceNameValid(test.resource))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIsNativeResourceNameValid(b *testing.B) {
|
||||
for _, test := range tests {
|
||||
b.Run(test.name, func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = IsNativeResourceNameValid(test.resource)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue