1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-07 00:17:13 +00:00
kyverno/cmd/cleanup-controller/validate/validate.go
Charles-Edouard Brétéché 217d77d670
feat: add cleanup controller makefile targets (#5327)
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
2022-11-14 11:00:40 +00:00

98 lines
3 KiB
Go

package validate
import (
"fmt"
"github.com/go-logr/logr"
kyvernov1alpha1 "github.com/kyverno/kyverno/api/kyverno/v1alpha1"
"github.com/kyverno/kyverno/cmd/cleanup-controller/logger"
"github.com/kyverno/kyverno/pkg/clients/dclient"
"github.com/kyverno/kyverno/pkg/engine/variables"
"github.com/kyverno/kyverno/pkg/logging"
"github.com/kyverno/kyverno/pkg/openapi"
"github.com/kyverno/kyverno/pkg/policy/generate"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/client-go/discovery"
)
// Cleanup provides implementation to validate permission for using DELETE operation by CleanupPolicy
type Cleanup struct {
// rule to hold CleanupPolicy specifications
spec kyvernov1alpha1.CleanupPolicySpec
// authCheck to check access for operations
authCheck generate.Operations
// logger
log logr.Logger
}
// NewCleanup returns a new instance of Cleanup validation checker
func NewCleanup(client dclient.Interface, cleanup kyvernov1alpha1.CleanupPolicySpec, log logr.Logger) *Cleanup {
c := Cleanup{
spec: cleanup,
authCheck: generate.NewAuth(client, log),
log: log,
}
return &c
}
// canIDelete returns a error if kyverno cannot perform operations
func (c *Cleanup) CanIDelete(kind, namespace string) error {
// Skip if there is variable defined
authCheck := c.authCheck
if !variables.IsVariable(kind) && !variables.IsVariable(namespace) {
// DELETE
ok, err := authCheck.CanIDelete(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", kind, namespace)
}
} else {
c.log.V(4).Info("name & namespace uses variables, so cannot be resolved. Skipping Auth Checks.")
}
return nil
}
// Validate checks the policy and rules declarations for required configurations
func ValidateCleanupPolicy(cleanuppolicy kyvernov1alpha1.CleanupPolicyInterface, client dclient.Interface, mock bool, openApiManager openapi.Manager) error {
namespace := cleanuppolicy.GetNamespace()
var res []*metav1.APIResourceList
clusterResources := sets.NewString()
// Get all the cluster type kind supported by cluster
res, err := discovery.ServerPreferredResources(client.Discovery().DiscoveryInterface())
if err != nil {
if discovery.IsGroupDiscoveryFailedError(err) {
err := err.(*discovery.ErrGroupDiscoveryFailed)
for gv, err := range err.Groups {
logger.Logger.Error(err, "failed to list api resources", "group", gv)
}
} else {
return err
}
}
for _, resList := range res {
for _, r := range resList.APIResources {
if !r.Namespaced {
clusterResources.Insert(r.Kind)
}
}
}
if errs := cleanuppolicy.Validate(clusterResources); len(errs) != 0 {
return errs.ToAggregate()
}
for kind := range clusterResources {
checker := NewCleanup(client, *cleanuppolicy.GetSpec(), logging.GlobalLogger())
if err := checker.CanIDelete(kind, namespace); err != nil {
return fmt.Errorf("cannot delete kind %s in namespace %s", kind, namespace)
}
}
return nil
}