Skip to content

Commit

Permalink
feat: add rbac rules for non-resource urls (#279)
Browse files Browse the repository at this point in the history
* refactor: move rbac into its own package

Signed-off-by: Dustin Scott <sdustin@vmware.com>

* fix: Fixes #274, added capability to generate rules for nonresource urls

Signed-off-by: Dustin Scott <sdustin@vmware.com>

* refactor: move utils file into proper utils package

Signed-off-by: Dustin Scott <sdustin@vmware.com>

* test: added test cases for rbac after refactor

Signed-off-by: Dustin Scott <sdustin@vmware.com>

* chore: fix linting

Signed-off-by: Dustin Scott <sdustin@vmware.com>

* test: fix test case for roles with non-resource urls

Signed-off-by: Dustin Scott <sdustin@vmware.com>
  • Loading branch information
scottd018 authored Mar 7, 2022
1 parent 6b8a0ce commit f2daa61
Show file tree
Hide file tree
Showing 22 changed files with 2,161 additions and 529 deletions.
78 changes: 78 additions & 0 deletions internal/utils/conversion.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright 2021 VMware, Inc.
// SPDX-License-Identifier: MIT

package utils

import (
"errors"
"fmt"
)

var (
ErrConvertArrayInterface = errors.New("unable to convert to []interface{}")
ErrConvertArrayString = errors.New("unable to convert to []string")
ErrConvertMapStringInterface = errors.New("unable to convert to map[string]interface{}")
ErrConvertString = errors.New("unable to convert to string")
)

// ToArrayInterface attempts a conversion from an interface to an underlying array of
// interface type. Returns an error if the conversion is not possible.
func ToArrayInterface(in interface{}) ([]interface{}, error) {
out, ok := in.([]interface{})
if !ok {
return nil, ErrConvertArrayInterface
}

return out, nil
}

// ToArrayString attempts a conversion from an interface to an underlying array of
// string type. Returns an error if the conversion is not possible.
func ToArrayString(in interface{}) ([]string, error) {
// attempt direct conversion
out, ok := in.([]string)
if !ok {
// attempt conversion for each item
outInterfaces, err := ToArrayInterface(in)
if err != nil {
return nil, fmt.Errorf("%w; %s", err, ErrConvertArrayString)
}

outStrings := make([]string, len(outInterfaces))

for i := range outInterfaces {
outString, err := ToString(outInterfaces[i])
if err != nil {
return nil, fmt.Errorf("%w; %s", err, ErrConvertArrayString)
}

outStrings[i] = outString
}

return outStrings, nil
}

return out, nil
}

// ToMapStringInterface attempts a conversion from an interface to an underlying map
// string interface type. Returns an error if the conversion is not possible.
func ToMapStringInterface(in interface{}) (map[string]interface{}, error) {
out, ok := in.(map[string]interface{})
if !ok {
return nil, ErrConvertMapStringInterface
}

return out, nil
}

// ToArrayInterface attempts a conversion from an interface to an underlying
// string type. Returns an error if the conversion is not possible.
func ToString(in interface{}) (string, error) {
out, ok := in.(string)
if !ok {
return "", ErrConvertString
}

return out, nil
}
63 changes: 1 addition & 62 deletions internal/workload/v1/utils.go → internal/utils/files.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2021 VMware, Inc.
// SPDX-License-Identifier: MIT

package v1
package utils

import (
"errors"
Expand All @@ -13,13 +13,6 @@ import (
"strings"
)

var (
ErrConvertArrayInterface = errors.New("unable to convert to []interface{}")
ErrConvertArrayString = errors.New("unable to convert to []string")
ErrConvertMapStringInterface = errors.New("unable to convert to map[string]interface{}")
ErrConvertString = errors.New("unable to convert to string")
)

func ReadStream(fileName string) (io.ReadCloser, error) {
file, err := os.Open(fileName)
if err != nil {
Expand Down Expand Up @@ -109,57 +102,3 @@ func expand(g []string) ([]string, error) {

return matches, nil
}

func toArrayInterface(in interface{}) ([]interface{}, error) {
out, ok := in.([]interface{})
if !ok {
return nil, ErrConvertArrayInterface
}

return out, nil
}

func toArrayString(in interface{}) ([]string, error) {
// attempt direct conversion
out, ok := in.([]string)
if !ok {
// attempt conversion for each item
outInterfaces, err := toArrayInterface(in)
if err != nil {
return nil, fmt.Errorf("%w; %s", err, ErrConvertArrayString)
}

outStrings := make([]string, len(outInterfaces))

for i := range outInterfaces {
outString, err := toString(outInterfaces[i])
if err != nil {
return nil, fmt.Errorf("%w; %s", err, ErrConvertArrayString)
}

outStrings[i] = outString
}

return outStrings, nil
}

return out, nil
}

func toMapStringInterface(in interface{}) (map[string]interface{}, error) {
out, ok := in.(map[string]interface{})
if !ok {
return nil, ErrConvertMapStringInterface
}

return out, nil
}

func toString(in interface{}) (string, error) {
out, ok := in.(string)
if !ok {
return "", ErrConvertString
}

return out, nil
}
7 changes: 4 additions & 3 deletions internal/workload/v1/collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/vmware-tanzu-labs/operator-builder/internal/utils"
"github.com/vmware-tanzu-labs/operator-builder/internal/workload/v1/markers"
"github.com/vmware-tanzu-labs/operator-builder/internal/workload/v1/rbac"
)

const (
Expand Down Expand Up @@ -152,7 +153,7 @@ func (c *WorkloadCollection) IsCollection() bool {
}

func (c *WorkloadCollection) SetRBAC() {
c.Spec.RBACRules.addRulesForWorkload(c)
c.Spec.RBACRules.Add(rbac.ForWorkloads(c))
}

func (c *WorkloadCollection) SetResources(workloadPath string) error {
Expand Down Expand Up @@ -208,8 +209,8 @@ func (c *WorkloadCollection) GetAPISpecFields() *APIFields {
return c.Spec.APISpecFields
}

func (c *WorkloadCollection) GetRBACRules() *[]RBACRule {
var rules []RBACRule = *c.Spec.RBACRules
func (c *WorkloadCollection) GetRBACRules() *[]rbac.Rule {
var rules []rbac.Rule = *c.Spec.RBACRules

return &rules
}
Expand Down
7 changes: 4 additions & 3 deletions internal/workload/v1/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/vmware-tanzu-labs/operator-builder/internal/utils"
"github.com/vmware-tanzu-labs/operator-builder/internal/workload/v1/markers"
"github.com/vmware-tanzu-labs/operator-builder/internal/workload/v1/rbac"
)

var ErrNoComponentsOnComponent = errors.New("cannot set component workloads on a component workload - only on collections")
Expand Down Expand Up @@ -134,7 +135,7 @@ func (*ComponentWorkload) IsCollection() bool {
}

func (c *ComponentWorkload) SetRBAC() {
c.Spec.RBACRules.addRulesForWorkload(c)
c.Spec.RBACRules.Add(rbac.ForWorkloads(c, c.Spec.Collection))
}

func (c *ComponentWorkload) SetResources(workloadPath string) error {
Expand Down Expand Up @@ -178,8 +179,8 @@ func (c *ComponentWorkload) GetAPISpecFields() *APIFields {
return c.Spec.APISpecFields
}

func (c *ComponentWorkload) GetRBACRules() *[]RBACRule {
var rules []RBACRule = *c.Spec.RBACRules
func (c *ComponentWorkload) GetRBACRules() *[]rbac.Rule {
var rules []rbac.Rule = *c.Spec.RBACRules

return &rules
}
Expand Down
11 changes: 6 additions & 5 deletions internal/workload/v1/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/go-playground/validator"
"gopkg.in/yaml.v3"

"github.com/vmware-tanzu-labs/operator-builder/internal/utils"
"github.com/vmware-tanzu-labs/operator-builder/internal/workload/v1/markers"
)

Expand Down Expand Up @@ -182,12 +183,12 @@ func parseConfig(workloadConfig string) (map[WorkloadKind][]WorkloadIdentifier,
return nil, ErrConfigMustExist
}

file, err := ReadStream(workloadConfig)
file, err := utils.ReadStream(workloadConfig)
if err != nil {
return nil, err
return nil, fmt.Errorf("%w; error reading file %s", err, workloadConfig)
}

defer CloseFile(file)
defer utils.CloseFile(file)

var kindReader bytes.Buffer
reader := io.TeeReader(file, &kindReader)
Expand Down Expand Up @@ -252,9 +253,9 @@ func parseCollectionComponents(workload *WorkloadCollection, workloadConfig stri
var workloads []WorkloadIdentifier

for _, componentFile := range workload.Spec.ComponentFiles {
componentPaths, err := Glob(filepath.Join(filepath.Dir(workloadConfig), componentFile))
componentPaths, err := utils.Glob(filepath.Join(filepath.Dir(workloadConfig), componentFile))
if err != nil {
return nil, err
return nil, fmt.Errorf("%w; error globbing workload config at path %s", err, componentFile)
}

for _, componentPath := range componentPaths {
Expand Down
10 changes: 6 additions & 4 deletions internal/workload/v1/init_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"os"

"gopkg.in/yaml.v3"

"github.com/vmware-tanzu-labs/operator-builder/internal/utils"
)

var (
Expand Down Expand Up @@ -117,25 +119,25 @@ func mutateConfig(workloadConfig WorkloadInitializer) ([]byte, error) {
}

func mutateResources(yamlData map[string]interface{}) error {
specField, err := toMapStringInterface(yamlData["spec"])
specField, err := utils.ToMapStringInterface(yamlData["spec"])
if err != nil {
return fmt.Errorf("%w; error converting workload config spec %v", err, yamlData["spec"])
}

resourceObjs, err := toArrayInterface(specField["resources"])
resourceObjs, err := utils.ToArrayInterface(specField["resources"])
if err != nil {
return fmt.Errorf("%w; error converting spec.resources %v", err, specField["resources"])
}

resources := make([]string, len(resourceObjs))

for i, resource := range resourceObjs {
resourceMap, err := toMapStringInterface(resource)
resourceMap, err := utils.ToMapStringInterface(resource)
if err != nil {
return fmt.Errorf("%w; error converting spec.resources item %v", err, resource)
}

filename, err := toString(resourceMap["filename"])
filename, err := utils.ToString(resourceMap["filename"])
if err != nil {
return fmt.Errorf("%w; error converting spec.resources.filename %v", err, resource)
}
Expand Down
8 changes: 6 additions & 2 deletions internal/workload/v1/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@

package v1

import "sigs.k8s.io/kubebuilder/v3/pkg/model/resource"
import (
"sigs.k8s.io/kubebuilder/v3/pkg/model/resource"

"github.com/vmware-tanzu-labs/operator-builder/internal/workload/v1/rbac"
)

// WorkloadIdentifier defines an interface for identifying any workload.
type WorkloadIdentifier interface {
Expand Down Expand Up @@ -51,7 +55,7 @@ type WorkloadAPIBuilder interface {
GetComponents() []*ComponentWorkload
GetSourceFiles() *[]SourceFile
GetAPISpecFields() *APIFields
GetRBACRules() *[]RBACRule
GetRBACRules() *[]rbac.Rule
GetComponentResource(domain, repo string, clusterScoped bool) *resource.Resource
GetFuncNames() (createFuncNames, initFuncNames []string)
GetRootCommand() *CliCommand
Expand Down
Loading

0 comments on commit f2daa61

Please sign in to comment.