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:
parent
fd67707c00
commit
767e576a9a
8 changed files with 92 additions and 90 deletions
|
@ -1,4 +1,4 @@
|
|||
package admission
|
||||
package policy
|
||||
|
||||
import (
|
||||
"context"
|
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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{
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
31
pkg/utils/admission/metadata.go
Normal file
31
pkg/utils/admission/metadata.go
Normal 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
|
||||
}
|
32
pkg/validation/resource/validate.go
Normal file
32
pkg/validation/resource/validate.go
Normal 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
|
||||
}
|
|
@ -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
|
||||
}
|
Loading…
Add table
Reference in a new issue