2022-11-07 15:53:40 +01:00
|
|
|
package handlers
|
|
|
|
|
|
|
|
import (
|
2022-11-17 16:17:52 +01:00
|
|
|
"context"
|
2022-11-08 10:35:08 +01:00
|
|
|
"errors"
|
2022-11-07 15:53:40 +01:00
|
|
|
"fmt"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/go-logr/logr"
|
|
|
|
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
|
|
|
"github.com/kyverno/kyverno/pkg/config"
|
|
|
|
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
|
|
|
|
admissionv1 "k8s.io/api/admission/v1"
|
|
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
|
|
)
|
|
|
|
|
2023-01-24 18:07:27 +01:00
|
|
|
const namespaceControllerUsername = "system:serviceaccount:kube-system:namespace-controller"
|
|
|
|
|
2023-04-04 12:23:20 +02:00
|
|
|
var kyvernoUsername = fmt.Sprintf("system:serviceaccount:%s:%s", config.KyvernoNamespace(), config.KyvernoServiceAccountName())
|
|
|
|
|
2022-11-23 07:50:55 +01:00
|
|
|
func (inner AdmissionHandler) WithProtection(enabled bool) AdmissionHandler {
|
2022-11-09 11:52:20 +01:00
|
|
|
if !enabled {
|
2022-11-23 07:50:55 +01:00
|
|
|
return inner
|
2022-11-09 11:52:20 +01:00
|
|
|
}
|
2022-11-23 07:50:55 +01:00
|
|
|
return inner.withProtection().WithTrace("PROTECT")
|
2022-11-09 11:52:20 +01:00
|
|
|
}
|
|
|
|
|
2022-11-23 07:50:55 +01:00
|
|
|
func (inner AdmissionHandler) withProtection() AdmissionHandler {
|
2023-04-04 07:11:18 +02:00
|
|
|
return func(ctx context.Context, logger logr.Logger, request AdmissionRequest, startTime time.Time) AdmissionResponse {
|
2023-01-24 18:07:27 +01:00
|
|
|
// Allows deletion of namespace containing managed resources
|
|
|
|
if request.Operation == admissionv1.Delete && request.UserInfo.Username == namespaceControllerUsername {
|
|
|
|
return inner(ctx, logger, request, startTime)
|
|
|
|
}
|
2023-04-04 07:11:18 +02:00
|
|
|
newResource, oldResource, err := admissionutils.ExtractResources(nil, request.AdmissionRequest)
|
2022-11-23 07:50:55 +01:00
|
|
|
if err != nil {
|
2023-04-06 16:28:13 +02:00
|
|
|
logger.Error(err, "failed to extract resources")
|
2022-11-30 16:37:42 +01:00
|
|
|
return admissionutils.Response(request.UID, err)
|
2022-11-23 07:50:55 +01:00
|
|
|
}
|
|
|
|
for _, resource := range []unstructured.Unstructured{newResource, oldResource} {
|
|
|
|
resLabels := resource.GetLabels()
|
|
|
|
if resLabels[kyvernov1.LabelAppManagedBy] == kyvernov1.ValueKyvernoApp {
|
2023-04-04 12:23:20 +02:00
|
|
|
if request.UserInfo.Username != kyvernoUsername {
|
2023-04-06 16:28:13 +02:00
|
|
|
logger.V(2).Info("access to the resource not authorized, this is a kyverno managed resource and should be altered only by kyverno")
|
2022-11-30 16:37:42 +01:00
|
|
|
return admissionutils.Response(request.UID, errors.New("A kyverno managed resource can only be modified by kyverno"))
|
2022-11-07 15:53:40 +01:00
|
|
|
}
|
2022-11-23 07:50:55 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return inner(ctx, logger, request, startTime)
|
2022-11-07 15:53:40 +01:00
|
|
|
}
|
|
|
|
}
|