1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-13 19:28:55 +00:00

[Feat]: Perform permissions check when TTL label is observed (#8128)

* added permissions check

Signed-off-by: Ved Ratan <vedratan8@gmail.com>

* lint fix

Signed-off-by: Ved Ratan <vedratan8@gmail.com>

* lint fix

Signed-off-by: Ved Ratan <vedratan8@gmail.com>

* issue_8091

Signed-off-by: Ved Ratan <vedratan8@gmail.com>

* log fix

Signed-off-by: Ved Ratan <vedratan8@gmail.com>

* refactor

Signed-off-by: Ved Ratan <vedratan8@gmail.com>

* fix

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>

---------

Signed-off-by: Ved Ratan <vedratan8@gmail.com>
Signed-off-by: Ved Ratan <82467006+VedRatan@users.noreply.github.com>
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
Co-authored-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
Ved Ratan 2023-08-28 21:48:48 +05:30 committed by GitHub
parent 94aa1f18c6
commit daadd36c72
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 32 additions and 14 deletions

View file

@ -11,17 +11,17 @@ import (
"github.com/kyverno/kyverno/pkg/webhooks/handlers"
)
type cleanupHandlers struct {
type validationHandlers struct {
client dclient.Interface
}
func New(client dclient.Interface) *cleanupHandlers {
return &cleanupHandlers{
func New(client dclient.Interface) *validationHandlers {
return &validationHandlers{
client: client,
}
}
func (h *cleanupHandlers) Validate(ctx context.Context, logger logr.Logger, request handlers.AdmissionRequest, _ time.Time) handlers.AdmissionResponse {
func (h *validationHandlers) Validate(ctx context.Context, logger logr.Logger, request handlers.AdmissionRequest, _ time.Time) handlers.AdmissionResponse {
policy, _, err := admissionutils.GetCleanupPolicies(request.AdmissionRequest)
if err != nil {
logger.Error(err, "failed to unmarshal policies from admission request")

View file

@ -6,17 +6,33 @@ import (
"time"
"github.com/go-logr/logr"
"github.com/kyverno/kyverno/pkg/auth/checker"
manager "github.com/kyverno/kyverno/pkg/controllers/ttl"
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
validation "github.com/kyverno/kyverno/pkg/validation/resource"
"github.com/kyverno/kyverno/pkg/webhooks/handlers"
"k8s.io/apimachinery/pkg/runtime/schema"
)
func Validate(ctx context.Context, logger logr.Logger, request handlers.AdmissionRequest, _ time.Time) handlers.AdmissionResponse {
type validationHandlers struct {
checker checker.AuthChecker
}
func New(checker checker.AuthChecker) *validationHandlers {
return &validationHandlers{
checker: checker,
}
}
func (h *validationHandlers) Validate(ctx context.Context, logger logr.Logger, request handlers.AdmissionRequest, _ time.Time) handlers.AdmissionResponse {
metadata, _, err := admissionutils.GetPartialObjectMetadatas(request.AdmissionRequest)
if err != nil {
logger.Error(err, "failed to unmarshal metadatas from admission request")
return admissionutils.ResponseSuccess(request.UID, err.Error())
}
if !manager.HasResourcePermissions(logger, schema.GroupVersionResource(request.AdmissionRequest.Resource), h.checker) {
logger.Info("doesn't have required permissions for deletion", "gvr", request.AdmissionRequest.Resource)
}
if err := validation.ValidateTtlLabel(ctx, metadata); err != nil {
logger.Error(err, "metadatas validation errors")
return admissionutils.ResponseSuccess(request.UID, fmt.Sprintf("cleanup.kyverno.io/ttl label value cannot be parsed as any recognizable format (%s)", err.Error()))

View file

@ -13,6 +13,7 @@ import (
resourcehandlers "github.com/kyverno/kyverno/cmd/cleanup-controller/handlers/admission/resource"
cleanuphandlers "github.com/kyverno/kyverno/cmd/cleanup-controller/handlers/cleanup"
"github.com/kyverno/kyverno/cmd/internal"
"github.com/kyverno/kyverno/pkg/auth/checker"
kyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions"
"github.com/kyverno/kyverno/pkg/config"
"github.com/kyverno/kyverno/pkg/controllers/certmanager"
@ -101,6 +102,7 @@ func main() {
setup.Logger.Error(errors.New("failed to wait for cache sync"), "failed to wait for cache sync")
os.Exit(1)
}
checker := checker.NewSelfChecker(setup.KubeClient.AuthorizationV1().SelfSubjectAccessReviews())
// setup leader election
le, err := leaderelection.New(
setup.Logger.WithName("leader-election"),
@ -229,7 +231,7 @@ func main() {
ttlcontroller.NewManager(
setup.MetadataClient,
setup.KubeClient.Discovery(),
setup.KubeClient.AuthorizationV1(),
checker,
interval,
),
ttlcontroller.Workers,
@ -289,7 +291,8 @@ func main() {
var wg sync.WaitGroup
go eventGenerator.Run(ctx, 3, &wg)
// create handlers
admissionHandlers := policyhandlers.New(setup.KyvernoDynamicClient)
policyHandlers := policyhandlers.New(setup.KyvernoDynamicClient)
resourceHandlers := resourcehandlers.New(checker)
cmResolver := internal.NewConfigMapResolver(ctx, setup.Logger, setup.KubeClient, resyncPeriod)
cleanupHandlers := cleanuphandlers.New(
setup.Logger.WithName("cleanup-handler"),
@ -310,8 +313,8 @@ func main() {
}
return secret.Data[corev1.TLSCertKey], secret.Data[corev1.TLSPrivateKeyKey], nil
},
admissionHandlers.Validate,
resourcehandlers.Validate,
policyHandlers.Validate,
resourceHandlers.Validate,
cleanupHandlers.Cleanup,
setup.MetricsManager,
webhooks.DebugModeOptions{

View file

@ -20,7 +20,6 @@ import (
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/discovery"
authorizationv1client "k8s.io/client-go/kubernetes/typed/authorization/v1"
"k8s.io/client-go/metadata"
"k8s.io/client-go/metadata/metadatainformer"
"k8s.io/client-go/tools/cache"
@ -47,7 +46,7 @@ type manager struct {
func NewManager(
metadataInterface metadata.Interface,
discoveryInterface discovery.DiscoveryInterface,
authorizationInterface authorizationv1client.AuthorizationV1Interface,
checker checker.AuthChecker,
timeInterval time.Duration,
) controllers.Controller {
logger := logging.WithName(ControllerName)
@ -63,7 +62,7 @@ func NewManager(
mgr := &manager{
metadataClient: metadataInterface,
discoveryClient: discoveryInterface,
checker: checker.NewSelfChecker(authorizationInterface.SelfSubjectAccessReviews()),
checker: checker,
resController: map[schema.GroupVersionResource]stopFunc{},
logger: logger,
interval: timeInterval,
@ -182,7 +181,7 @@ func (m *manager) filterPermissionsResource(resources []schema.GroupVersionResou
validResources := []schema.GroupVersionResource{}
for _, resource := range resources {
// Check if the service account has the necessary permissions
if hasResourcePermissions(m.logger, resource, m.checker) {
if HasResourcePermissions(m.logger, resource, m.checker) {
validResources = append(validResources, resource)
}
}

View file

@ -41,7 +41,7 @@ func discoverResources(logger logr.Logger, discoveryClient discovery.DiscoveryIn
return resources, nil
}
func hasResourcePermissions(logger logr.Logger, resource schema.GroupVersionResource, s checker.AuthChecker) bool {
func HasResourcePermissions(logger logr.Logger, resource schema.GroupVersionResource, s checker.AuthChecker) bool {
can, err := checker.Check(context.TODO(), s, resource.Group, resource.Version, resource.Resource, "", "", "watch", "list", "delete")
if err != nil {
logger.Error(err, "failed to check permissions")