Refactor RBAC YAML decoding
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user