Option to customize NamespaceTransfomer role binding subject handling

This commit is contained in:
Katrina Verey
2022-07-08 14:18:25 -04:00
parent ab09d27ec7
commit 0c37ee89af
5 changed files with 400 additions and 57 deletions

View File

@@ -10,14 +10,16 @@ import (
"sigs.k8s.io/kustomize/api/filters/namespace"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/types"
"sigs.k8s.io/kustomize/kyaml/errors"
"sigs.k8s.io/yaml"
)
// Change or set the namespace of non-cluster level resources.
type plugin struct {
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
FieldSpecs []types.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
UnsetOnly bool `json:"unsetOnly" yaml:"unsetOnly"`
types.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
FieldSpecs []types.FieldSpec `json:"fieldSpecs,omitempty" yaml:"fieldSpecs,omitempty"`
UnsetOnly bool `json:"unsetOnly" yaml:"unsetOnly"`
SetRoleBindingSubjects namespace.RoleBindingSubjectMode `json:"setRoleBindingSubjects" yaml:"setRoleBindingSubjects"`
}
//noinspection GoUnusedGlobalVariable
@@ -27,7 +29,21 @@ func (p *plugin) Config(
_ *resmap.PluginHelpers, c []byte) (err error) {
p.Namespace = ""
p.FieldSpecs = nil
return yaml.Unmarshal(c, p)
if err := yaml.Unmarshal(c, p); err != nil {
return errors.WrapPrefixf(err, "unmarshalling NamespaceTransformer config")
}
switch p.SetRoleBindingSubjects {
case namespace.AllServiceAccountSubjects, namespace.DefaultSubjectsOnly, namespace.NoSubjects:
// valid
case namespace.SubjectModeUnspecified:
p.SetRoleBindingSubjects = namespace.DefaultSubjectsOnly
default:
return errors.Errorf("invalid value %q for setRoleBindingSubjects: "+
"must be one of %q, %q or %q", p.SetRoleBindingSubjects,
namespace.DefaultSubjectsOnly, namespace.NoSubjects, namespace.AllServiceAccountSubjects)
}
return nil
}
func (p *plugin) Transform(m resmap.ResMap) error {
@@ -41,9 +57,10 @@ func (p *plugin) Transform(m resmap.ResMap) error {
}
r.StorePreviousId()
if err := r.ApplyFilter(namespace.Filter{
Namespace: p.Namespace,
FsSlice: p.FieldSpecs,
UnsetOnly: p.UnsetOnly,
Namespace: p.Namespace,
FsSlice: p.FieldSpecs,
SetRoleBindingSubjects: p.SetRoleBindingSubjects,
UnsetOnly: p.UnsetOnly,
}); err != nil {
return err
}

View File

@@ -14,6 +14,12 @@ const defaultFieldSpecs = `
fieldSpecs:
- path: metadata/namespace
create: true
- path: subjects/namespace
kind: RoleBinding
group: rbac.authorization.k8s.io
- path: subjects/namespace
kind: ClusterRoleBinding
group: rbac.authorization.k8s.io
- path: subjects
kind: RoleBinding
group: rbac.authorization.k8s.io
@@ -419,3 +425,278 @@ spec:
namespace: original
`)
}
func TestNamespaceTransformer_RoleBindingSubjectMode(t *testing.T) {
th := kusttest_test.MakeEnhancedHarness(t).
PrepBuiltin("NamespaceTransformer")
defer th.Reset()
defaultInput := `
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: manager-rolebinding
subjects:
- kind: ServiceAccount
name: default
namespace: system
- kind: ServiceAccount
name: service-account
namespace: system
- kind: ServiceAccount
name: another
namespace: random
- kind: ServiceAccount
name: without-namespace
- kind: Unrecognized
name: no-namespace
- apiGroup: rbac.authorization.k8s.io
kind: User
name: alice@example.com
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: frontend-admins
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:serviceaccounts:qa
`
tests := []struct {
name string
input string
transformerConfig string
expected string
}{
{
name: "target ALL service account subjects",
input: defaultInput,
transformerConfig: `
apiVersion: builtin
kind: NamespaceTransformer
metadata:
name: notImportantHere
namespace: test
setRoleBindingSubjects: allServiceAccounts
` + defaultFieldSpecs,
expected: `
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: manager-rolebinding
subjects:
- kind: ServiceAccount
name: default
namespace: test
- kind: ServiceAccount
name: service-account
namespace: test
- kind: ServiceAccount
name: another
namespace: test
- kind: ServiceAccount
name: without-namespace
namespace: test
- kind: Unrecognized
name: no-namespace
- apiGroup: rbac.authorization.k8s.io
kind: User
name: alice@example.com
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: frontend-admins
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:serviceaccounts:qa
`,
},
{
name: "target ALL subjects, role binding fieldspecs missing",
input: defaultInput,
transformerConfig: `
apiVersion: builtin
kind: NamespaceTransformer
metadata:
name: notImportantHere
namespace: test
setRoleBindingSubjects: allServiceAccounts
fieldSpecs:
- path: metadata/namespace
create: true
`,
expected: `
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: manager-rolebinding
subjects:
- kind: ServiceAccount
name: default
namespace: test
- kind: ServiceAccount
name: service-account
namespace: test
- kind: ServiceAccount
name: another
namespace: test
- kind: ServiceAccount
name: without-namespace
namespace: test
- kind: Unrecognized
name: no-namespace
- apiGroup: rbac.authorization.k8s.io
kind: User
name: alice@example.com
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: frontend-admins
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:serviceaccounts:qa
`,
},
{
name: "target ALL UNSET service account subjects",
input: defaultInput,
transformerConfig: `
apiVersion: builtin
kind: NamespaceTransformer
metadata:
name: notImportantHere
namespace: test
setRoleBindingSubjects: allServiceAccounts
unsetOnly: true
` + defaultFieldSpecs,
expected: `
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: manager-rolebinding
subjects:
- kind: ServiceAccount
name: default
namespace: system
- kind: ServiceAccount
name: service-account
namespace: system
- kind: ServiceAccount
name: another
namespace: random
- kind: ServiceAccount
name: without-namespace
namespace: test
- kind: Unrecognized
name: no-namespace
- apiGroup: rbac.authorization.k8s.io
kind: User
name: alice@example.com
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: frontend-admins
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:serviceaccounts:qa
`,
},
{
name: "target NO subjects",
input: defaultInput,
transformerConfig: `
apiVersion: builtin
kind: NamespaceTransformer
metadata:
name: notImportantHere
namespace: test
setRoleBindingSubjects: none
` + defaultFieldSpecs,
expected: defaultInput,
},
{
name: "target subject named 'default' (explicitly)",
input: defaultInput,
transformerConfig: `
apiVersion: builtin
kind: NamespaceTransformer
metadata:
name: notImportantHere
namespace: test
setRoleBindingSubjects: defaultOnly
` + defaultFieldSpecs,
expected: `
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: manager-rolebinding
subjects:
- kind: ServiceAccount
name: default
namespace: test
- kind: ServiceAccount
name: service-account
namespace: system
- kind: ServiceAccount
name: another
namespace: random
- kind: ServiceAccount
name: without-namespace
- kind: Unrecognized
name: no-namespace
- apiGroup: rbac.authorization.k8s.io
kind: User
name: alice@example.com
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: frontend-admins
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:serviceaccounts:qa
`,
},
{
name: "target subject named 'default' (mode unspecified)",
input: defaultInput,
transformerConfig: `
apiVersion: builtin
kind: NamespaceTransformer
metadata:
name: notImportantHere
namespace: test
` + defaultFieldSpecs,
expected: `
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: manager-rolebinding
subjects:
- kind: ServiceAccount
name: default
namespace: test
- kind: ServiceAccount
name: service-account
namespace: system
- kind: ServiceAccount
name: another
namespace: random
- kind: ServiceAccount
name: without-namespace
- kind: Unrecognized
name: no-namespace
- apiGroup: rbac.authorization.k8s.io
kind: User
name: alice@example.com
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: frontend-admins
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:serviceaccounts:qa
`,
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
th.RunTransformerAndCheckResult(test.transformerConfig, test.input, test.expected)
})
}
}