diff --git a/pkg/envoy/yaml/compose_chart.go b/pkg/envoy/yaml/compose_chart.go index a2ca2806c..8ab378407 100644 --- a/pkg/envoy/yaml/compose_chart.go +++ b/pkg/envoy/yaml/compose_chart.go @@ -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 diff --git a/pkg/envoy/yaml/compose_module.go b/pkg/envoy/yaml/compose_module.go index 87cdaba6c..b22d2d43a 100644 --- a/pkg/envoy/yaml/compose_module.go +++ b/pkg/envoy/yaml/compose_module.go @@ -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 diff --git a/pkg/envoy/yaml/compose_namespace.go b/pkg/envoy/yaml/compose_namespace.go index 07d97ce56..f3090ae1c 100644 --- a/pkg/envoy/yaml/compose_namespace.go +++ b/pkg/envoy/yaml/compose_namespace.go @@ -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 diff --git a/pkg/envoy/yaml/compose_page.go b/pkg/envoy/yaml/compose_page.go index 607279431..9bf69bd1c 100644 --- a/pkg/envoy/yaml/compose_page.go +++ b/pkg/envoy/yaml/compose_page.go @@ -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 diff --git a/pkg/envoy/yaml/compose_record.go b/pkg/envoy/yaml/compose_record.go index 8a9bb2b37..b02bd413c 100644 --- a/pkg/envoy/yaml/compose_record.go +++ b/pkg/envoy/yaml/compose_record.go @@ -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 diff --git a/pkg/envoy/yaml/doc.go b/pkg/envoy/yaml/doc.go index 89db6dbfa..71999e8a7 100644 --- a/pkg/envoy/yaml/doc.go +++ b/pkg/envoy/yaml/doc.go @@ -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 } // diff --git a/pkg/envoy/yaml/rbac.go b/pkg/envoy/yaml/rbac.go index 16a5b8357..04afaf0e5 100644 --- a/pkg/envoy/yaml/rbac.go +++ b/pkg/envoy/yaml/rbac.go @@ -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)) }) }) }