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

refactor: ttl label validation (#7960)

Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
Charles-Edouard Brétéché 2023-08-03 06:48:10 +02:00 committed by GitHub
parent fd67707c00
commit 767e576a9a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 92 additions and 90 deletions

View file

@ -1,4 +1,4 @@
package admission
package policy
import (
"context"

View file

@ -0,0 +1,24 @@
package resource
import (
"context"
"time"
"github.com/go-logr/logr"
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
validation "github.com/kyverno/kyverno/pkg/validation/resource"
"github.com/kyverno/kyverno/pkg/webhooks/handlers"
)
func 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 err := validation.ValidateTtlLabel(ctx, metadata); err != nil {
logger.Error(err, "metadatas validation errors")
return admissionutils.ResponseSuccess(request.UID, err.Error())
}
return admissionutils.ResponseSuccess(request.UID)
}

View file

@ -1,37 +0,0 @@
package resourceadmission
import (
"context"
"time"
"github.com/go-logr/logr"
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
validation "github.com/kyverno/kyverno/pkg/validation/ttl-label"
"github.com/kyverno/kyverno/pkg/webhooks/handlers"
admissionv1 "k8s.io/api/admission/v1"
)
func Validate(_ context.Context, logger logr.Logger, request handlers.AdmissionRequest, _ time.Time) handlers.AdmissionResponse {
logger.Info("triggered the label validator")
ttlLabel, err := admissionutils.GetTtlLabel(request.AdmissionRequest.Object.Raw)
if err != nil {
logger.Error(err, "failed to get the ttl label")
return admissionutils.ResponseSuccess(request.UID, err.Error())
}
if request.Operation == admissionv1.Update {
ttlLabel, err = admissionutils.GetTtlLabel(request.AdmissionRequest.Object.Raw)
if err != nil {
logger.Error(err, "failed to get the ttl label")
return admissionutils.ResponseSuccess(request.UID, err.Error())
}
}
if ttlLabel != "" {
if err := validation.Validate(ttlLabel); err != nil {
logger.Error(err, "failed to unmarshal the ttl label value")
return admissionutils.ResponseSuccess(request.UID, err.Error())
}
}
return admissionutils.ResponseSuccess(request.UID)
}

View file

@ -9,9 +9,9 @@ import (
"time"
"github.com/kyverno/kyverno/api/kyverno"
admissionhandlers "github.com/kyverno/kyverno/cmd/cleanup-controller/handlers/admission"
policyhandlers "github.com/kyverno/kyverno/cmd/cleanup-controller/handlers/admission/policy"
resourcehandlers "github.com/kyverno/kyverno/cmd/cleanup-controller/handlers/admission/resource"
cleanuphandlers "github.com/kyverno/kyverno/cmd/cleanup-controller/handlers/cleanup"
labelhandlers "github.com/kyverno/kyverno/cmd/cleanup-controller/handlers/resource-admission"
"github.com/kyverno/kyverno/cmd/internal"
kyvernoinformer "github.com/kyverno/kyverno/pkg/client/informers/externalversions"
"github.com/kyverno/kyverno/pkg/config"
@ -272,7 +272,7 @@ func main() {
var wg sync.WaitGroup
go eventGenerator.Run(ctx, 3, &wg)
// create handlers
admissionHandlers := admissionhandlers.New(setup.KyvernoDynamicClient)
admissionHandlers := policyhandlers.New(setup.KyvernoDynamicClient)
cmResolver := internal.NewConfigMapResolver(ctx, setup.Logger, setup.KubeClient, resyncPeriod)
cleanupHandlers := cleanuphandlers.New(
setup.Logger.WithName("cleanup-handler"),
@ -294,7 +294,7 @@ func main() {
return secret.Data[corev1.TLSCertKey], secret.Data[corev1.TLSPrivateKeyKey], nil
},
admissionHandlers.Validate,
labelhandlers.Validate,
resourcehandlers.Validate,
cleanupHandlers.Cleanup,
setup.MetricsManager,
webhooks.DebugModeOptions{

View file

@ -4,7 +4,6 @@ import (
"encoding/json"
"fmt"
"github.com/kyverno/kyverno/api/kyverno"
kyvernov2alpha1 "github.com/kyverno/kyverno/api/kyverno/v2alpha1"
admissionv1 "k8s.io/api/admission/v1"
)
@ -38,28 +37,3 @@ func GetCleanupPolicies(request admissionv1.AdmissionRequest) (kyvernov2alpha1.C
}
return policy, emptypolicy, nil
}
// UnmarshalTTLLabel extracts the cleanup.kyverno.io/ttl label value from the raw admission request.
func GetTtlLabel(raw []byte) (string, error) {
var resourceObj map[string]interface{}
if err := json.Unmarshal(raw, &resourceObj); err != nil {
return "", err
}
metadata, found := resourceObj["metadata"].(map[string]interface{})
if !found {
return "", fmt.Errorf("resource has no metadata field")
}
labels, found := metadata["labels"].(map[string]interface{})
if !found {
return "", fmt.Errorf("resource has no labels field")
}
ttlValue, found := labels[kyverno.LabelCleanupTtl].(string)
if !found {
return "", fmt.Errorf("resource has no %s label", kyverno.LabelCleanupTtl)
}
return ttlValue, nil
}

View file

@ -0,0 +1,31 @@
package admission
import (
"encoding/json"
admissionv1 "k8s.io/api/admission/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func UnmarshalPartialObjectMetadata(raw []byte) (*metav1.PartialObjectMetadata, error) {
var object *metav1.PartialObjectMetadata
if err := json.Unmarshal(raw, &object); err != nil {
return nil, err
}
return object, nil
}
func GetPartialObjectMetadatas(request admissionv1.AdmissionRequest) (*metav1.PartialObjectMetadata, *metav1.PartialObjectMetadata, error) {
object, err := UnmarshalPartialObjectMetadata(request.Object.Raw)
if err != nil {
return nil, nil, err
}
if request.Operation != admissionv1.Update {
return object, nil, nil
}
oldObject, err := UnmarshalPartialObjectMetadata(request.OldObject.Raw)
if err != nil {
return nil, nil, err
}
return object, oldObject, nil
}

View file

@ -0,0 +1,32 @@
package resource
import (
"context"
"time"
"github.com/kyverno/kyverno/api/kyverno"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func ValidateTtlLabel(_ context.Context, object metav1.Object) error {
labels := object.GetLabels()
if labels == nil {
return nil
}
if ttl, ok := labels[kyverno.LabelCleanupTtl]; !ok {
return nil
} else {
_, err := time.ParseDuration(ttl)
if err != nil {
// Try parsing ttlValue as a time in ISO 8601 format
_, err := time.Parse(kyverno.ValueTtlDateTimeLayout, ttl)
if err != nil {
_, err = time.Parse(kyverno.ValueTtlDateLayout, ttl)
if err != nil {
return err
}
}
}
}
return nil
}

View file

@ -1,22 +0,0 @@
package ttllabel
import (
"time"
"github.com/kyverno/kyverno/api/kyverno"
)
func Validate(ttlValue string) error {
_, err := time.ParseDuration(ttlValue)
if err != nil {
// Try parsing ttlValue as a time in ISO 8601 format
_, err := time.Parse(kyverno.ValueTtlDateTimeLayout, ttlValue)
if err != nil {
_, err = time.Parse(kyverno.ValueTtlDateLayout, ttlValue)
if err != nil {
return err
}
}
}
return nil
}