Tweak logic & add base RBAC import/export test
This commit is contained in:
+2
-2
@@ -83,9 +83,9 @@ func (e StoreEncoder) Encode(ctx context.Context, p envoyx.EncodeParams, rt stri
|
||||
|
||||
case types.TriggerResourceType:
|
||||
return e.encodeTriggers(ctx, p, s, nodes, tree)
|
||||
default:
|
||||
return e.encode(ctx, p, s, rt, nodes, tree)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// // // // // // // // // // // // // // // // // // // // // // // // //
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
package envoy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/automation/types"
|
||||
"github.com/cortezaproject/corteza/server/pkg/envoyx"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
)
|
||||
|
||||
func (e StoreEncoder) encode(ctx context.Context, p envoyx.EncodeParams, s store.Storer, rt string, nn envoyx.NodeSet, tree envoyx.Traverser) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (e StoreEncoder) setWorkflowDefaults(res *types.Workflow) (err error) {
|
||||
if res.CreatedAt.IsZero() {
|
||||
res.CreatedAt = time.Now()
|
||||
|
||||
+41
-43
@@ -86,29 +86,6 @@ func (d *auxYamlDoc) UnmarshalYAML(n *yaml.Node) (err error) {
|
||||
}
|
||||
return err
|
||||
|
||||
// Access control nodes
|
||||
case "allow":
|
||||
aux, err = unmarshalAllowNode(v)
|
||||
d.nodes = append(d.nodes, aux...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case "deny":
|
||||
aux, err = unmarshalDenyNode(v)
|
||||
d.nodes = append(d.nodes, aux...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Resource translation nodes
|
||||
case "locale", "translation", "translations", "i18n":
|
||||
aux, err = unmarshalLocaleNode(v)
|
||||
d.nodes = append(d.nodes, aux...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Offload to custom handlers
|
||||
default:
|
||||
aux, err = d.unmarshalYAML(kv, v)
|
||||
@@ -741,10 +718,28 @@ func unmarshalDenyNode(n *yaml.Node) (out envoyx.NodeSet, err error) {
|
||||
|
||||
func unmarshalRBACNode(n *yaml.Node, acc rbac.Access) (out envoyx.NodeSet, err error) {
|
||||
if y7s.IsMapping(n.Content[1]) {
|
||||
return unmarshalNestedRBACNode(n, acc)
|
||||
out, err = unmarshalNestedRBACNode(n, acc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
out, err = unmarshalFlatRBACNode(n, acc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return unmarshalFlatRBACNode(n, acc)
|
||||
for _, o := range out {
|
||||
for _, r := range o.References {
|
||||
if r.Scope.IsEmpty() {
|
||||
continue
|
||||
}
|
||||
o.Scope = r.Scope
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// unmarshalNestedRBACNode handles RBAC rules when they are nested inside a resource
|
||||
@@ -765,25 +760,28 @@ func unmarshalRBACNode(n *yaml.Node, acc rbac.Access) (out envoyx.NodeSet, err e
|
||||
func unmarshalNestedRBACNode(n *yaml.Node, acc rbac.Access) (out envoyx.NodeSet, err error) {
|
||||
// Handles role
|
||||
return out, y7s.EachMap(n, func(role, perm *yaml.Node) error {
|
||||
// Handles operation
|
||||
return y7s.EachMap(perm, func(res, op *yaml.Node) error {
|
||||
out = append(out, &envoyx.Node{
|
||||
Resource: &rbac.Rule{
|
||||
Resource: res.Value,
|
||||
Operation: op.Value,
|
||||
Access: acc,
|
||||
},
|
||||
ResourceType: rbac.RuleResourceType,
|
||||
References: envoyx.MergeRefs(
|
||||
map[string]envoyx.Ref{"RoleID": {
|
||||
// Providing resource type as plain text to reduce cross component references
|
||||
ResourceType: "corteza::system:role",
|
||||
Identifiers: envoyx.MakeIdentifiers(role.Value),
|
||||
}},
|
||||
envoyx.SplitResourceIdentifier(res.Value),
|
||||
),
|
||||
// Handles operations
|
||||
return y7s.EachMap(perm, func(res, ops *yaml.Node) error {
|
||||
// Handle operation (one RBAC rule per op)
|
||||
return y7s.EachSeq(ops, func(op *yaml.Node) error {
|
||||
out = append(out, &envoyx.Node{
|
||||
Resource: &rbac.Rule{
|
||||
Resource: res.Value,
|
||||
Operation: op.Value,
|
||||
Access: acc,
|
||||
},
|
||||
ResourceType: rbac.RuleResourceType,
|
||||
References: envoyx.MergeRefs(
|
||||
map[string]envoyx.Ref{"RoleID": {
|
||||
// Providing resource type as plain text to reduce cross component references
|
||||
ResourceType: "corteza::system:role",
|
||||
Identifiers: envoyx.MakeIdentifiers(role.Value),
|
||||
}},
|
||||
envoyx.SplitResourceIdentifier(res.Value),
|
||||
),
|
||||
})
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
+8
-2
@@ -73,8 +73,14 @@ func (e YamlEncoder) Encode(ctx context.Context, p envoyx.EncodeParams, rt strin
|
||||
return
|
||||
}
|
||||
default:
|
||||
// When this encoder doesn't handle any node it shouldn't write anything;
|
||||
// this just removes the need for an extra check at the end.
|
||||
out, err = e.encode(ctx, out, p, rt, nodes, tt)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Don't output nil values since that will produce broken yaml docs
|
||||
if out == nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package envoy
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/envoyx"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func (e YamlEncoder) encode(ctx context.Context, base *yaml.Node, p envoyx.EncodeParams, rt string, nodes envoyx.NodeSet, tt envoyx.Traverser) (out *yaml.Node, err error) {
|
||||
return
|
||||
}
|
||||
@@ -89,9 +89,9 @@ func (e StoreEncoder) Encode(ctx context.Context, p envoyx.EncodeParams, rt stri
|
||||
case types.{{.expIdent}}ResourceType:
|
||||
return e.encode{{.expIdent}}s(ctx, p, s, nodes, tree)
|
||||
{{ end -}}
|
||||
default:
|
||||
return e.encode(ctx, p, s, rt, nodes, tree)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
{{- range .resources }}
|
||||
|
||||
@@ -36,6 +36,7 @@ func SplitResourceIdentifier(ref string) (out map[string]Ref) {
|
||||
|
||||
|
||||
case "corteza::{{$rootCmp.ident}}:{{.ident}}":
|
||||
scope := Scope{}
|
||||
{{$res := .}}
|
||||
{{range $i, $p := .parents}}
|
||||
if gRef(pp, {{$i}}) == "" {
|
||||
@@ -48,9 +49,17 @@ func SplitResourceIdentifier(ref string) (out map[string]Ref) {
|
||||
{{ end }}
|
||||
|
||||
{{ if eq $p.handle $cmp.ident }}
|
||||
out["{{$i}}"] = Ref{
|
||||
{{ if and (eq $rootCmp.ident "compose") (eq $i 0) }}
|
||||
aux := gRef(pp, {{ $i }})
|
||||
if aux != "" {
|
||||
scope.ResourceType = "corteza::compose:namespace"
|
||||
scope.Identifiers = MakeIdentifiers(aux)
|
||||
}
|
||||
{{ end }}
|
||||
out["Path.{{$i}}"] = Ref{
|
||||
ResourceType: "{{$cmp.fqrt}}",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, {{ $i }})),
|
||||
Scope: scope,
|
||||
}
|
||||
{{break}}
|
||||
{{ end }}
|
||||
@@ -60,9 +69,14 @@ func SplitResourceIdentifier(ref string) (out map[string]Ref) {
|
||||
if gRef(pp, {{len .parents}}) == "" {
|
||||
return
|
||||
}
|
||||
out["{{len .parents}}"] = Ref{
|
||||
{{if eq .ident "namespace"}}
|
||||
scope.ResourceType = "{{.fqrt}}"
|
||||
scope.Identifiers = MakeIdentifiers(gRef(pp, {{len .parents}}))
|
||||
{{end}}
|
||||
out["Path.{{len .parents}}"] = Ref{
|
||||
ResourceType: "{{.fqrt}}",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, {{len .parents}})),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
{{ end }}
|
||||
|
||||
@@ -91,6 +91,7 @@ func (d *auxYamlDoc) UnmarshalYAML(n *yaml.Node) (err error) {
|
||||
return err
|
||||
{{ end }}
|
||||
|
||||
{{ if eq .componentIdent "system" }}
|
||||
// Access control nodes
|
||||
case "allow":
|
||||
aux, err = unmarshalAllowNode(v)
|
||||
@@ -113,6 +114,7 @@ func (d *auxYamlDoc) UnmarshalYAML(n *yaml.Node) (err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
// Offload to custom handlers
|
||||
default:
|
||||
@@ -600,10 +602,28 @@ func unmarshalDenyNode(n *yaml.Node) (out envoyx.NodeSet, err error) {
|
||||
|
||||
func unmarshalRBACNode(n *yaml.Node, acc rbac.Access) (out envoyx.NodeSet, err error) {
|
||||
if y7s.IsMapping(n.Content[1]) {
|
||||
return unmarshalNestedRBACNode(n, acc)
|
||||
out, err = unmarshalNestedRBACNode(n, acc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
out, err = unmarshalFlatRBACNode(n, acc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return unmarshalFlatRBACNode(n, acc)
|
||||
for _, o := range out {
|
||||
for _, r := range o.References {
|
||||
if r.Scope.IsEmpty() {
|
||||
continue
|
||||
}
|
||||
o.Scope = r.Scope
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// unmarshalNestedRBACNode handles RBAC rules when they are nested inside a resource
|
||||
@@ -624,25 +644,28 @@ func unmarshalRBACNode(n *yaml.Node, acc rbac.Access) (out envoyx.NodeSet, err e
|
||||
func unmarshalNestedRBACNode(n *yaml.Node, acc rbac.Access) (out envoyx.NodeSet, err error) {
|
||||
// Handles role
|
||||
return out, y7s.EachMap(n, func(role, perm *yaml.Node) error {
|
||||
// Handles operation
|
||||
return y7s.EachMap(perm, func(res, op *yaml.Node) error {
|
||||
out = append(out, &envoyx.Node{
|
||||
Resource: &rbac.Rule{
|
||||
Resource: res.Value,
|
||||
Operation: op.Value,
|
||||
Access: acc,
|
||||
},
|
||||
ResourceType: rbac.RuleResourceType,
|
||||
References: envoyx.MergeRefs(
|
||||
map[string]envoyx.Ref{"RoleID": {
|
||||
// Providing resource type as plain text to reduce cross component references
|
||||
ResourceType: "corteza::system:role",
|
||||
Identifiers: envoyx.MakeIdentifiers(role.Value),
|
||||
}},
|
||||
envoyx.SplitResourceIdentifier(res.Value),
|
||||
),
|
||||
// Handles operations
|
||||
return y7s.EachMap(perm, func(res, ops *yaml.Node) error {
|
||||
// Handle operation (one RBAC rule per op)
|
||||
return y7s.EachSeq(ops, func(op *yaml.Node) error {
|
||||
out = append(out, &envoyx.Node{
|
||||
Resource: &rbac.Rule{
|
||||
Resource: res.Value,
|
||||
Operation: op.Value,
|
||||
Access: acc,
|
||||
},
|
||||
ResourceType: rbac.RuleResourceType,
|
||||
References: envoyx.MergeRefs(
|
||||
map[string]envoyx.Ref{"RoleID": {
|
||||
// Providing resource type as plain text to reduce cross component references
|
||||
ResourceType: "corteza::system:role",
|
||||
Identifiers: envoyx.MakeIdentifiers(role.Value),
|
||||
}},
|
||||
envoyx.SplitResourceIdentifier(res.Value),
|
||||
),
|
||||
})
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -67,8 +67,14 @@ func (e YamlEncoder) Encode(ctx context.Context, p envoyx.EncodeParams, rt strin
|
||||
}
|
||||
{{ end -}}
|
||||
default:
|
||||
// When this encoder doesn't handle any node it shouldn't write anything;
|
||||
// this just removes the need for an extra check at the end.
|
||||
out, err = e.encode(ctx, out, p, rt, nodes, tt)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Don't output nil values since that will produce broken yaml docs
|
||||
if out == nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -32,9 +32,9 @@ import (
|
||||
[
|
||||
{
|
||||
template: "gocode/envoy/rbac_rules_parse.go.tpl"
|
||||
output: "pkg/envoy/resource/rbac_rules_parse.gen.go"
|
||||
output: "pkg/envoyx/rbac_rules_parse.gen.go"
|
||||
payload: {
|
||||
package: "resource"
|
||||
package: "envoyx"
|
||||
imports: [
|
||||
for cmp in app.corteza.components {
|
||||
"\(cmp.ident)Types \"github.com/cortezaproject/corteza/server/\(cmp.ident)/types\""
|
||||
|
||||
Generated
+2
-2
@@ -98,9 +98,9 @@ func (e StoreEncoder) Encode(ctx context.Context, p envoyx.EncodeParams, rt stri
|
||||
|
||||
case types.PageResourceType:
|
||||
return e.encodePages(ctx, p, s, nodes, tree)
|
||||
default:
|
||||
return e.encode(ctx, p, s, rt, nodes, tree)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// // // // // // // // // // // // // // // // // // // // // // // // //
|
||||
|
||||
@@ -12,6 +12,10 @@ import (
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
)
|
||||
|
||||
func (e StoreEncoder) encode(ctx context.Context, p envoyx.EncodeParams, s store.Storer, rt string, nn envoyx.NodeSet, tree envoyx.Traverser) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (e StoreEncoder) setChartDefaults(res *types.Chart) (err error) {
|
||||
if res.CreatedAt.IsZero() {
|
||||
res.CreatedAt = time.Now()
|
||||
|
||||
Generated
+41
-43
@@ -127,29 +127,6 @@ func (d *auxYamlDoc) UnmarshalYAML(n *yaml.Node) (err error) {
|
||||
}
|
||||
return err
|
||||
|
||||
// Access control nodes
|
||||
case "allow":
|
||||
aux, err = unmarshalAllowNode(v)
|
||||
d.nodes = append(d.nodes, aux...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
case "deny":
|
||||
aux, err = unmarshalDenyNode(v)
|
||||
d.nodes = append(d.nodes, aux...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Resource translation nodes
|
||||
case "locale", "translation", "translations", "i18n":
|
||||
aux, err = unmarshalLocaleNode(v)
|
||||
d.nodes = append(d.nodes, aux...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Offload to custom handlers
|
||||
default:
|
||||
aux, err = d.unmarshalYAML(kv, v)
|
||||
@@ -1803,10 +1780,28 @@ func unmarshalDenyNode(n *yaml.Node) (out envoyx.NodeSet, err error) {
|
||||
|
||||
func unmarshalRBACNode(n *yaml.Node, acc rbac.Access) (out envoyx.NodeSet, err error) {
|
||||
if y7s.IsMapping(n.Content[1]) {
|
||||
return unmarshalNestedRBACNode(n, acc)
|
||||
out, err = unmarshalNestedRBACNode(n, acc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
out, err = unmarshalFlatRBACNode(n, acc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return unmarshalFlatRBACNode(n, acc)
|
||||
for _, o := range out {
|
||||
for _, r := range o.References {
|
||||
if r.Scope.IsEmpty() {
|
||||
continue
|
||||
}
|
||||
o.Scope = r.Scope
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// unmarshalNestedRBACNode handles RBAC rules when they are nested inside a resource
|
||||
@@ -1827,25 +1822,28 @@ func unmarshalRBACNode(n *yaml.Node, acc rbac.Access) (out envoyx.NodeSet, err e
|
||||
func unmarshalNestedRBACNode(n *yaml.Node, acc rbac.Access) (out envoyx.NodeSet, err error) {
|
||||
// Handles role
|
||||
return out, y7s.EachMap(n, func(role, perm *yaml.Node) error {
|
||||
// Handles operation
|
||||
return y7s.EachMap(perm, func(res, op *yaml.Node) error {
|
||||
out = append(out, &envoyx.Node{
|
||||
Resource: &rbac.Rule{
|
||||
Resource: res.Value,
|
||||
Operation: op.Value,
|
||||
Access: acc,
|
||||
},
|
||||
ResourceType: rbac.RuleResourceType,
|
||||
References: envoyx.MergeRefs(
|
||||
map[string]envoyx.Ref{"RoleID": {
|
||||
// Providing resource type as plain text to reduce cross component references
|
||||
ResourceType: "corteza::system:role",
|
||||
Identifiers: envoyx.MakeIdentifiers(role.Value),
|
||||
}},
|
||||
envoyx.SplitResourceIdentifier(res.Value),
|
||||
),
|
||||
// Handles operations
|
||||
return y7s.EachMap(perm, func(res, ops *yaml.Node) error {
|
||||
// Handle operation (one RBAC rule per op)
|
||||
return y7s.EachSeq(ops, func(op *yaml.Node) error {
|
||||
out = append(out, &envoyx.Node{
|
||||
Resource: &rbac.Rule{
|
||||
Resource: res.Value,
|
||||
Operation: op.Value,
|
||||
Access: acc,
|
||||
},
|
||||
ResourceType: rbac.RuleResourceType,
|
||||
References: envoyx.MergeRefs(
|
||||
map[string]envoyx.Ref{"RoleID": {
|
||||
// Providing resource type as plain text to reduce cross component references
|
||||
ResourceType: "corteza::system:role",
|
||||
Identifiers: envoyx.MakeIdentifiers(role.Value),
|
||||
}},
|
||||
envoyx.SplitResourceIdentifier(res.Value),
|
||||
),
|
||||
})
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
Generated
+8
-2
@@ -103,8 +103,14 @@ func (e YamlEncoder) Encode(ctx context.Context, p envoyx.EncodeParams, rt strin
|
||||
}
|
||||
|
||||
default:
|
||||
// When this encoder doesn't handle any node it shouldn't write anything;
|
||||
// this just removes the need for an extra check at the end.
|
||||
out, err = e.encode(ctx, out, p, rt, nodes, tt)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Don't output nil values since that will produce broken yaml docs
|
||||
if out == nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,13 @@ import (
|
||||
"github.com/cortezaproject/corteza/server/compose/types"
|
||||
"github.com/cortezaproject/corteza/server/pkg/envoyx"
|
||||
"github.com/cortezaproject/corteza/server/pkg/y7s"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func (e YamlEncoder) encode(ctx context.Context, base *yaml.Node, p envoyx.EncodeParams, rt string, nodes envoyx.NodeSet, tt envoyx.Traverser) (out *yaml.Node, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (e YamlEncoder) encodeChartConfigC(ctx context.Context, p envoyx.EncodeParams, tt envoyx.Traverser, n *envoyx.Node, chart *types.Chart, cfg types.ChartConfig) (_ any, err error) {
|
||||
|
||||
reports, _ := y7s.MakeSeq()
|
||||
|
||||
+1
-2
@@ -8,12 +8,11 @@ package envoyx
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
automationTypes "github.com/cortezaproject/corteza/server/automation/types"
|
||||
composeTypes "github.com/cortezaproject/corteza/server/compose/types"
|
||||
federationTypes "github.com/cortezaproject/corteza/server/federation/types"
|
||||
systemTypes "github.com/cortezaproject/corteza/server/system/types"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Parse generates resource setting logic for each resource
|
||||
|
||||
@@ -69,7 +69,7 @@ func RBACRulesForNodes(rr rbac.RuleSet, nn ...*Node) (rules NodeSet, err error)
|
||||
ref.Scope = n.Scope
|
||||
|
||||
// @todo make the thing not a pointer
|
||||
rf[fmt.Sprintf("Resource.%d", i)] = *ref
|
||||
rf[fmt.Sprintf("Path.%d", i)] = *ref
|
||||
}
|
||||
|
||||
// Ref to the rule
|
||||
@@ -93,7 +93,7 @@ func RBACRulesForNodes(rr rbac.RuleSet, nn ...*Node) (rules NodeSet, err error)
|
||||
if dups[r.RoleID][r.Resource] == nil {
|
||||
dups[r.RoleID][r.Resource] = make(map[string]bool)
|
||||
}
|
||||
dups[r.RoleID][r.Resource][r.Resource] = true
|
||||
dups[r.RoleID][r.Resource][r.Operation] = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Generated
+183
-103
@@ -30,468 +30,548 @@ func SplitResourceIdentifier(ref string) (out map[string]Ref) {
|
||||
switch rt {
|
||||
|
||||
case "corteza::system:apigwFilter":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::system:apigw-filter",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::system:apigwRoute":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::system:apigw-route",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::system:application":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::system:application",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::system:attachment":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::system:attachment",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::system:authClient":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::system:auth-client",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::system:authConfirmedClient":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::system:auth-confirmed-client",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::system:authOa2token":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::system:auth-oa2token",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::system:authSession":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::system:auth-session",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::system:credential":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::system:credential",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::system:dalConnection":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::system:dal-connection",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::system:dalSensitivityLevel":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::system:dal-sensitivity-level",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::system:dataPrivacyRequest":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::system:data-privacy-request",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::system:dataPrivacyRequestComment":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::system:data-privacy-request-comment",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::system:queue":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::system:queue",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::system:queueMessage":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::system:queue-message",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::system:reminder":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::system:reminder",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::system:report":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::system:report",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::system:resourceTranslation":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::system:resource-translation",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::system:role":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::system:role",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::system:roleMember":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::system:role-member",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::system:settingValue":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::system:settings",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::system:template":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::system:template",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::system:user":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::system:user",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::compose:attachment":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::compose:attachment",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::compose:chart":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
|
||||
out["0"] = Ref{
|
||||
aux := gRef(pp, 0)
|
||||
if aux != "" {
|
||||
scope.ResourceType = "corteza::compose:namespace"
|
||||
scope.Identifiers = MakeIdentifiers(aux)
|
||||
}
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::compose:namespace",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
if gRef(pp, 1) == "" {
|
||||
return
|
||||
}
|
||||
out["1"] = Ref{
|
||||
|
||||
out["Path.1"] = Ref{
|
||||
ResourceType: "corteza::compose:chart",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 1)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::compose:module":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
|
||||
out["0"] = Ref{
|
||||
aux := gRef(pp, 0)
|
||||
if aux != "" {
|
||||
scope.ResourceType = "corteza::compose:namespace"
|
||||
scope.Identifiers = MakeIdentifiers(aux)
|
||||
}
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::compose:namespace",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
if gRef(pp, 1) == "" {
|
||||
return
|
||||
}
|
||||
out["1"] = Ref{
|
||||
|
||||
out["Path.1"] = Ref{
|
||||
ResourceType: "corteza::compose:module",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 1)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::compose:moduleField":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
|
||||
out["0"] = Ref{
|
||||
aux := gRef(pp, 0)
|
||||
if aux != "" {
|
||||
scope.ResourceType = "corteza::compose:namespace"
|
||||
scope.Identifiers = MakeIdentifiers(aux)
|
||||
}
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::compose:namespace",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
if gRef(pp, 1) == "" {
|
||||
return
|
||||
}
|
||||
|
||||
out["1"] = Ref{
|
||||
out["Path.1"] = Ref{
|
||||
ResourceType: "corteza::compose:module",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 1)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
if gRef(pp, 2) == "" {
|
||||
return
|
||||
}
|
||||
out["2"] = Ref{
|
||||
|
||||
out["Path.2"] = Ref{
|
||||
ResourceType: "corteza::compose:module-field",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 2)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::compose:namespace":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
scope.ResourceType = "corteza::compose:namespace"
|
||||
scope.Identifiers = MakeIdentifiers(gRef(pp, 0))
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::compose:namespace",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::compose:page":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
|
||||
out["0"] = Ref{
|
||||
aux := gRef(pp, 0)
|
||||
if aux != "" {
|
||||
scope.ResourceType = "corteza::compose:namespace"
|
||||
scope.Identifiers = MakeIdentifiers(aux)
|
||||
}
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::compose:namespace",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
if gRef(pp, 1) == "" {
|
||||
return
|
||||
}
|
||||
out["1"] = Ref{
|
||||
|
||||
out["Path.1"] = Ref{
|
||||
ResourceType: "corteza::compose:page",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 1)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::compose:record":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
|
||||
out["0"] = Ref{
|
||||
aux := gRef(pp, 0)
|
||||
if aux != "" {
|
||||
scope.ResourceType = "corteza::compose:namespace"
|
||||
scope.Identifiers = MakeIdentifiers(aux)
|
||||
}
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::compose:namespace",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
if gRef(pp, 1) == "" {
|
||||
return
|
||||
}
|
||||
|
||||
out["1"] = Ref{
|
||||
out["Path.1"] = Ref{
|
||||
ResourceType: "corteza::compose:module",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 1)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
if gRef(pp, 2) == "" {
|
||||
return
|
||||
}
|
||||
out["2"] = Ref{
|
||||
|
||||
out["Path.2"] = Ref{
|
||||
ResourceType: "corteza::compose:record",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 2)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::compose:recordRevision":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::compose:record-revision",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::automation:session":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::automation:session",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::automation:trigger":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::automation:trigger",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
case "corteza::automation:workflow":
|
||||
scope := Scope{}
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
|
||||
out["Path.0"] = Ref{
|
||||
ResourceType: "corteza::automation:workflow",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
}
|
||||
|
||||
case "corteza::federation:exposedModule":
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
|
||||
if gRef(pp, 1) == "" {
|
||||
return
|
||||
}
|
||||
out["1"] = Ref{
|
||||
ResourceType: "corteza::federation:exposed-module",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 1)),
|
||||
}
|
||||
|
||||
case "corteza::federation:moduleMapping":
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
|
||||
if gRef(pp, 1) == "" {
|
||||
return
|
||||
}
|
||||
out["1"] = Ref{
|
||||
ResourceType: "corteza::federation:module-mapping",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 1)),
|
||||
}
|
||||
|
||||
case "corteza::federation:node":
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
ResourceType: "corteza::federation:node",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
}
|
||||
|
||||
case "corteza::federation:nodeSync":
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
out["0"] = Ref{
|
||||
ResourceType: "corteza::federation:node-sync",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 0)),
|
||||
}
|
||||
|
||||
case "corteza::federation:sharedModule":
|
||||
|
||||
if gRef(pp, 0) == "" {
|
||||
return
|
||||
}
|
||||
|
||||
if gRef(pp, 1) == "" {
|
||||
return
|
||||
}
|
||||
out["1"] = Ref{
|
||||
ResourceType: "corteza::federation:shared-module",
|
||||
Identifiers: MakeIdentifiers(gRef(pp, 1)),
|
||||
Scope: scope,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+13
-1
@@ -64,6 +64,18 @@ func (set RuleSet) FilterAccess(a Access) (out RuleSet) {
|
||||
return out
|
||||
}
|
||||
|
||||
func (set RuleSet) FilterOperation(op string) (out RuleSet) {
|
||||
out = make(RuleSet, 0, len(set))
|
||||
|
||||
for _, s := range set {
|
||||
if s.Operation == op {
|
||||
out = append(out, s)
|
||||
}
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// FilterResource returns rules that match given list of resources
|
||||
// Wildcards are not used!
|
||||
//
|
||||
@@ -117,7 +129,7 @@ func (u *Rule) setValue(name string, pos uint, v any) (err error) {
|
||||
pp := strings.Split(name, ".")
|
||||
|
||||
switch pp[0] {
|
||||
case "resource", "Resource":
|
||||
case "resource", "Resource", "Path", "path":
|
||||
ix, err := strconv.ParseUint(pp[1], 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
Generated
+2
-2
@@ -131,9 +131,9 @@ func (e StoreEncoder) Encode(ctx context.Context, p envoyx.EncodeParams, rt stri
|
||||
|
||||
case types.DalSensitivityLevelResourceType:
|
||||
return e.encodeDalSensitivityLevels(ctx, p, s, nodes, tree)
|
||||
default:
|
||||
return e.encode(ctx, p, s, rt, nodes, tree)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// // // // // // // // // // // // // // // // // // // // // // // // //
|
||||
|
||||
@@ -5,11 +5,26 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/envoyx"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rbac"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
)
|
||||
|
||||
func (e StoreEncoder) prepare(ctx context.Context, p envoyx.EncodeParams, s store.Storer, rt string, nn envoyx.NodeSet) (err error) {
|
||||
switch rt {
|
||||
case rbac.RuleResourceType:
|
||||
return e.prepareRbacRule(ctx, p, s, nn)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (e StoreEncoder) encode(ctx context.Context, p envoyx.EncodeParams, s store.Storer, rt string, nn envoyx.NodeSet, tree envoyx.Traverser) (err error) {
|
||||
switch rt {
|
||||
case rbac.RuleResourceType:
|
||||
return e.encodeRbacRules(ctx, p, s, nn, tree)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
package envoy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/envoyx"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rbac"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
)
|
||||
|
||||
func (e StoreEncoder) prepareRbacRule(ctx context.Context, p envoyx.EncodeParams, s store.Storer, nn envoyx.NodeSet) (err error) {
|
||||
// @todo existing RBAC rules?
|
||||
for _, n := range nn {
|
||||
if n.Resource == nil {
|
||||
panic("unexpected state: cannot call prepareRbacRule with nodes without a defined Resource")
|
||||
}
|
||||
|
||||
res, ok := n.Resource.(*rbac.Rule)
|
||||
if !ok {
|
||||
panic("unexpected resource type: node expecting type of RbacRule")
|
||||
}
|
||||
|
||||
// Run expressions on the nodes
|
||||
err = e.runEvals(ctx, false, n)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// @todo merge conflicts if we do existing assertion
|
||||
|
||||
n.Resource = res
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// encodeRbacRules encodes a set of resource into the database
|
||||
func (e StoreEncoder) encodeRbacRules(ctx context.Context, p envoyx.EncodeParams, s store.Storer, nn envoyx.NodeSet, tree envoyx.Traverser) (err error) {
|
||||
for _, n := range nn {
|
||||
err = e.encodeRbacRule(ctx, p, s, n, tree)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// encodeRbacRule encodes the resource into the database
|
||||
func (e StoreEncoder) encodeRbacRule(ctx context.Context, p envoyx.EncodeParams, s store.Storer, n *envoyx.Node, tree envoyx.Traverser) (err error) {
|
||||
// Grab dependency references
|
||||
var auxID uint64
|
||||
for fieldLabel, ref := range n.References {
|
||||
rn := tree.ParentForRef(n, ref)
|
||||
if rn == nil {
|
||||
err = fmt.Errorf("missing node for ref %v", ref)
|
||||
return
|
||||
}
|
||||
|
||||
auxID = rn.Resource.GetID()
|
||||
if auxID == 0 {
|
||||
err = fmt.Errorf("related resource doesn't provide an ID")
|
||||
return
|
||||
}
|
||||
|
||||
err = n.Resource.SetValue(fieldLabel, 0, auxID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Flush to the DB
|
||||
err = store.UpsertRbacRule(ctx, s, n.Resource.(*rbac.Rule))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
Generated
+41
-20
@@ -3207,10 +3207,28 @@ func unmarshalDenyNode(n *yaml.Node) (out envoyx.NodeSet, err error) {
|
||||
|
||||
func unmarshalRBACNode(n *yaml.Node, acc rbac.Access) (out envoyx.NodeSet, err error) {
|
||||
if y7s.IsMapping(n.Content[1]) {
|
||||
return unmarshalNestedRBACNode(n, acc)
|
||||
out, err = unmarshalNestedRBACNode(n, acc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
out, err = unmarshalFlatRBACNode(n, acc)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return unmarshalFlatRBACNode(n, acc)
|
||||
for _, o := range out {
|
||||
for _, r := range o.References {
|
||||
if r.Scope.IsEmpty() {
|
||||
continue
|
||||
}
|
||||
o.Scope = r.Scope
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// unmarshalNestedRBACNode handles RBAC rules when they are nested inside a resource
|
||||
@@ -3231,25 +3249,28 @@ func unmarshalRBACNode(n *yaml.Node, acc rbac.Access) (out envoyx.NodeSet, err e
|
||||
func unmarshalNestedRBACNode(n *yaml.Node, acc rbac.Access) (out envoyx.NodeSet, err error) {
|
||||
// Handles role
|
||||
return out, y7s.EachMap(n, func(role, perm *yaml.Node) error {
|
||||
// Handles operation
|
||||
return y7s.EachMap(perm, func(res, op *yaml.Node) error {
|
||||
out = append(out, &envoyx.Node{
|
||||
Resource: &rbac.Rule{
|
||||
Resource: res.Value,
|
||||
Operation: op.Value,
|
||||
Access: acc,
|
||||
},
|
||||
ResourceType: rbac.RuleResourceType,
|
||||
References: envoyx.MergeRefs(
|
||||
map[string]envoyx.Ref{"RoleID": {
|
||||
// Providing resource type as plain text to reduce cross component references
|
||||
ResourceType: "corteza::system:role",
|
||||
Identifiers: envoyx.MakeIdentifiers(role.Value),
|
||||
}},
|
||||
envoyx.SplitResourceIdentifier(res.Value),
|
||||
),
|
||||
// Handles operations
|
||||
return y7s.EachMap(perm, func(res, ops *yaml.Node) error {
|
||||
// Handle operation (one RBAC rule per op)
|
||||
return y7s.EachSeq(ops, func(op *yaml.Node) error {
|
||||
out = append(out, &envoyx.Node{
|
||||
Resource: &rbac.Rule{
|
||||
Resource: res.Value,
|
||||
Operation: op.Value,
|
||||
Access: acc,
|
||||
},
|
||||
ResourceType: rbac.RuleResourceType,
|
||||
References: envoyx.MergeRefs(
|
||||
map[string]envoyx.Ref{"RoleID": {
|
||||
// Providing resource type as plain text to reduce cross component references
|
||||
ResourceType: "corteza::system:role",
|
||||
Identifiers: envoyx.MakeIdentifiers(role.Value),
|
||||
}},
|
||||
envoyx.SplitResourceIdentifier(res.Value),
|
||||
),
|
||||
})
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
Generated
+8
-2
@@ -157,8 +157,14 @@ func (e YamlEncoder) Encode(ctx context.Context, p envoyx.EncodeParams, rt strin
|
||||
return
|
||||
}
|
||||
default:
|
||||
// When this encoder doesn't handle any node it shouldn't write anything;
|
||||
// this just removes the need for an extra check at the end.
|
||||
out, err = e.encode(ctx, out, p, rt, nodes, tt)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Don't output nil values since that will produce broken yaml docs
|
||||
if out == nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -3,13 +3,208 @@ package envoy
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/pkg/envoyx"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rbac"
|
||||
"github.com/cortezaproject/corteza/server/pkg/y7s"
|
||||
"github.com/cortezaproject/corteza/server/system/types"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type (
|
||||
// Wrapper to avoid constant type casting for role nodes
|
||||
rbacRuleWrap struct {
|
||||
node *envoyx.Node
|
||||
rule *rbac.Rule
|
||||
}
|
||||
|
||||
// Wrapper to keep role and rules together
|
||||
rbacRuleRoleWrap struct {
|
||||
rules []rbacRuleWrap
|
||||
roleNode *envoyx.Node
|
||||
role *types.Role
|
||||
}
|
||||
)
|
||||
|
||||
func (e YamlEncoder) encode(ctx context.Context, base *yaml.Node, p envoyx.EncodeParams, rt string, nodes envoyx.NodeSet, tt envoyx.Traverser) (out *yaml.Node, err error) {
|
||||
switch rt {
|
||||
case rbac.RuleResourceType:
|
||||
return e.encodeRbacRules(ctx, base, p, nodes, tt)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (e YamlEncoder) encodeRbacRules(ctx context.Context, base *yaml.Node, p envoyx.EncodeParams, nodes envoyx.NodeSet, tt envoyx.Traverser) (out *yaml.Node, err error) {
|
||||
err = e.resolveRulePathDeps(ctx, tt, nodes)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Batch by access (allow, deny)
|
||||
allows := make([]rbacRuleWrap, 0, len(nodes))
|
||||
denies := make([]rbacRuleWrap, 0, len(nodes))
|
||||
for _, n := range nodes {
|
||||
r := n.Resource.(*rbac.Rule)
|
||||
if r.Access == rbac.Allow {
|
||||
allows = append(allows, rbacRuleWrap{
|
||||
node: n,
|
||||
rule: r,
|
||||
})
|
||||
} else {
|
||||
denies = append(denies, rbacRuleWrap{
|
||||
node: n,
|
||||
rule: r,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Encode allows
|
||||
var aux *yaml.Node
|
||||
aux, err = e.encodeRbacRulesByRole(p, allows, tt)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
out = base
|
||||
out, err = y7s.AddMap(out, "allow", aux)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Encode denies
|
||||
aux, err = e.encodeRbacRulesByRole(p, denies, tt)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
out, err = y7s.AddMap(out, "deny", aux)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (e YamlEncoder) encodeRbacRulesByRole(p envoyx.EncodeParams, rules []rbacRuleWrap, tt envoyx.Traverser) (out *yaml.Node, err error) {
|
||||
// Batch by role; make sure to keep the multiple identifier thing in mind
|
||||
byRole := make(map[string]rbacRuleRoleWrap)
|
||||
for _, r := range rules {
|
||||
role := r.node.References["RoleID"]
|
||||
aux := rbacRuleRoleWrap{}
|
||||
ok := false
|
||||
|
||||
// Check if an identifier already exists
|
||||
for _, ident := range role.Identifiers.Slice {
|
||||
aux, ok = byRole[ident]
|
||||
if ok {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// If not, create a new entry and resolve the role
|
||||
if !ok {
|
||||
aux.roleNode = tt.ParentForRef(r.node, role)
|
||||
if aux.roleNode != nil {
|
||||
aux.role = aux.roleNode.Resource.(*types.Role)
|
||||
}
|
||||
}
|
||||
|
||||
// Add the rule to the batch and update potentially missing identifiers
|
||||
aux.rules = append(aux.rules, r)
|
||||
for _, ident := range role.Identifiers.Slice {
|
||||
byRole[ident] = aux
|
||||
}
|
||||
}
|
||||
|
||||
// Encode
|
||||
var aux *yaml.Node
|
||||
for _, r := range byRole {
|
||||
aux, err = e.encodeRbacRulesByResource(p, r.rules)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
out, err = y7s.AddMap(out,
|
||||
r.roleNode.Identifiers.FriendlyIdentifier(), aux,
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (e YamlEncoder) encodeRbacRulesByResource(p envoyx.EncodeParams, rules []rbacRuleWrap) (out *yaml.Node, err error) {
|
||||
byResource := make(map[string][]rbacRuleWrap)
|
||||
|
||||
// Batch
|
||||
for _, r := range rules {
|
||||
byResource[r.rule.Resource] = append(byResource[r.rule.Resource], r)
|
||||
}
|
||||
|
||||
// Encode
|
||||
var aux *yaml.Node
|
||||
for resource, rules := range byResource {
|
||||
aux, err = e.encodeRbacRuleOperations(p, rules)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
out, err = y7s.AddMap(out, resource, aux)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (e YamlEncoder) encodeRbacRuleOperations(p envoyx.EncodeParams, rules []rbacRuleWrap) (out *yaml.Node, err error) {
|
||||
ops, _ := y7s.MakeSeq()
|
||||
|
||||
for _, r := range rules {
|
||||
ops, err = y7s.AddSeq(ops, r.rule.Operation)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return ops, nil
|
||||
}
|
||||
|
||||
func (e YamlEncoder) resolveRulePathDeps(ctx context.Context, tt envoyx.Traverser, nodes envoyx.NodeSet) (err error) {
|
||||
for _, n := range nodes {
|
||||
|
||||
var auxIdent string
|
||||
for fieldLabel, ref := range n.References {
|
||||
// Only resolve path refs; others are done later on
|
||||
if !strings.Contains(fieldLabel, "Path.") {
|
||||
continue
|
||||
}
|
||||
|
||||
rn := tt.ParentForRef(n, ref)
|
||||
if rn == nil {
|
||||
err = fmt.Errorf("missing node for ref %v", ref)
|
||||
return
|
||||
}
|
||||
|
||||
auxIdent = rn.Identifiers.FriendlyIdentifier()
|
||||
if auxIdent == "" || auxIdent == "0" {
|
||||
err = fmt.Errorf("related resource doesn't provide an ID")
|
||||
return
|
||||
}
|
||||
|
||||
err = n.Resource.SetValue(fieldLabel, 0, auxIdent)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (e YamlEncoder) encodeAuthClientSecurityC(ctx context.Context, p envoyx.EncodeParams, tt envoyx.Traverser, n *envoyx.Node, ac *types.AuthClient, sec *types.AuthClientSecurity) (_ any, err error) {
|
||||
sqPermittedRoles, err := e.encodeRoleSlice(n, tt, "Security.PermittedRoles", sec.PermittedRoles)
|
||||
if err != nil {
|
||||
|
||||
@@ -125,6 +125,7 @@ func cleanup(t *testing.T) {
|
||||
store.TruncateUsers(ctx, defaultStore),
|
||||
store.TruncateDalConnections(ctx, defaultStore),
|
||||
store.TruncateDalSensitivityLevels(ctx, defaultStore),
|
||||
store.TruncateRbacRules(ctx, defaultStore),
|
||||
|
||||
store.TruncateAutomationWorkflows(ctx, defaultStore),
|
||||
store.TruncateAutomationTriggers(ctx, defaultStore),
|
||||
|
||||
@@ -0,0 +1,273 @@
|
||||
package envoy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/cortezaproject/corteza/server/compose/types"
|
||||
"github.com/cortezaproject/corteza/server/pkg/envoyx"
|
||||
"github.com/cortezaproject/corteza/server/pkg/rbac"
|
||||
"github.com/cortezaproject/corteza/server/store"
|
||||
systemTypes "github.com/cortezaproject/corteza/server/system/types"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestRbacImportExport(t *testing.T) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
req = require.New(t)
|
||||
nodes envoyx.NodeSet
|
||||
gg *envoyx.DepGraph
|
||||
err error
|
||||
)
|
||||
|
||||
cleanup(t)
|
||||
|
||||
// The test
|
||||
//
|
||||
// * imports some YAML files
|
||||
// * checks the DB state
|
||||
// * exports the DB into a YAML
|
||||
// * clears the DB
|
||||
// * imports the YAML
|
||||
// * checks the DB state the same way as before
|
||||
//
|
||||
// The above outlined flow allows us to trivially check if the data is both
|
||||
// imported and exported correctly.
|
||||
//
|
||||
// The initial step could also manually populate the DB but the YAML import
|
||||
// is more convenient.
|
||||
|
||||
t.Run("initial import", func(t *testing.T) {
|
||||
t.Run("parse configs", func(t *testing.T) {
|
||||
nodes, err = defaultEnvoy.Decode(ctx, envoyx.DecodeParams{
|
||||
Type: envoyx.DecodeTypeURI,
|
||||
Params: map[string]any{
|
||||
"uri": "file://testdata/rbac",
|
||||
},
|
||||
})
|
||||
req.NoError(err)
|
||||
})
|
||||
|
||||
t.Run("bake", func(t *testing.T) {
|
||||
gg, err = defaultEnvoy.Bake(ctx, envoyx.EncodeParams{
|
||||
Type: envoyx.EncodeTypeStore,
|
||||
Params: map[string]any{
|
||||
"storer": defaultStore,
|
||||
"dal": defaultDal,
|
||||
},
|
||||
}, nodes...)
|
||||
req.NoError(err)
|
||||
})
|
||||
|
||||
t.Run("import into DB", func(t *testing.T) {
|
||||
err = defaultEnvoy.Encode(ctx, envoyx.EncodeParams{
|
||||
Type: envoyx.EncodeTypeStore,
|
||||
Params: map[string]any{
|
||||
"storer": defaultStore,
|
||||
"dal": defaultDal,
|
||||
},
|
||||
}, gg)
|
||||
req.NoError(err)
|
||||
})
|
||||
|
||||
assertRBACState(ctx, t, defaultStore, req)
|
||||
})
|
||||
|
||||
// Prepare a temp file where we'll dump the YAML into
|
||||
auxFile, err := os.CreateTemp(os.TempDir(), "*.yaml")
|
||||
req.NoError(err)
|
||||
spew.Dump(auxFile.Name())
|
||||
// defer os.Remove(auxFile.Name())
|
||||
defer auxFile.Close()
|
||||
|
||||
var rules envoyx.NodeSet
|
||||
t.Run("export", func(t *testing.T) {
|
||||
t.Run("export from DB", func(t *testing.T) {
|
||||
nodes, err = defaultEnvoy.Decode(ctx, envoyx.DecodeParams{
|
||||
Type: envoyx.DecodeTypeStore,
|
||||
Params: map[string]any{
|
||||
"storer": defaultStore,
|
||||
},
|
||||
Filter: map[string]envoyx.ResourceFilter{
|
||||
types.ModuleResourceType: {},
|
||||
types.NamespaceResourceType: {},
|
||||
|
||||
systemTypes.RoleResourceType: {},
|
||||
},
|
||||
})
|
||||
req.NoError(err)
|
||||
})
|
||||
|
||||
var rr rbac.RuleSet
|
||||
t.Run("get all rules", func(t *testing.T) {
|
||||
rr, _, err = store.SearchRbacRules(ctx, defaultStore, rbac.RuleFilter{})
|
||||
req.NoError(err)
|
||||
})
|
||||
|
||||
t.Run("connect rules to resources", func(t *testing.T) {
|
||||
rules, err = envoyx.RBACRulesForNodes(rr, nodes...)
|
||||
req.NoError(err)
|
||||
|
||||
nodes = append(nodes, rules...)
|
||||
})
|
||||
|
||||
t.Run("bake", func(t *testing.T) {
|
||||
gg, err = defaultEnvoy.Bake(ctx, envoyx.EncodeParams{
|
||||
Type: envoyx.EncodeTypeStore,
|
||||
Params: map[string]any{
|
||||
"storer": defaultStore,
|
||||
"dal": defaultDal,
|
||||
},
|
||||
}, nodes...)
|
||||
req.NoError(err)
|
||||
})
|
||||
|
||||
t.Run("write file", func(t *testing.T) {
|
||||
err = defaultEnvoy.Encode(ctx, envoyx.EncodeParams{
|
||||
Type: envoyx.EncodeTypeIo,
|
||||
Params: map[string]any{
|
||||
"writer": auxFile,
|
||||
},
|
||||
}, gg)
|
||||
req.NoError(err)
|
||||
})
|
||||
})
|
||||
|
||||
cleanup(t)
|
||||
|
||||
t.Run("second import", func(t *testing.T) {
|
||||
t.Run("yaml parse", func(t *testing.T) {
|
||||
nodes, err = defaultEnvoy.Decode(ctx, envoyx.DecodeParams{
|
||||
Type: envoyx.DecodeTypeURI,
|
||||
Params: map[string]any{
|
||||
"uri": fmt.Sprintf("file://%s", auxFile.Name()),
|
||||
},
|
||||
})
|
||||
req.NoError(err)
|
||||
})
|
||||
|
||||
t.Run("bake", func(t *testing.T) {
|
||||
gg, err = defaultEnvoy.Bake(ctx, envoyx.EncodeParams{
|
||||
Type: envoyx.EncodeTypeStore,
|
||||
Params: map[string]any{
|
||||
"storer": defaultStore,
|
||||
"dal": defaultDal,
|
||||
},
|
||||
}, nodes...)
|
||||
req.NoError(err)
|
||||
})
|
||||
|
||||
t.Run("run import", func(t *testing.T) {
|
||||
err = defaultEnvoy.Encode(ctx, envoyx.EncodeParams{
|
||||
Type: envoyx.EncodeTypeStore,
|
||||
Params: map[string]any{
|
||||
"storer": defaultStore,
|
||||
"dal": defaultDal,
|
||||
},
|
||||
}, gg)
|
||||
req.NoError(err)
|
||||
})
|
||||
|
||||
assertRBACState(ctx, t, defaultStore, req)
|
||||
})
|
||||
}
|
||||
|
||||
func assertRBACState(ctx context.Context, t *testing.T, s store.Storer, req *require.Assertions) {
|
||||
t.Run("check state", func(t *testing.T) {
|
||||
namespaces, _, err := store.SearchComposeNamespaces(ctx, defaultStore, types.NamespaceFilter{})
|
||||
req.NoError(err)
|
||||
ns1 := namespaces[0]
|
||||
|
||||
modules, _, err := store.SearchComposeModules(ctx, defaultStore, types.ModuleFilter{})
|
||||
req.NoError(err)
|
||||
mod1 := modules[0]
|
||||
|
||||
roles, _, err := store.SearchRoles(ctx, defaultStore, systemTypes.RoleFilter{})
|
||||
req.NoError(err)
|
||||
role1 := roles.FindByHandle("test_role_1")
|
||||
role2 := roles.FindByHandle("test_role_2")
|
||||
|
||||
rr, _, err := store.SearchRbacRules(ctx, defaultStore, rbac.RuleFilter{})
|
||||
req.NoError(err)
|
||||
|
||||
allows := rr.FilterAccess(rbac.Allow)
|
||||
compareRules(req, *allows.FilterOperation("op1")[0], rbac.Rule{
|
||||
RoleID: role1.ID,
|
||||
Resource: "corteza::compose:namespace/*",
|
||||
Operation: "op1",
|
||||
Access: rbac.Allow,
|
||||
})
|
||||
|
||||
compareRules(req, *allows.FilterOperation("op2")[0], rbac.Rule{
|
||||
RoleID: role1.ID,
|
||||
Resource: fmt.Sprintf("corteza::compose:namespace/%d", ns1.ID),
|
||||
Operation: "op2",
|
||||
Access: rbac.Allow,
|
||||
})
|
||||
|
||||
compareRules(req, *allows.FilterOperation("op3")[0], rbac.Rule{
|
||||
RoleID: role1.ID,
|
||||
Resource: fmt.Sprintf("corteza::compose:module/%d/*", ns1.ID),
|
||||
Operation: "op3",
|
||||
Access: rbac.Allow,
|
||||
})
|
||||
|
||||
compareRules(req, *allows.FilterOperation("op4")[0], rbac.Rule{
|
||||
RoleID: role1.ID,
|
||||
Resource: fmt.Sprintf("corteza::compose:module/%d/%d", ns1.ID, mod1.ID),
|
||||
Operation: "op4",
|
||||
Access: rbac.Allow,
|
||||
})
|
||||
|
||||
denies := rr.FilterAccess(rbac.Deny)
|
||||
compareRules(req, *denies.FilterOperation("op1")[0], rbac.Rule{
|
||||
RoleID: role2.ID,
|
||||
Resource: "corteza::compose:namespace/*",
|
||||
Operation: "op1",
|
||||
Access: rbac.Deny,
|
||||
})
|
||||
|
||||
compareRules(req, *denies.FilterOperation("op2")[0], rbac.Rule{
|
||||
RoleID: role2.ID,
|
||||
Resource: fmt.Sprintf("corteza::compose:namespace/%d", ns1.ID),
|
||||
Operation: "op2",
|
||||
Access: rbac.Deny,
|
||||
})
|
||||
|
||||
compareRules(req, *denies.FilterOperation("op3")[0], rbac.Rule{
|
||||
RoleID: role2.ID,
|
||||
Resource: fmt.Sprintf("corteza::compose:module/%d/*", ns1.ID),
|
||||
Operation: "op3",
|
||||
Access: rbac.Deny,
|
||||
})
|
||||
|
||||
compareRules(req, *denies.FilterOperation("op4")[0], rbac.Rule{
|
||||
RoleID: role2.ID,
|
||||
Resource: fmt.Sprintf("corteza::compose:module/%d/%d", ns1.ID, mod1.ID),
|
||||
Operation: "op4",
|
||||
Access: rbac.Deny,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func compareRules(req *require.Assertions, a, b rbac.Rule) {
|
||||
if a.RoleID != b.RoleID {
|
||||
req.FailNow("RoleID missmatch")
|
||||
}
|
||||
|
||||
if a.Resource != b.Resource {
|
||||
req.FailNow("Resource missmatch")
|
||||
}
|
||||
|
||||
if a.Operation != b.Operation {
|
||||
req.FailNow("Operation missmatch")
|
||||
}
|
||||
|
||||
if a.Access != b.Access {
|
||||
req.FailNow("Access missmatch")
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
namespace:
|
||||
test_ns_1:
|
||||
name: Test Namespace 1
|
||||
modules:
|
||||
test_mod_1:
|
||||
name: Test Module 1
|
||||
roles:
|
||||
test_role_1:
|
||||
name: Test Role 1
|
||||
test_role_2:
|
||||
name: Test Role 2
|
||||
|
||||
allow:
|
||||
test_role_1:
|
||||
corteza::compose:namespace/*:
|
||||
- op1
|
||||
corteza::compose:namespace/test_ns_1:
|
||||
- op2
|
||||
corteza::compose:module/test_ns_1/*:
|
||||
- op3
|
||||
corteza::compose:module/test_ns_1/test_mod_1:
|
||||
- op4
|
||||
|
||||
deny:
|
||||
test_role_2:
|
||||
corteza::compose:namespace/*:
|
||||
- op1
|
||||
corteza::compose:namespace/test_ns_1:
|
||||
- op2
|
||||
corteza::compose:module/test_ns_1/*:
|
||||
- op3
|
||||
corteza::compose:module/test_ns_1/test_mod_1:
|
||||
- op4
|
||||
Reference in New Issue
Block a user