2022-05-16 16:36:21 +02:00
|
|
|
package resource
|
|
|
|
|
|
|
|
import (
|
2022-12-09 14:45:11 +01:00
|
|
|
"context"
|
2022-11-08 10:35:08 +01:00
|
|
|
"errors"
|
|
|
|
|
2022-05-16 16:36:21 +02:00
|
|
|
"github.com/go-logr/logr"
|
|
|
|
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
|
|
|
kyvernov1beta1 "github.com/kyverno/kyverno/api/kyverno/v1beta1"
|
2023-01-30 12:41:09 +01:00
|
|
|
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
2022-05-16 16:36:21 +02:00
|
|
|
engineutils "github.com/kyverno/kyverno/pkg/engine/utils"
|
|
|
|
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
|
|
|
|
"github.com/kyverno/kyverno/pkg/webhooks/updaterequest"
|
|
|
|
admissionv1 "k8s.io/api/admission/v1"
|
2022-11-30 16:37:42 +01:00
|
|
|
"k8s.io/apimachinery/pkg/types"
|
2022-05-16 16:36:21 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
type updateRequestResponse struct {
|
|
|
|
ur kyvernov1beta1.UpdateRequestSpec
|
|
|
|
err error
|
|
|
|
}
|
|
|
|
|
2022-11-30 16:37:42 +01:00
|
|
|
func errorResponse(logger logr.Logger, uid types.UID, err error, message string) *admissionv1.AdmissionResponse {
|
2022-05-16 16:36:21 +02:00
|
|
|
logger.Error(err, message)
|
2022-11-30 16:37:42 +01:00
|
|
|
return admissionutils.Response(uid, errors.New(message+": "+err.Error()))
|
2022-05-16 16:36:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func patchRequest(patches []byte, request *admissionv1.AdmissionRequest, logger logr.Logger) *admissionv1.AdmissionRequest {
|
|
|
|
patchedResource := processResourceWithPatches(patches, request.Object.Raw, logger)
|
|
|
|
newRequest := request.DeepCopy()
|
|
|
|
newRequest.Object.Raw = patchedResource
|
|
|
|
return newRequest
|
|
|
|
}
|
|
|
|
|
|
|
|
func processResourceWithPatches(patch []byte, resource []byte, log logr.Logger) []byte {
|
|
|
|
if patch == nil {
|
|
|
|
return resource
|
|
|
|
}
|
|
|
|
resource, err := engineutils.ApplyPatchNew(resource, patch)
|
|
|
|
if err != nil {
|
|
|
|
log.Error(err, "failed to patch resource:", "patch", string(patch), "resource", string(resource))
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
log.V(6).Info("", "patchedResource", string(resource))
|
|
|
|
return resource
|
|
|
|
}
|
|
|
|
|
2022-12-09 14:45:11 +01:00
|
|
|
func applyUpdateRequest(
|
|
|
|
ctx context.Context,
|
|
|
|
request *admissionv1.AdmissionRequest,
|
|
|
|
ruleType kyvernov1beta1.RequestType,
|
|
|
|
grGenerator updaterequest.Generator,
|
|
|
|
userRequestInfo kyvernov1beta1.RequestInfo,
|
|
|
|
action admissionv1.Operation,
|
2023-01-30 12:41:09 +01:00
|
|
|
engineResponses ...*engineapi.EngineResponse,
|
2022-05-17 08:19:03 +02:00
|
|
|
) (failedUpdateRequest []updateRequestResponse) {
|
2022-05-16 16:36:21 +02:00
|
|
|
admissionRequestInfo := kyvernov1beta1.AdmissionRequestInfoObject{
|
2022-05-29 09:27:14 +02:00
|
|
|
AdmissionRequest: request,
|
2022-05-16 16:36:21 +02:00
|
|
|
Operation: action,
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, er := range engineResponses {
|
|
|
|
ur := transform(admissionRequestInfo, userRequestInfo, er, ruleType)
|
2022-12-09 14:45:11 +01:00
|
|
|
if err := grGenerator.Apply(ctx, ur, action); err != nil {
|
2022-05-16 16:36:21 +02:00
|
|
|
failedUpdateRequest = append(failedUpdateRequest, updateRequestResponse{ur: ur, err: err})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-01-30 12:41:09 +01:00
|
|
|
func transform(admissionRequestInfo kyvernov1beta1.AdmissionRequestInfoObject, userRequestInfo kyvernov1beta1.RequestInfo, er *engineapi.EngineResponse, ruleType kyvernov1beta1.RequestType) kyvernov1beta1.UpdateRequestSpec {
|
2022-05-16 16:36:21 +02:00
|
|
|
var PolicyNameNamespaceKey string
|
|
|
|
if er.PolicyResponse.Policy.Namespace != "" {
|
|
|
|
PolicyNameNamespaceKey = er.PolicyResponse.Policy.Namespace + "/" + er.PolicyResponse.Policy.Name
|
|
|
|
} else {
|
|
|
|
PolicyNameNamespaceKey = er.PolicyResponse.Policy.Name
|
|
|
|
}
|
|
|
|
|
|
|
|
ur := kyvernov1beta1.UpdateRequestSpec{
|
|
|
|
Type: ruleType,
|
|
|
|
Policy: PolicyNameNamespaceKey,
|
|
|
|
Resource: kyvernov1.ResourceSpec{
|
|
|
|
Kind: er.PolicyResponse.Resource.Kind,
|
|
|
|
Namespace: er.PolicyResponse.Resource.Namespace,
|
|
|
|
Name: er.PolicyResponse.Resource.Name,
|
|
|
|
APIVersion: er.PolicyResponse.Resource.APIVersion,
|
|
|
|
},
|
|
|
|
Context: kyvernov1beta1.UpdateRequestSpecContext{
|
|
|
|
UserRequestInfo: userRequestInfo,
|
|
|
|
AdmissionRequestInfo: admissionRequestInfo,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
return ur
|
|
|
|
}
|