Refactor RBAC YAML decoding

This commit is contained in:
Denis Arh
2020-11-27 11:19:15 +01:00
committed by Tomaž Jerman
parent b3683a15bf
commit 90e2860061
7 changed files with 108 additions and 143 deletions
+7 -6
View File
@@ -90,14 +90,18 @@ func (wset composeChartSet) MarshalEnvoy() ([]envoy.Node, error) {
return nn, nil
}
func (wrap *composeChart) UnmarshalYAML(n *yaml.Node) error {
func (wrap *composeChart) UnmarshalYAML(n *yaml.Node) (err error) {
if !isKind(n, yaml.MappingNode) {
return nodeErr(n, "chart definition must be a map")
}
if wrap.res == nil {
wrap.rbacRules = &rbacRules{}
wrap.res = &types.Chart{}
}
if !isKind(n, yaml.MappingNode) {
return nodeErr(n, "chart definition must be a map")
if wrap.rbacRules, err = decodeResourceAccessControl(types.ChartRBACResource, n); err != nil {
return
}
return iterator(n, func(k, v *yaml.Node) (err error) {
@@ -121,9 +125,6 @@ func (wrap *composeChart) UnmarshalYAML(n *yaml.Node) error {
wrap.res.Config = cfg.config
wrap.refReportModules = cfg.refReportModules
case "allow", "deny":
return wrap.rbacRules.DecodeResourceRules(types.ChartRBACResource, k, v)
}
return nil
+18 -35
View File
@@ -82,14 +82,18 @@ func (wset ComposeModuleSet) MarshalEnvoy() ([]envoy.Node, error) {
return nn, nil
}
func (wrap *ComposeModule) UnmarshalYAML(n *yaml.Node) error {
func (wrap *ComposeModule) UnmarshalYAML(n *yaml.Node) (err error) {
if !isKind(n, yaml.MappingNode) {
return nodeErr(n, "module definition must be a map")
}
if wrap.res == nil {
wrap.rbacRules = &rbacRules{}
wrap.res = &types.Module{}
}
if !isKind(n, yaml.MappingNode) {
return nodeErr(n, "module definition must be a map")
if wrap.rbacRules, err = decodeResourceAccessControl(types.ModuleRBACResource, n); err != nil {
return
}
return iterator(n, func(k, v *yaml.Node) (err error) {
@@ -116,9 +120,6 @@ func (wrap *ComposeModule) UnmarshalYAML(n *yaml.Node) error {
wrap.res.Fields = aux.set()
return nil
case "allow", "deny":
return wrap.rbacRules.DecodeResourceRules(types.ModuleRBACResource, k, v)
}
return nil
@@ -168,14 +169,21 @@ func (set ComposeModuleFieldSet) set() (out types.ModuleFieldSet) {
return out
}
func (wrap *ComposeModuleField) UnmarshalYAML(n *yaml.Node) error {
func (wrap *ComposeModuleField) UnmarshalYAML(n *yaml.Node) (err error) {
if !isKind(n, yaml.MappingNode) {
return nodeErr(n, "module field definition must be a map")
}
if wrap.res == nil {
wrap.rbacRules = &rbacRules{}
wrap.res = &types.ModuleField{}
}
if !isKind(n, yaml.MappingNode) {
return nodeErr(n, "module field definition must be a map")
if err = n.Decode(&wrap.res); err != nil {
return
}
if wrap.rbacRules, err = decodeResourceAccessControl(types.ModuleFieldRBACResource, n); err != nil {
return
}
return iterator(n, func(k, v *yaml.Node) (err error) {
@@ -183,27 +191,6 @@ func (wrap *ComposeModuleField) UnmarshalYAML(n *yaml.Node) error {
case "name":
return fmt.Errorf("name should be encoded as field definition key")
case "label":
return decodeScalar(v, "module field label", &wrap.res.Label)
case "kind", "type":
return decodeScalar(v, "module field kind", &wrap.res.Kind)
case "options":
return v.Decode(&wrap.res.Options)
case "private":
return decodeScalar(v, "module field private", &wrap.res.Private)
case "required":
return decodeScalar(v, "module field required", &wrap.res.Required)
case "visible":
return decodeScalar(v, "module field visible", &wrap.res.Visible)
case "multi":
return decodeScalar(v, "module field multi", &wrap.res.Multi)
case "default":
return fmt.Errorf("field.default /// to be imple,emted")
//wrap.res.DefaultValue = types.RecordValueSet{}
@@ -215,10 +202,6 @@ func (wrap *ComposeModuleField) UnmarshalYAML(n *yaml.Node) error {
//
// return
//})
case "allow", "deny":
return wrap.rbacRules.DecodeResourceRules(types.ModuleFieldRBACResource, k, v)
}
return nil
+9 -15
View File
@@ -73,36 +73,30 @@ func (wset ComposeNamespaceSet) MarshalEnvoy() ([]envoy.Node, error) {
return nn, nil
}
func (wrap *ComposeNamespace) UnmarshalYAML(n *yaml.Node) error {
func (wrap *ComposeNamespace) UnmarshalYAML(n *yaml.Node) (err error) {
if !isKind(n, yaml.MappingNode) {
return nodeErr(n, "namespace definition must be a map or scalar")
}
if wrap.res == nil {
wrap.rbacRules = &rbacRules{}
wrap.res = &types.Namespace{
// namespaces are enabled by default
Enabled: true,
}
}
if err = n.Decode(&wrap.res); err != nil {
return
}
if wrap.rbacRules, err = decodeResourceAccessControl(types.NamespaceRBACResource, n); err != nil {
return
}
return iterator(n, func(k, v *yaml.Node) (err error) {
switch k.Value {
case "slug":
return decodeScalar(v, "namespace slug", &wrap.res.Slug)
case "name":
return decodeScalar(v, "namespace name", &wrap.res.Name)
case "enabled":
return decodeScalar(v, "namespace enabled", &wrap.res.Enabled)
case "modules":
return v.Decode(&wrap.modules)
case "allow", "deny":
return wrap.rbacRules.DecodeResourceRules(types.NamespaceRBACResource, k, v)
}
return nil
+7 -11
View File
@@ -81,7 +81,11 @@ func (wset composePageSet) MarshalEnvoy() ([]envoy.Node, error) {
return nn, nil
}
func (wrap *composePage) UnmarshalYAML(n *yaml.Node) error {
func (wrap *composePage) UnmarshalYAML(n *yaml.Node) (err error) {
if !isKind(n, yaml.MappingNode) {
return nodeErr(n, "page definition must be a map")
}
if wrap.res == nil {
wrap.rbacRules = &rbacRules{}
wrap.res = &types.Page{
@@ -90,8 +94,8 @@ func (wrap *composePage) UnmarshalYAML(n *yaml.Node) error {
}
}
if !isKind(n, yaml.MappingNode) {
return nodeErr(n, "page definition must be a map")
if wrap.rbacRules, err = decodeResourceAccessControl(types.PageRBACResource, n); err != nil {
return
}
return iterator(n, func(k, v *yaml.Node) (err error) {
@@ -122,17 +126,9 @@ func (wrap *composePage) UnmarshalYAML(n *yaml.Node) error {
wrap.res.Blocks[i] = b
}
// @todo
// return decodeScalar(v, "page blocks", &wrap.res.Visible)
case "pages":
return v.Decode(&wrap.pages)
// return decodeScalar(v, "page pages", &wrap.res.Visible)
case "allow", "deny":
return wrap.rbacRules.DecodeResourceRules(types.PageRBACResource, k, v)
}
return nil
+6 -7
View File
@@ -101,7 +101,7 @@ func (set ComposeRecordSet) setNamespaceRef(ref string) error {
return nil
}
func (wrap *ComposeRecord) UnmarshalYAML(n *yaml.Node) error {
func (wrap *ComposeRecord) UnmarshalYAML(n *yaml.Node) (err error) {
if !isKind(n, yaml.MappingNode) {
return nodeErr(n, "expecting mapping node for record definition")
}
@@ -111,6 +111,11 @@ func (wrap *ComposeRecord) UnmarshalYAML(n *yaml.Node) error {
wrap.res = &types.Record{}
}
// @todo enable when records are ready for RBAC
//if wrap.rbacRules, err = decodeResourceAccessControl(types.RecordRBACResource, n); err != nil {
// return
//}
return iterator(n, func(k, v *yaml.Node) error {
switch k.Value {
case "module":
@@ -141,12 +146,6 @@ func (wrap *ComposeRecord) UnmarshalYAML(n *yaml.Node) error {
case "ownedBy":
return decodeRef(v, "ownedBy user", &wrap.refOwnedBy)
case "allow", "deny":
// @todo enable when records are ready for RBAC
// return wrap.rbacRules.DecodeResourceRules(types.RecordRBACResource, k, v)
default:
return nodeErr(k, "unsupported key %s used for record definition", k.Value)
}
return nil
+7 -12
View File
@@ -14,26 +14,21 @@ type (
}
)
func (doc *Document) UnmarshalYAML(n *yaml.Node) error {
func (doc *Document) UnmarshalYAML(n *yaml.Node) (err error) {
if !isKind(n, yaml.MappingNode) {
// root node kind be mapping
return nodeErr(n, "expecting mapping node")
}
if err := n.Decode(&doc.compose); err != nil {
return err
if err = n.Decode(&doc.compose); err != nil {
return
}
doc.rbacRules = &rbacRules{}
return iterator(n, func(k, v *yaml.Node) error {
switch k.Value {
case "allow", "deny":
return doc.rbacRules.DecodeGlobalRules(k, v)
if doc.rbacRules, err = decodeGlobalAccessControl(n); err != nil {
return
}
}
return nil
})
return nil
}
//
+54 -57
View File
@@ -12,93 +12,90 @@ type (
}
)
// Decodes RBAC rules defined as access/role/ops...
func (wrap *rbacRules) DecodeResourceRules(res rbac.Resource, k, v *yaml.Node) error {
func decodeRbacOperations(rr *rbacRules, access rbac.Access, role string, res rbac.Resource) func(_, _ *yaml.Node) error {
if _, set := rr.rules[role]; !set {
rr.rules[role] = rbac.RuleSet{}
}
return func(_, v *yaml.Node) error {
rule := &rbac.Rule{Resource: res, Operation: rbac.Operation(v.Value), Access: access}
rr.rules[role] = append(rr.rules[role], rule)
return nil
}
}
func decodeResourceAccessControl(res rbac.Resource, n *yaml.Node) (*rbacRules, error) {
var (
access rbac.Access
rr = &rbacRules{rules: make(map[string]rbac.RuleSet)}
)
if wrap.rules == nil {
wrap.rules = make(map[string]rbac.RuleSet)
}
return rr, iterator(n, func(k, v *yaml.Node) (err error) {
switch k.Value {
case "allow":
return rr.decodeResourceAccessControl(rbac.Allow, res, v)
case "deny":
return rr.decodeResourceAccessControl(rbac.Deny, res, v)
}
return nil
})
}
func decodeGlobalAccessControl(n *yaml.Node) (*rbacRules, error) {
var (
rr = &rbacRules{rules: make(map[string]rbac.RuleSet)}
)
return rr, iterator(n, func(k, v *yaml.Node) (err error) {
switch k.Value {
case "allow":
return rr.decodeGlobalAccessControl(rbac.Allow, v)
case "deny":
return rr.decodeGlobalAccessControl(rbac.Deny, v)
}
return nil
})
}
// Decodes RBAC rules defined as access/role/ops...
func (wrap *rbacRules) decodeResourceAccessControl(access rbac.Access, res rbac.Resource, v *yaml.Node) error {
if !isKind(v, yaml.MappingNode) {
return nodeErr(v, "rbac per access rule definition must be a map")
}
if k.Value == "allow" {
access = rbac.Allow
return nodeErr(v, "RBAC per access rule definition must be a map")
}
return iterator(v, func(k, v *yaml.Node) error {
var (
role = k.Value
)
if _, set := wrap.rules[role]; !set {
wrap.rules[role] = rbac.RuleSet{}
}
if !isKind(v, yaml.SequenceNode) {
return nodeErr(v, "rbac rule operations list must be a sequence")
return nodeErr(v, "RBAC rule operations list must be a sequence")
}
return iterator(v, func(_, v *yaml.Node) error {
rule := &rbac.Rule{Resource: res, Operation: rbac.Operation(v.Value), Access: access}
wrap.rules[role] = append(wrap.rules[role], rule)
return nil
})
return iterator(v, decodeRbacOperations(wrap, access, k.Value, res))
})
}
// Decodes RBAC rules defined as access/role/resource/ops...
func (wrap *rbacRules) DecodeGlobalRules(k, v *yaml.Node) error {
var (
access rbac.Access
)
if wrap.rules == nil {
wrap.rules = make(map[string]rbac.RuleSet)
}
func (wrap *rbacRules) decodeGlobalAccessControl(access rbac.Access, v *yaml.Node) error {
if !isKind(v, yaml.MappingNode) {
return nodeErr(v, "rbac per access rule definition must be a map")
}
if k.Value == "allow" {
access = rbac.Allow
return nodeErr(v, "RBAC per access rule definition must be a map")
}
return iterator(v, func(k, v *yaml.Node) error {
var (
role = k.Value
)
if _, set := wrap.rules[role]; !set {
wrap.rules[role] = rbac.RuleSet{}
}
var role = k.Value
if !isKind(v, yaml.MappingNode) {
return nodeErr(v, "rbac per role rule definition must be a map")
return nodeErr(v, "RBAC per role rule definition must be a map")
}
return iterator(v, func(k, v *yaml.Node) error {
var res = rbac.Resource(k.Value)
if !res.IsValid() {
return nodeErr(k, "rbac resource %s invalid", k.Value)
return nodeErr(k, "RBAC resource %s invalid", k.Value)
}
if !isKind(v, yaml.SequenceNode) {
return nodeErr(v, "rbac rule operations list must be a sequence")
return nodeErr(v, "RBAC rule operations list must be a sequence")
}
return iterator(v, func(_, v *yaml.Node) error {
rule := &rbac.Rule{Resource: res, Operation: rbac.Operation(v.Value), Access: access}
wrap.rules[role] = append(wrap.rules[role], rule)
return nil
})
return iterator(v, decodeRbacOperations(wrap, access, role, res))
})
})
}