mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-14 11:57:48 +00:00
fix: block generate policies when lack of permission to operate downstream resources (#6610)
* debug Signed-off-by: ShutingZhao <shuting@nirmata.com> * return on errors only Signed-off-by: ShutingZhao <shuting@nirmata.com> * update clusterrolebinding Signed-off-by: ShutingZhao <shuting@nirmata.com> * update clusterrolebinding Signed-off-by: ShutingZhao <shuting@nirmata.com> * remove debug Signed-off-by: ShutingZhao <shuting@nirmata.com> * add kuttl tests Signed-off-by: ShutingZhao <shuting@nirmata.com> * fix ns Signed-off-by: ShutingZhao <shuting@nirmata.com> --------- Signed-off-by: ShutingZhao <shuting@nirmata.com>
This commit is contained in:
parent
f5e96e6ef2
commit
6249ab70e8
58 changed files with 587 additions and 64 deletions
|
@ -14,5 +14,8 @@ subjects:
|
|||
- kind: ServiceAccount
|
||||
name: {{ template "kyverno.background-controller.serviceAccountName" . }}
|
||||
namespace: {{ template "kyverno.namespace" . }}
|
||||
- kind: ServiceAccount
|
||||
name: {{ template "kyverno.admission-controller.serviceAccountName" . }}
|
||||
namespace: {{ template "kyverno.namespace" . }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package policy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
|
@ -14,7 +15,7 @@ import (
|
|||
|
||||
// Validation provides methods to validate a rule
|
||||
type Validation interface {
|
||||
Validate() (string, error)
|
||||
Validate(ctx context.Context) (string, error)
|
||||
}
|
||||
|
||||
// validateAction performs validation on the rule actions
|
||||
|
@ -27,11 +28,10 @@ func validateActions(idx int, rule *kyvernov1.Rule, client dclient.Interface, mo
|
|||
}
|
||||
|
||||
var checker Validation
|
||||
|
||||
// Mutate
|
||||
if rule.HasMutate() {
|
||||
checker = mutate.NewMutateFactory(rule.Mutation)
|
||||
if path, err := checker.Validate(); err != nil {
|
||||
checker = mutate.NewMutateFactory(rule.Mutation, client)
|
||||
if path, err := checker.Validate(context.TODO()); err != nil {
|
||||
return fmt.Errorf("path: spec.rules[%d].mutate.%s.: %v", idx, path, err)
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ func validateActions(idx int, rule *kyvernov1.Rule, client dclient.Interface, mo
|
|||
// Validate
|
||||
if rule.HasValidate() {
|
||||
checker = validate.NewValidateFactory(&rule.Validation)
|
||||
if path, err := checker.Validate(); err != nil {
|
||||
if path, err := checker.Validate(context.TODO()); err != nil {
|
||||
return fmt.Errorf("path: spec.rules[%d].validate.%s.: %v", idx, path, err)
|
||||
}
|
||||
}
|
||||
|
@ -51,12 +51,12 @@ func validateActions(idx int, rule *kyvernov1.Rule, client dclient.Interface, mo
|
|||
// this need to modified to use different implementation for online and offline mode
|
||||
if mock {
|
||||
checker = generate.NewFakeGenerate(rule.Generation)
|
||||
if path, err := checker.Validate(); err != nil {
|
||||
if path, err := checker.Validate(context.TODO()); err != nil {
|
||||
return fmt.Errorf("path: spec.rules[%d].generate.%s.: %v", idx, path, err)
|
||||
}
|
||||
} else {
|
||||
checker = generate.NewGenerateFactory(client, rule.Generation, logging.GlobalLogger())
|
||||
if path, err := checker.Validate(); err != nil {
|
||||
if path, err := checker.Validate(context.TODO()); err != nil {
|
||||
return fmt.Errorf("path: spec.rules[%d].generate.%s.: %v", idx, path, err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ func NewGenerateFactory(client dclient.Interface, rule kyvernov1.Generation, log
|
|||
}
|
||||
|
||||
// Validate validates the 'generate' rule
|
||||
func (g *Generate) Validate() (string, error) {
|
||||
func (g *Generate) Validate(ctx context.Context) (string, error) {
|
||||
rule := g.rule
|
||||
if rule.GetData() != nil && rule.Clone != (kyvernov1.CloneFrom{}) {
|
||||
return "", fmt.Errorf("only one of data or clone can be specified")
|
||||
|
@ -91,12 +91,12 @@ func (g *Generate) Validate() (string, error) {
|
|||
if len(rule.CloneList.Kinds) != 0 {
|
||||
for _, kind = range rule.CloneList.Kinds {
|
||||
_, kind = kubeutils.GetKindFromGVK(kind)
|
||||
if err := g.canIGenerate(kind, namespace); err != nil {
|
||||
if err := g.canIGenerate(ctx, kind, namespace); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if err := g.canIGenerate(kind, namespace); err != nil {
|
||||
if err := g.canIGenerate(ctx, kind, namespace); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ func (g *Generate) validateClone(c kyvernov1.CloneFrom, cl kyvernov1.CloneList,
|
|||
return "", err
|
||||
}
|
||||
if !ok {
|
||||
return "", fmt.Errorf("kyverno does not have permissions to 'get' resource %s/%s. Update permissions in ClusterRole 'kyverno:generate'", kind, namespace)
|
||||
return "", fmt.Errorf("kyverno does not have permissions to 'get' resource %s/%s. Update permissions in ClusterRole 'kyverno:background-controller:additional'", kind, namespace)
|
||||
}
|
||||
} else {
|
||||
g.log.V(4).Info("name & namespace uses variables, so cannot be resolved. Skipping Auth Checks.")
|
||||
|
@ -128,46 +128,46 @@ func (g *Generate) validateClone(c kyvernov1.CloneFrom, cl kyvernov1.CloneList,
|
|||
}
|
||||
|
||||
// canIGenerate returns a error if kyverno cannot perform operations
|
||||
func (g *Generate) canIGenerate(kind, namespace string) error {
|
||||
func (g *Generate) canIGenerate(ctx context.Context, kind, namespace string) error {
|
||||
// Skip if there is variable defined
|
||||
authCheck := g.authCheck
|
||||
if !regex.IsVariable(kind) && !regex.IsVariable(namespace) {
|
||||
// CREATE
|
||||
ok, err := authCheck.CanICreate(context.TODO(), kind, namespace)
|
||||
ok, err := authCheck.CanICreate(ctx, kind, namespace)
|
||||
if err != nil {
|
||||
// machinery error
|
||||
return err
|
||||
}
|
||||
if !ok {
|
||||
return fmt.Errorf("kyverno does not have permissions to 'create' resource %s/%s. Update permissions in ClusterRole 'kyverno:generate'", kind, namespace)
|
||||
return fmt.Errorf("kyverno does not have permissions to 'create' resource %s/%s. Update permissions in ClusterRole 'kyverno:background-controller:additional'", kind, namespace)
|
||||
}
|
||||
// UPDATE
|
||||
ok, err = authCheck.CanIUpdate(context.TODO(), kind, namespace)
|
||||
ok, err = authCheck.CanIUpdate(ctx, kind, namespace)
|
||||
if err != nil {
|
||||
// machinery error
|
||||
return err
|
||||
}
|
||||
if !ok {
|
||||
return fmt.Errorf("kyverno does not have permissions to 'update' resource %s/%s. Update permissions in ClusterRole 'kyverno:generate'", kind, namespace)
|
||||
return fmt.Errorf("kyverno does not have permissions to 'update' resource %s/%s. Update permissions in ClusterRole 'kyverno:background-controller:additional'", kind, namespace)
|
||||
}
|
||||
// GET
|
||||
ok, err = authCheck.CanIGet(context.TODO(), kind, namespace)
|
||||
ok, err = authCheck.CanIGet(ctx, kind, namespace)
|
||||
if err != nil {
|
||||
// machinery error
|
||||
return err
|
||||
}
|
||||
if !ok {
|
||||
return fmt.Errorf("kyverno does not have permissions to 'get' resource %s/%s. Update permissions in ClusterRole 'kyverno:generate'", kind, namespace)
|
||||
return fmt.Errorf("kyverno does not have permissions to 'get' resource %s/%s. Update permissions in ClusterRole 'kyverno:background-controller:additional'", kind, namespace)
|
||||
}
|
||||
|
||||
// DELETE
|
||||
ok, err = authCheck.CanIDelete(context.TODO(), kind, namespace)
|
||||
ok, err = authCheck.CanIDelete(ctx, kind, namespace)
|
||||
if err != nil {
|
||||
// machinery error
|
||||
return err
|
||||
}
|
||||
if !ok {
|
||||
return fmt.Errorf("kyverno does not have permissions to 'delete' resource %s/%s. Update permissions in ClusterRole 'kyverno:generate'", kind, namespace)
|
||||
return fmt.Errorf("kyverno does not have permissions to 'delete' resource %s/%s. Update permissions in ClusterRole 'kyverno:background-controller:additional'", kind, namespace)
|
||||
}
|
||||
} else {
|
||||
g.log.V(4).Info("name & namespace uses variables, so cannot be resolved. Skipping Auth Checks.")
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package generate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
|
@ -34,7 +35,7 @@ func Test_Validate_Generate(t *testing.T) {
|
|||
err := json.Unmarshal(rawGenerate, &genRule)
|
||||
assert.NilError(t, err)
|
||||
checker := NewFakeGenerate(genRule)
|
||||
if _, err := checker.Validate(); err != nil {
|
||||
if _, err := checker.Validate(context.TODO()); err != nil {
|
||||
assert.Assert(t, err != nil)
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +67,7 @@ func Test_Validate_Generate_HasAnchors(t *testing.T) {
|
|||
err = json.Unmarshal(rawGenerate, &genRule)
|
||||
assert.NilError(t, err)
|
||||
checker := NewFakeGenerate(genRule)
|
||||
if _, err := checker.Validate(); err != nil {
|
||||
if _, err := checker.Validate(context.TODO()); err != nil {
|
||||
assert.Assert(t, err != nil)
|
||||
}
|
||||
|
||||
|
@ -83,7 +84,7 @@ func Test_Validate_Generate_HasAnchors(t *testing.T) {
|
|||
err = json.Unmarshal(rawGenerate, &genRule)
|
||||
assert.NilError(t, err)
|
||||
checker = NewFakeGenerate(genRule)
|
||||
if _, err := checker.Validate(); err != nil {
|
||||
if _, err := checker.Validate(context.TODO()); err != nil {
|
||||
assert.Assert(t, err != nil)
|
||||
}
|
||||
}
|
||||
|
|
37
pkg/policy/mutate/auth.go
Normal file
37
pkg/policy/mutate/auth.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
package mutate
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/kyverno/kyverno/pkg/auth"
|
||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
)
|
||||
|
||||
type authChecker struct {
|
||||
client dclient.Interface
|
||||
}
|
||||
|
||||
type AuthChecker interface {
|
||||
CanICreate(ctx context.Context, kind, namespace, subresource string) (bool, error)
|
||||
CanIUpdate(ctx context.Context, kind, namespace, subresource string) (bool, error)
|
||||
CanIGet(ctx context.Context, kind, namespace, subresource string) (bool, error)
|
||||
}
|
||||
|
||||
func newAuthChecker(client dclient.Interface) AuthChecker {
|
||||
return &authChecker{client: client}
|
||||
}
|
||||
|
||||
func (a *authChecker) CanICreate(ctx context.Context, kind, namespace, subresource string) (bool, error) {
|
||||
checker := auth.NewCanI(a.client.Discovery(), a.client.GetKubeClient().AuthorizationV1().SelfSubjectAccessReviews(), kind, namespace, "create", subresource)
|
||||
return checker.RunAccessCheck(ctx)
|
||||
}
|
||||
|
||||
func (a *authChecker) CanIUpdate(ctx context.Context, kind, namespace, subresource string) (bool, error) {
|
||||
checker := auth.NewCanI(a.client.Discovery(), a.client.GetKubeClient().AuthorizationV1().SelfSubjectAccessReviews(), kind, namespace, "update", subresource)
|
||||
return checker.RunAccessCheck(ctx)
|
||||
}
|
||||
|
||||
func (a *authChecker) CanIGet(ctx context.Context, kind, namespace, subresource string) (bool, error) {
|
||||
checker := auth.NewCanI(a.client.Discovery(), a.client.GetKubeClient().AuthorizationV1().SelfSubjectAccessReviews(), kind, namespace, "get", subresource)
|
||||
return checker.RunAccessCheck(ctx)
|
||||
}
|
|
@ -1,27 +1,34 @@
|
|||
package mutate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
"github.com/kyverno/kyverno/pkg/engine/variables/regex"
|
||||
"github.com/kyverno/kyverno/pkg/utils/api"
|
||||
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
|
||||
"go.uber.org/multierr"
|
||||
v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
)
|
||||
|
||||
// Mutate provides implementation to validate 'mutate' rule
|
||||
type Mutate struct {
|
||||
mutation kyvernov1.Mutation
|
||||
mutation kyvernov1.Mutation
|
||||
authChecker AuthChecker
|
||||
}
|
||||
|
||||
// NewMutateFactory returns a new instance of Mutate validation checker
|
||||
func NewMutateFactory(m kyvernov1.Mutation) *Mutate {
|
||||
func NewMutateFactory(m kyvernov1.Mutation, client dclient.Interface) *Mutate {
|
||||
return &Mutate{
|
||||
mutation: m,
|
||||
mutation: m,
|
||||
authChecker: newAuthChecker(client),
|
||||
}
|
||||
}
|
||||
|
||||
// Validate validates the 'mutate' rule
|
||||
func (m *Mutate) Validate() (string, error) {
|
||||
func (m *Mutate) Validate(ctx context.Context) (string, error) {
|
||||
if m.hasForEach() {
|
||||
if m.hasPatchStrategicMerge() || m.hasPatchesJSON6902() {
|
||||
return "foreach", fmt.Errorf("only one of `foreach`, `patchStrategicMerge`, or `patchesJson6902` is allowed")
|
||||
|
@ -34,6 +41,11 @@ func (m *Mutate) Validate() (string, error) {
|
|||
return "foreach", fmt.Errorf("only one of `patchStrategicMerge` or `patchesJson6902` is allowed")
|
||||
}
|
||||
|
||||
if m.mutation.Targets != nil {
|
||||
if err := m.validateAuth(ctx, m.mutation.Targets); err != nil {
|
||||
return "targets", fmt.Errorf("auth check fails, require additional privileges, update the ClusterRole 'kyverno:background-controller:additional':%v", err)
|
||||
}
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
|
@ -77,3 +89,30 @@ func (m *Mutate) hasPatchStrategicMerge() bool {
|
|||
func (m *Mutate) hasPatchesJSON6902() bool {
|
||||
return m.mutation.PatchesJSON6902 != ""
|
||||
}
|
||||
|
||||
func (m *Mutate) validateAuth(ctx context.Context, targets []kyvernov1.ResourceSpec) error {
|
||||
var errs []error
|
||||
for _, target := range targets {
|
||||
if !regex.IsVariable(target.Namespace) {
|
||||
_, _, k, sub := kubeutils.ParseKindSelector(target.Kind)
|
||||
if ok, err := m.authChecker.CanICreate(ctx, k, target.Namespace, sub); err != nil {
|
||||
errs = append(errs, err)
|
||||
} else if !ok {
|
||||
errs = append(errs, fmt.Errorf("cannot %s %s/%s in namespace %s", "create", k, sub, target.Namespace))
|
||||
}
|
||||
|
||||
if ok, err := m.authChecker.CanIUpdate(ctx, k, target.Namespace, sub); err != nil {
|
||||
errs = append(errs, err)
|
||||
} else if !ok {
|
||||
errs = append(errs, fmt.Errorf("cannot %s %s/%s in namespace %s", "update", k, sub, target.Namespace))
|
||||
}
|
||||
|
||||
if ok, err := m.authChecker.CanIGet(ctx, k, target.Namespace, sub); err != nil {
|
||||
errs = append(errs, err)
|
||||
} else if !ok {
|
||||
errs = append(errs, fmt.Errorf("cannot %s %s/%s in namespace %s", "get", k, sub, target.Namespace))
|
||||
}
|
||||
}
|
||||
}
|
||||
return multierr.Combine(errs...)
|
||||
}
|
||||
|
|
|
@ -252,7 +252,9 @@ func Validate(policy, oldPolicy kyvernov1.PolicyInterface, client dclient.Interf
|
|||
// validate Cluster Resources in namespaced policy
|
||||
// For namespaced policy, ClusterResource type field and values are not allowed in match and exclude
|
||||
if namespaced {
|
||||
return warnings, checkClusterResourceInMatchAndExclude(rule, clusterResources, policy.GetNamespace(), mock, res)
|
||||
if err := checkClusterResourceInMatchAndExclude(rule, clusterResources, policy.GetNamespace(), mock, res); err != nil {
|
||||
return warnings, err
|
||||
}
|
||||
}
|
||||
|
||||
if err := validateActions(i, &rules[i], client, mock); err != nil {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package validate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
|
@ -24,7 +25,7 @@ func NewValidateFactory(rule *kyvernov1.Validation) *Validate {
|
|||
}
|
||||
|
||||
// Validate validates the 'validate' rule
|
||||
func (v *Validate) Validate() (string, error) {
|
||||
func (v *Validate) Validate(ctx context.Context) (string, error) {
|
||||
if err := v.validateElements(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package validate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
|
@ -17,7 +18,7 @@ func Test_Validate_OverlayPattern_Empty(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
checker := NewValidateFactory(&validation)
|
||||
if _, err := checker.Validate(); err != nil {
|
||||
if _, err := checker.Validate(context.TODO()); err != nil {
|
||||
assert.Assert(t, err != nil)
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +32,7 @@ func Test_Validate_OverlayPattern_Nil_PatternAnypattern(t *testing.T) {
|
|||
err := json.Unmarshal(rawValidation, &validation)
|
||||
assert.NilError(t, err)
|
||||
checker := NewValidateFactory(&validation)
|
||||
if _, err := checker.Validate(); err != nil {
|
||||
if _, err := checker.Validate(context.TODO()); err != nil {
|
||||
assert.Assert(t, err != nil)
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +70,7 @@ func Test_Validate_OverlayPattern_Exist_PatternAnypattern(t *testing.T) {
|
|||
err := json.Unmarshal(rawValidation, &validation)
|
||||
assert.NilError(t, err)
|
||||
checker := NewValidateFactory(&validation)
|
||||
if _, err := checker.Validate(); err != nil {
|
||||
if _, err := checker.Validate(context.TODO()); err != nil {
|
||||
assert.Assert(t, err != nil)
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +108,7 @@ func Test_Validate_OverlayPattern_Valid(t *testing.T) {
|
|||
err := json.Unmarshal(rawValidation, &validation)
|
||||
assert.NilError(t, err)
|
||||
checker := NewValidateFactory(&validation)
|
||||
if _, err := checker.Validate(); err != nil {
|
||||
if _, err := checker.Validate(context.TODO()); err != nil {
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
}
|
||||
|
@ -140,7 +141,7 @@ func Test_Validate_ExistingAnchor_AnchorOnMap(t *testing.T) {
|
|||
err := json.Unmarshal(rawValidation, &validation)
|
||||
assert.NilError(t, err)
|
||||
checker := NewValidateFactory(&validation)
|
||||
if _, err := checker.Validate(); err != nil {
|
||||
if _, err := checker.Validate(context.TODO()); err != nil {
|
||||
assert.Assert(t, err != nil)
|
||||
}
|
||||
}
|
||||
|
@ -170,7 +171,7 @@ func Test_Validate_ExistingAnchor_AnchorOnString(t *testing.T) {
|
|||
err := json.Unmarshal(rawValidation, &validation)
|
||||
assert.NilError(t, err)
|
||||
checker := NewValidateFactory(&validation)
|
||||
if _, err := checker.Validate(); err != nil {
|
||||
if _, err := checker.Validate(context.TODO()); err != nil {
|
||||
assert.Assert(t, err != nil)
|
||||
}
|
||||
}
|
||||
|
@ -203,7 +204,7 @@ func Test_Validate_ExistingAnchor_Valid(t *testing.T) {
|
|||
err = json.Unmarshal(rawValidation, &validation)
|
||||
assert.NilError(t, err)
|
||||
checker := NewValidateFactory(&validation)
|
||||
if _, err := checker.Validate(); err != nil {
|
||||
if _, err := checker.Validate(context.TODO()); err != nil {
|
||||
assert.Assert(t, err != nil)
|
||||
}
|
||||
rawValidation = []byte(`
|
||||
|
@ -228,7 +229,7 @@ func Test_Validate_ExistingAnchor_Valid(t *testing.T) {
|
|||
err = json.Unmarshal(rawValidation, &validation)
|
||||
assert.NilError(t, err)
|
||||
checker = NewValidateFactory(&validation)
|
||||
if _, err := checker.Validate(); err != nil {
|
||||
if _, err := checker.Validate(context.TODO()); err != nil {
|
||||
assert.Assert(t, err != nil)
|
||||
}
|
||||
|
||||
|
@ -269,7 +270,7 @@ func Test_Validate_Validate_ValidAnchor(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
checker := NewValidateFactory(&validate)
|
||||
if _, err := checker.Validate(); err != nil {
|
||||
if _, err := checker.Validate(context.TODO()); err != nil {
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
|
@ -291,7 +292,7 @@ func Test_Validate_Validate_ValidAnchor(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
checker = NewValidateFactory(&validate)
|
||||
if _, err := checker.Validate(); err != nil {
|
||||
if _, err := checker.Validate(context.TODO()); err != nil {
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
}
|
||||
|
@ -318,7 +319,7 @@ func Test_Validate_Validate_Mismatched(t *testing.T) {
|
|||
err := json.Unmarshal(rawValidate, &validate)
|
||||
assert.NilError(t, err)
|
||||
checker := NewValidateFactory(&validate)
|
||||
if _, err := checker.Validate(); err != nil {
|
||||
if _, err := checker.Validate(context.TODO()); err != nil {
|
||||
assert.Assert(t, err != nil)
|
||||
}
|
||||
}
|
||||
|
@ -348,7 +349,7 @@ func Test_Validate_Validate_Unsupported(t *testing.T) {
|
|||
err = json.Unmarshal(rawValidate, &validate)
|
||||
assert.NilError(t, err)
|
||||
checker := NewValidateFactory(&validate)
|
||||
if _, err := checker.Validate(); err != nil {
|
||||
if _, err := checker.Validate(context.TODO()); err != nil {
|
||||
assert.Assert(t, err != nil)
|
||||
}
|
||||
|
||||
|
@ -374,7 +375,7 @@ func Test_Validate_Validate_Unsupported(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
|
||||
checker = NewValidateFactory(&validate)
|
||||
if _, err := checker.Validate(); err != nil {
|
||||
if _, err := checker.Validate(context.TODO()); err != nil {
|
||||
assert.Assert(t, err != nil)
|
||||
}
|
||||
|
||||
|
|
|
@ -32,11 +32,10 @@ spec:
|
|||
example.com/sm-sync: "true"
|
||||
generate:
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
kind: ConfigMap
|
||||
name: "{{request.object.metadata.name}}-modify"
|
||||
namespace: match-trigger-namespace-ns
|
||||
synchronize: true
|
||||
data:
|
||||
type: Opaque
|
||||
data:
|
||||
modify: Zm9v
|
|
@ -1,8 +1,7 @@
|
|||
apiVersion: v1
|
||||
data:
|
||||
modify: Zm9v
|
||||
kind: Secret
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: regcred-modify
|
||||
namespace: match-trigger-namespace-ns
|
||||
type: Opaque
|
||||
namespace: match-trigger-namespace-ns
|
|
@ -37,11 +37,10 @@ spec:
|
|||
example.com/sm-sync: "true"
|
||||
generate:
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
kind: ConfigMap
|
||||
name: "{{request.object.metadata.name}}-modify"
|
||||
namespace: non-match-trigger-namespace-ns
|
||||
synchronize: true
|
||||
data:
|
||||
type: Opaque
|
||||
data:
|
||||
modify: Zm9v
|
|
@ -1,8 +1,7 @@
|
|||
apiVersion: v1
|
||||
data:
|
||||
modify: Zm9v
|
||||
kind: Secret
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: regcred-modify
|
||||
namespace: non-match-trigger-namespace-ns
|
||||
type: Opaque
|
||||
namespace: non-match-trigger-namespace-ns
|
|
@ -3,7 +3,7 @@ kind: ClusterPolicy
|
|||
metadata:
|
||||
name: generate-update-rule-spec
|
||||
spec:
|
||||
generateExistingOnPolicyUpdate: false
|
||||
generateExisting: false
|
||||
rules:
|
||||
- name: k-kafka-address
|
||||
match:
|
||||
|
|
|
@ -3,7 +3,7 @@ kind: ClusterPolicy
|
|||
metadata:
|
||||
name: generate-update-rule-spec
|
||||
spec:
|
||||
generateExistingOnPolicyUpdate: false
|
||||
generateExisting: false
|
||||
rules:
|
||||
- name: k-kafka-address
|
||||
match:
|
||||
|
|
|
@ -3,7 +3,7 @@ kind: ClusterPolicy
|
|||
metadata:
|
||||
name: generate-update-rule-spec
|
||||
spec:
|
||||
generateExistingOnPolicyUpdate: false
|
||||
generateExisting: false
|
||||
rules:
|
||||
- name: k-kafka-address
|
||||
match:
|
||||
|
|
|
@ -3,7 +3,7 @@ kind: ClusterPolicy
|
|||
metadata:
|
||||
name: generate-update-rule-spec
|
||||
spec:
|
||||
generateExistingOnPolicyUpdate: false
|
||||
generateExisting: false
|
||||
rules:
|
||||
- name: k-kafka-address
|
||||
match:
|
||||
|
|
|
@ -3,7 +3,7 @@ kind: ClusterPolicy
|
|||
metadata:
|
||||
name: generate-update-rule-spec
|
||||
spec:
|
||||
generateExistingOnPolicyUpdate: false
|
||||
generateExisting: false
|
||||
rules:
|
||||
- name: i-changed-this
|
||||
match:
|
||||
|
|
|
@ -3,7 +3,7 @@ kind: ClusterPolicy
|
|||
metadata:
|
||||
name: generate-update-rule-spec
|
||||
spec:
|
||||
generateExistingOnPolicyUpdate: false
|
||||
generateExisting: false
|
||||
rules:
|
||||
- name: k-kafka-address
|
||||
match:
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
apiVersion: kuttl.dev/v1beta1
|
||||
kind: TestStep
|
||||
apply:
|
||||
- file: policy.yaml
|
||||
shouldFail: true
|
|
@ -0,0 +1,16 @@
|
|||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: kyverno:background-controller:additional
|
||||
rules:
|
||||
- apiGroups:
|
||||
- '*'
|
||||
resources:
|
||||
- serviceaccounts
|
||||
verbs:
|
||||
- create
|
||||
- update
|
||||
- patch
|
||||
- delete
|
||||
- get
|
||||
- list
|
|
@ -0,0 +1,6 @@
|
|||
apiVersion: kuttl.dev/v1beta1
|
||||
kind: TestStep
|
||||
apply:
|
||||
- policy.yaml
|
||||
assert:
|
||||
- policy-assert.yaml
|
|
@ -0,0 +1,27 @@
|
|||
## reset changed clusterrole for the rest of the tests
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: kyverno:background-controller:additional
|
||||
rules:
|
||||
- apiGroups:
|
||||
- '*'
|
||||
resources:
|
||||
- configmaps
|
||||
- networkpolicies
|
||||
- resourcequotas
|
||||
- secrets
|
||||
- roles
|
||||
- rolebindings
|
||||
- limitranges
|
||||
- namespaces
|
||||
- nodes
|
||||
- nodes/status
|
||||
- pods
|
||||
verbs:
|
||||
- create
|
||||
- update
|
||||
- patch
|
||||
- delete
|
||||
- get
|
||||
- list
|
|
@ -0,0 +1,12 @@
|
|||
## Description
|
||||
|
||||
This test ensures that a generate policy is denied when it does not have corresponding permissions to generate the downstream resource.
|
||||
|
||||
## Expected Behavior
|
||||
|
||||
The test fails if the policy creation is allowed, otherwise passes.
|
||||
|
||||
|
||||
## Reference Issue(s)
|
||||
|
||||
https://github.com/kyverno/kyverno/issues/6584
|
|
@ -0,0 +1,9 @@
|
|||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: cpol-validate-create-sa-permission
|
||||
status:
|
||||
conditions:
|
||||
- reason: Succeeded
|
||||
status: "True"
|
||||
type: Ready
|
|
@ -0,0 +1,21 @@
|
|||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: cpol-validate-create-sa-permission
|
||||
spec:
|
||||
rules:
|
||||
- name: clone-secret
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- ConfigMap
|
||||
generate:
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
name: cpol-validate-create-sa-permission-sa
|
||||
namespace: default
|
||||
synchronize: true
|
||||
clone:
|
||||
namespace: default
|
||||
name: regcred
|
|
@ -4,7 +4,7 @@ metadata:
|
|||
name: generate-update-rule-spec
|
||||
namespace: default
|
||||
spec:
|
||||
generateExistingOnPolicyUpdate: false
|
||||
generateExisting: false
|
||||
rules:
|
||||
- name: k-kafka-address
|
||||
match:
|
||||
|
|
|
@ -4,7 +4,7 @@ metadata:
|
|||
name: generate-update-rule-spec
|
||||
namespace: default
|
||||
spec:
|
||||
generateExistingOnPolicyUpdate: false
|
||||
generateExisting: false
|
||||
rules:
|
||||
- name: k-kafka-address
|
||||
match:
|
||||
|
|
|
@ -4,7 +4,7 @@ metadata:
|
|||
name: generate-update-rule-spec
|
||||
namespace: default
|
||||
spec:
|
||||
generateExistingOnPolicyUpdate: false
|
||||
generateExisting: false
|
||||
rules:
|
||||
- name: k-kafka-address
|
||||
match:
|
||||
|
|
|
@ -4,7 +4,7 @@ metadata:
|
|||
name: generate-update-rule-spec
|
||||
namespace: default
|
||||
spec:
|
||||
generateExistingOnPolicyUpdate: false
|
||||
generateExisting: false
|
||||
rules:
|
||||
- name: k-kafka-address
|
||||
match:
|
||||
|
|
|
@ -4,7 +4,7 @@ metadata:
|
|||
name: generate-update-rule-spec
|
||||
namespace: default
|
||||
spec:
|
||||
generateExistingOnPolicyUpdate: false
|
||||
generateExisting: false
|
||||
rules:
|
||||
- name: i-changed-this
|
||||
match:
|
||||
|
|
|
@ -4,7 +4,7 @@ metadata:
|
|||
name: generate-update-rule-spec
|
||||
namespace: default
|
||||
spec:
|
||||
generateExistingOnPolicyUpdate: false
|
||||
generateExisting: false
|
||||
rules:
|
||||
- name: k-kafka-address
|
||||
match:
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: pol-validate-create-sa-permission-ns
|
|
@ -0,0 +1,5 @@
|
|||
apiVersion: kuttl.dev/v1beta1
|
||||
kind: TestStep
|
||||
apply:
|
||||
- file: policy.yaml
|
||||
shouldFail: true
|
|
@ -0,0 +1,16 @@
|
|||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: kyverno:background-controller:additional
|
||||
rules:
|
||||
- apiGroups:
|
||||
- '*'
|
||||
resources:
|
||||
- serviceaccounts
|
||||
verbs:
|
||||
- create
|
||||
- update
|
||||
- patch
|
||||
- delete
|
||||
- get
|
||||
- list
|
|
@ -0,0 +1,6 @@
|
|||
apiVersion: kuttl.dev/v1beta1
|
||||
kind: TestStep
|
||||
apply:
|
||||
- policy.yaml
|
||||
assert:
|
||||
- policy-assert.yaml
|
|
@ -0,0 +1,27 @@
|
|||
## reset changed clusterrole for the rest of the tests
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: kyverno:background-controller:additional
|
||||
rules:
|
||||
- apiGroups:
|
||||
- '*'
|
||||
resources:
|
||||
- configmaps
|
||||
- networkpolicies
|
||||
- resourcequotas
|
||||
- secrets
|
||||
- roles
|
||||
- rolebindings
|
||||
- limitranges
|
||||
- namespaces
|
||||
- nodes
|
||||
- nodes/status
|
||||
- pods
|
||||
verbs:
|
||||
- create
|
||||
- update
|
||||
- patch
|
||||
- delete
|
||||
- get
|
||||
- list
|
|
@ -0,0 +1,12 @@
|
|||
## Description
|
||||
|
||||
This test ensures that a generate policy is denied when it does not have corresponding permissions to generate the downstream resource.
|
||||
|
||||
## Expected Behavior
|
||||
|
||||
The test fails if the policy creation is allowed, otherwise passes.
|
||||
|
||||
|
||||
## Reference Issue(s)
|
||||
|
||||
https://github.com/kyverno/kyverno/issues/6584
|
|
@ -0,0 +1,10 @@
|
|||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: pol-validate-create-sa-permission
|
||||
namespace: pol-validate-create-sa-permission-ns
|
||||
status:
|
||||
conditions:
|
||||
- reason: Succeeded
|
||||
status: "True"
|
||||
type: Ready
|
|
@ -0,0 +1,22 @@
|
|||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: pol-validate-create-sa-permission
|
||||
namespace: pol-validate-create-sa-permission-ns
|
||||
spec:
|
||||
rules:
|
||||
- name: clone-secret
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- ConfigMap
|
||||
generate:
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
name: cpol-validate-create-sa-permission-sa
|
||||
namespace: pol-validate-create-sa-permission-ns
|
||||
synchronize: true
|
||||
clone:
|
||||
namespace: pol-validate-create-sa-permission-ns
|
||||
name: regcred
|
|
@ -0,0 +1,5 @@
|
|||
apiVersion: kuttl.dev/v1beta1
|
||||
kind: TestStep
|
||||
apply:
|
||||
- file: policy.yaml
|
||||
shouldFail: true
|
|
@ -0,0 +1,16 @@
|
|||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: kyverno:background-controller:additional
|
||||
rules:
|
||||
- apiGroups:
|
||||
- '*'
|
||||
resources:
|
||||
- serviceaccounts
|
||||
verbs:
|
||||
- create
|
||||
- update
|
||||
- patch
|
||||
- delete
|
||||
- get
|
||||
- list
|
|
@ -0,0 +1,6 @@
|
|||
apiVersion: kuttl.dev/v1beta1
|
||||
kind: TestStep
|
||||
apply:
|
||||
- policy.yaml
|
||||
assert:
|
||||
- policy-assert.yaml
|
|
@ -0,0 +1,27 @@
|
|||
## reset changed clusterrole for the rest of the tests
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: kyverno:background-controller:additional
|
||||
rules:
|
||||
- apiGroups:
|
||||
- '*'
|
||||
resources:
|
||||
- configmaps
|
||||
- networkpolicies
|
||||
- resourcequotas
|
||||
- secrets
|
||||
- roles
|
||||
- rolebindings
|
||||
- limitranges
|
||||
- namespaces
|
||||
- nodes
|
||||
- nodes/status
|
||||
- pods
|
||||
verbs:
|
||||
- create
|
||||
- update
|
||||
- patch
|
||||
- delete
|
||||
- get
|
||||
- list
|
|
@ -0,0 +1,12 @@
|
|||
## Description
|
||||
|
||||
This test ensures that a mutate existing policy is denied when it does not have corresponding permissions to generate the downstream resource.
|
||||
|
||||
## Expected Behavior
|
||||
|
||||
The test fails if the policy creation is allowed, otherwise passes.
|
||||
|
||||
|
||||
## Reference Issue(s)
|
||||
|
||||
https://github.com/kyverno/kyverno/issues/6584
|
|
@ -0,0 +1,9 @@
|
|||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: cpol-mutate-existing-auth-check
|
||||
status:
|
||||
conditions:
|
||||
- reason: Succeeded
|
||||
status: "True"
|
||||
type: Ready
|
|
@ -0,0 +1,22 @@
|
|||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: cpol-mutate-existing-auth-check
|
||||
spec:
|
||||
mutateExistingOnPolicyUpdate: true
|
||||
background: false
|
||||
rules:
|
||||
- name: label-privileged-namespaces
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Namespace
|
||||
mutate:
|
||||
targets:
|
||||
- apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
patchStrategicMerge:
|
||||
metadata:
|
||||
labels:
|
||||
foo: bar
|
|
@ -0,0 +1,4 @@
|
|||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: pol-mutate-existing-auth-check-ns
|
|
@ -0,0 +1,5 @@
|
|||
apiVersion: kuttl.dev/v1beta1
|
||||
kind: TestStep
|
||||
apply:
|
||||
- file: policy.yaml
|
||||
shouldFail: true
|
|
@ -0,0 +1,16 @@
|
|||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: kyverno:background-controller:additional
|
||||
rules:
|
||||
- apiGroups:
|
||||
- '*'
|
||||
resources:
|
||||
- serviceaccounts
|
||||
verbs:
|
||||
- create
|
||||
- update
|
||||
- patch
|
||||
- delete
|
||||
- get
|
||||
- list
|
|
@ -0,0 +1,6 @@
|
|||
apiVersion: kuttl.dev/v1beta1
|
||||
kind: TestStep
|
||||
apply:
|
||||
- policy.yaml
|
||||
assert:
|
||||
- policy-assert.yaml
|
|
@ -0,0 +1,27 @@
|
|||
## reset changed clusterrole for the rest of the tests
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: kyverno:background-controller:additional
|
||||
rules:
|
||||
- apiGroups:
|
||||
- '*'
|
||||
resources:
|
||||
- configmaps
|
||||
- networkpolicies
|
||||
- resourcequotas
|
||||
- secrets
|
||||
- roles
|
||||
- rolebindings
|
||||
- limitranges
|
||||
- namespaces
|
||||
- nodes
|
||||
- nodes/status
|
||||
- pods
|
||||
verbs:
|
||||
- create
|
||||
- update
|
||||
- patch
|
||||
- delete
|
||||
- get
|
||||
- list
|
|
@ -0,0 +1,12 @@
|
|||
## Description
|
||||
|
||||
This test ensures that a mutate existing policy is denied when it does not have corresponding permissions to generate the downstream resource.
|
||||
|
||||
## Expected Behavior
|
||||
|
||||
The test fails if the policy creation is allowed, otherwise passes.
|
||||
|
||||
|
||||
## Reference Issue(s)
|
||||
|
||||
https://github.com/kyverno/kyverno/issues/6584
|
|
@ -0,0 +1,10 @@
|
|||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: pol-mutate-existing-auth-check
|
||||
namespace: pol-mutate-existing-auth-check-ns
|
||||
status:
|
||||
conditions:
|
||||
- reason: Succeeded
|
||||
status: "True"
|
||||
type: Ready
|
|
@ -0,0 +1,24 @@
|
|||
apiVersion: kyverno.io/v1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: pol-mutate-existing-auth-check
|
||||
namespace: pol-mutate-existing-auth-check-ns
|
||||
spec:
|
||||
mutateExistingOnPolicyUpdate: true
|
||||
background: false
|
||||
rules:
|
||||
- name: label-privileged-namespaces
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- ConfigMap
|
||||
mutate:
|
||||
targets:
|
||||
- apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
namespace: pol-mutate-existing-auth-check-ns
|
||||
patchStrategicMerge:
|
||||
metadata:
|
||||
labels:
|
||||
foo: bar
|
|
@ -0,0 +1,16 @@
|
|||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: kyverno:background-controller:additional
|
||||
rules:
|
||||
- apiGroups:
|
||||
- '*'
|
||||
resources:
|
||||
- deployments
|
||||
verbs:
|
||||
- create
|
||||
- update
|
||||
- patch
|
||||
- delete
|
||||
- get
|
||||
- list
|
|
@ -0,0 +1,28 @@
|
|||
## reset changed clusterrole for the rest of the tests
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: kyverno:background-controller:additional
|
||||
rules:
|
||||
- apiGroups:
|
||||
- '*'
|
||||
resources:
|
||||
- configmaps
|
||||
- networkpolicies
|
||||
- resourcequotas
|
||||
- secrets
|
||||
- roles
|
||||
- rolebindings
|
||||
- limitranges
|
||||
- namespaces
|
||||
- nodes
|
||||
- nodes/status
|
||||
- pods
|
||||
- deployments
|
||||
verbs:
|
||||
- create
|
||||
- update
|
||||
- patch
|
||||
- delete
|
||||
- get
|
||||
- list
|
Loading…
Reference in a new issue