2020-01-07 10:33:28 -08:00
package webhooks
import (
2020-11-09 11:26:12 -08:00
contextdefault "context"
2021-04-27 01:28:34 +05:30
"encoding/json"
2020-07-09 11:48:34 -07:00
"fmt"
2020-08-31 23:55:13 +05:30
"strings"
"time"
2020-10-07 11:12:31 -07:00
2021-10-02 00:09:29 +05:30
"github.com/gardener/controller-manager-library/pkg/logger"
2020-12-22 11:07:31 -08:00
"github.com/go-logr/logr"
2021-10-29 18:13:20 +02:00
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
2020-12-22 11:07:31 -08:00
2022-03-28 16:01:27 +02:00
"github.com/kyverno/kyverno/pkg/autogen"
2021-02-04 02:39:42 +05:30
"github.com/kyverno/kyverno/pkg/common"
2020-10-07 11:12:31 -07:00
"github.com/kyverno/kyverno/pkg/config"
2021-04-27 01:28:34 +05:30
client "github.com/kyverno/kyverno/pkg/dclient"
2020-10-07 11:12:31 -07:00
"github.com/kyverno/kyverno/pkg/engine"
"github.com/kyverno/kyverno/pkg/engine/context"
2021-04-27 01:28:34 +05:30
enginectx "github.com/kyverno/kyverno/pkg/engine/context"
2020-10-07 11:12:31 -07:00
"github.com/kyverno/kyverno/pkg/engine/response"
2020-12-23 23:44:17 +05:30
enginutils "github.com/kyverno/kyverno/pkg/engine/utils"
2021-04-27 01:28:34 +05:30
"github.com/kyverno/kyverno/pkg/engine/variables"
2020-10-07 11:12:31 -07:00
"github.com/kyverno/kyverno/pkg/event"
2021-03-26 05:34:43 +05:30
gen "github.com/kyverno/kyverno/pkg/generate"
2020-12-01 12:30:08 -08:00
kyvernoutils "github.com/kyverno/kyverno/pkg/utils"
2020-10-07 11:12:31 -07:00
"github.com/kyverno/kyverno/pkg/webhooks/generate"
2022-04-06 22:43:07 +02:00
admissionv1 "k8s.io/api/admission/v1"
2020-10-07 11:12:31 -07:00
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2020-12-15 04:22:13 +05:30
"k8s.io/apimachinery/pkg/labels"
2020-01-07 10:33:28 -08:00
)
2022-04-06 22:43:07 +02:00
func ( ws * WebhookServer ) applyGeneratePolicies ( request * admissionv1 . AdmissionRequest , policyContext * engine . PolicyContext , policies [ ] kyverno . PolicyInterface , ts int64 , logger logr . Logger ) {
2021-07-09 18:01:46 -07:00
admissionReviewCompletionLatencyChannel := make ( chan int64 , 1 )
2021-07-23 21:46:50 +05:30
generateEngineResponsesSenderForAdmissionReviewDurationMetric := make ( chan [ ] * response . EngineResponse , 1 )
generateEngineResponsesSenderForAdmissionRequestsCountMetric := make ( chan [ ] * response . EngineResponse , 1 )
go ws . handleGenerate ( request , policies , policyContext . JSONContext , policyContext . AdmissionInfo , ws . configHandler , ts , & admissionReviewCompletionLatencyChannel , & generateEngineResponsesSenderForAdmissionReviewDurationMetric , & generateEngineResponsesSenderForAdmissionRequestsCountMetric )
2022-04-06 14:41:08 +02:00
go ws . registerAdmissionReviewDurationMetricGenerate ( logger , string ( request . Operation ) , & admissionReviewCompletionLatencyChannel , & generateEngineResponsesSenderForAdmissionReviewDurationMetric )
go ws . registerAdmissionRequestsMetricGenerate ( logger , string ( request . Operation ) , & generateEngineResponsesSenderForAdmissionRequestsCountMetric )
2021-07-09 18:01:46 -07:00
}
//handleGenerate handles admission-requests for policies with generate rules
func ( ws * WebhookServer ) handleGenerate (
2022-04-06 22:43:07 +02:00
request * admissionv1 . AdmissionRequest ,
2022-03-30 16:28:09 +02:00
policies [ ] kyverno . PolicyInterface ,
2022-04-09 13:52:50 +02:00
ctx context . Interface ,
2021-07-09 18:01:46 -07:00
userRequestInfo kyverno . RequestInfo ,
dynamicConfig config . Interface ,
admissionRequestTimestamp int64 ,
latencySender * chan int64 ,
2021-07-23 21:46:50 +05:30
generateEngineResponsesSenderForAdmissionReviewDurationMetric * chan [ ] * response . EngineResponse ,
generateEngineResponsesSenderForAdmissionRequestsCountMetric * chan [ ] * response . EngineResponse ,
) {
2021-07-09 18:01:46 -07:00
2021-05-13 12:03:13 -07:00
logger := ws . log . WithValues ( "action" , "generation" , "uid" , request . UID , "kind" , request . Kind , "namespace" , request . Namespace , "name" , request . Name , "operation" , request . Operation , "gvk" , request . Kind . String ( ) )
2021-07-09 18:01:46 -07:00
logger . V ( 6 ) . Info ( "generate request" )
2021-06-08 01:23:13 +05:30
2020-12-23 15:10:07 -08:00
var engineResponses [ ] * response . EngineResponse
2022-04-06 22:43:07 +02:00
if ( request . Operation == admissionv1 . Create || request . Operation == admissionv1 . Update ) && len ( policies ) != 0 {
2020-12-30 00:12:36 +05:30
// convert RAW to unstructured
new , old , err := kyvernoutils . ExtractResources ( nil , request )
if err != nil {
logger . Error ( err , "failed to extract resource" )
}
2020-01-07 10:33:28 -08:00
2021-02-01 12:59:13 -08:00
policyContext := & engine . PolicyContext {
2020-12-30 00:12:36 +05:30
NewResource : new ,
OldResource : old ,
AdmissionInfo : userRequestInfo ,
ExcludeGroupRole : dynamicConfig . GetExcludeGroupRole ( ) ,
ExcludeResourceFunc : ws . configHandler . ToFilter ,
JSONContext : ctx ,
2021-02-22 12:08:26 -08:00
Client : ws . client ,
2020-12-30 00:12:36 +05:30
}
2020-01-07 10:33:28 -08:00
2020-12-30 00:12:36 +05:30
for _ , policy := range policies {
var rules [ ] response . RuleResponse
2022-03-30 15:04:30 +02:00
policyContext . Policy = policy
2021-02-04 02:39:42 +05:30
if request . Kind . Kind != "Namespace" && request . Namespace != "" {
policyContext . NamespaceLabels = common . GetNamespaceSelectorsFromNamespaceLister ( request . Kind . Kind , request . Namespace , ws . nsLister , logger )
}
2020-12-30 00:12:36 +05:30
engineResponse := engine . Generate ( policyContext )
for _ , rule := range engineResponse . PolicyResponse . Rules {
2021-09-26 02:12:31 -07:00
if rule . Status != response . RuleStatusPass {
2020-12-30 00:12:36 +05:30
ws . deleteGR ( logger , engineResponse )
continue
}
rules = append ( rules , rule )
}
2020-01-07 10:33:28 -08:00
2020-12-30 00:12:36 +05:30
if len ( rules ) > 0 {
engineResponse . PolicyResponse . Rules = rules
// some generate rules do apply to the resource
engineResponses = append ( engineResponses , engineResponse )
2020-08-31 23:55:13 +05:30
}
2021-07-14 12:18:59 -07:00
2021-07-23 21:46:50 +05:30
// registering the kyverno_policy_results_total metric concurrently
2022-03-30 15:04:30 +02:00
go ws . registerPolicyResultsMetricGeneration ( logger , string ( request . Operation ) , policy , * engineResponse )
2021-05-15 21:34:26 +05:30
2021-07-23 21:46:50 +05:30
// registering the kyverno_policy_execution_duration_seconds metric concurrently
2022-03-30 15:04:30 +02:00
go ws . registerPolicyExecutionDurationMetricGenerate ( logger , string ( request . Operation ) , policy , * engineResponse )
2020-08-31 23:55:13 +05:30
}
2020-09-04 03:04:23 +05:30
2020-12-30 00:12:36 +05:30
// Adds Generate Request to a channel(queue size 1000) to generators
2021-10-02 00:09:29 +05:30
if failedResponse := applyGenerateRequest ( request , ws . grGenerator , userRequestInfo , request . Operation , engineResponses ... ) ; err != nil {
2020-12-30 00:12:36 +05:30
// report failure event
for _ , failedGR := range failedResponse {
events := failedEvents ( fmt . Errorf ( "failed to create Generate Request: %v" , failedGR . err ) , failedGR . gr , new )
ws . eventGen . Add ( events ... )
}
2020-01-07 10:33:28 -08:00
}
2020-08-31 23:55:13 +05:30
}
2020-09-04 03:04:23 +05:30
2022-04-06 22:43:07 +02:00
if request . Operation == admissionv1 . Update {
2021-07-09 18:01:46 -07:00
ws . handleUpdatesForGenerateRules ( request , policies )
2020-01-07 10:33:28 -08:00
}
2021-05-15 23:33:41 +05:30
// sending the admission request latency to other goroutine (reporting the metrics) over the channel
admissionReviewLatencyDuration := int64 ( time . Since ( time . Unix ( admissionRequestTimestamp , 0 ) ) )
* latencySender <- admissionReviewLatencyDuration
2021-07-23 21:46:50 +05:30
* generateEngineResponsesSenderForAdmissionReviewDurationMetric <- engineResponses
* generateEngineResponsesSenderForAdmissionRequestsCountMetric <- engineResponses
2020-01-07 10:33:28 -08:00
}
2021-07-09 18:01:46 -07:00
//handleUpdatesForGenerateRules handles admission-requests for update
2022-04-06 22:43:07 +02:00
func ( ws * WebhookServer ) handleUpdatesForGenerateRules ( request * admissionv1 . AdmissionRequest , policies [ ] kyverno . PolicyInterface ) {
if request . Operation != admissionv1 . Update {
2021-07-09 18:01:46 -07:00
return
}
logger := ws . log . WithValues ( "action" , "generate" , "uid" , request . UID , "kind" , request . Kind , "namespace" , request . Namespace , "name" , request . Name , "operation" , request . Operation , "gvk" , request . Kind . String ( ) )
2020-12-23 23:44:17 +05:30
resource , err := enginutils . ConvertToUnstructured ( request . OldObject . Raw )
if err != nil {
logger . Error ( err , "failed to convert object resource to unstructured format" )
}
resLabels := resource . GetLabels ( )
2020-12-30 00:12:36 +05:30
if resLabels [ "generate.kyverno.io/clone-policy-name" ] != "" {
2021-07-09 18:01:46 -07:00
ws . handleUpdateGenerateSourceResource ( resLabels , logger )
2021-01-27 23:41:22 +05:30
}
2022-04-06 22:43:07 +02:00
if resLabels [ "app.kubernetes.io/managed-by" ] == "kyverno" && resLabels [ "policy.kyverno.io/synchronize" ] == "enable" && request . Operation == admissionv1 . Update {
2021-07-09 18:01:46 -07:00
ws . handleUpdateGenerateTargetResource ( request , policies , resLabels , logger )
2021-01-27 23:41:22 +05:30
}
}
2021-07-09 18:01:46 -07:00
//handleUpdateGenerateSourceResource - handles update of clone source for generate policy
func ( ws * WebhookServer ) handleUpdateGenerateSourceResource ( resLabels map [ string ] string , logger logr . Logger ) {
2021-01-27 23:41:22 +05:30
policyNames := strings . Split ( resLabels [ "generate.kyverno.io/clone-policy-name" ] , "," )
for _ , policyName := range policyNames {
2021-07-01 00:30:02 +05:30
// check if the policy exists
_ , err := ws . kyvernoClient . KyvernoV1 ( ) . ClusterPolicies ( ) . Get ( contextdefault . TODO ( ) , policyName , metav1 . GetOptions { } )
2021-01-27 23:41:22 +05:30
if err != nil {
2021-07-01 00:30:02 +05:30
if strings . Contains ( err . Error ( ) , "not found" ) {
2021-07-09 18:01:46 -07:00
logger . V ( 4 ) . Info ( "skipping update of generate request as policy is deleted" )
2021-07-01 00:30:02 +05:30
} else {
logger . Error ( err , "failed to get generate policy" , "Name" , policyName )
2021-07-01 15:44:15 +05:30
}
} else {
selector := labels . SelectorFromSet ( labels . Set ( map [ string ] string {
"generate.kyverno.io/policy-name" : policyName ,
} ) )
grList , err := ws . grLister . List ( selector )
if err != nil {
logger . Error ( err , "failed to get generate request for the resource" , "label" , "generate.kyverno.io/policy-name" )
return
}
for _ , gr := range grList {
ws . updateAnnotationInGR ( gr , logger )
2021-07-01 00:30:02 +05:30
}
2021-01-27 23:41:22 +05:30
}
2021-07-01 00:30:02 +05:30
2021-01-27 23:41:22 +05:30
}
}
2021-06-08 12:37:19 -07:00
// updateAnnotationInGR - function used to update GR annotation
// updating GR will trigger reprocessing of GR and recreation/updation of generated resource
2021-10-29 18:13:20 +02:00
func ( ws * WebhookServer ) updateAnnotationInGR ( gr * kyverno . GenerateRequest , logger logr . Logger ) {
2021-06-08 12:37:19 -07:00
grAnnotations := gr . Annotations
if len ( grAnnotations ) == 0 {
grAnnotations = make ( map [ string ] string )
}
2022-03-28 11:31:33 +05:30
ws . mu . Lock ( )
2021-06-08 12:37:19 -07:00
grAnnotations [ "generate.kyverno.io/updation-time" ] = time . Now ( ) . String ( )
gr . SetAnnotations ( grAnnotations )
2022-03-28 11:31:33 +05:30
ws . mu . Unlock ( )
2021-06-08 12:37:19 -07:00
_ , err := ws . kyvernoClient . KyvernoV1 ( ) . GenerateRequests ( config . KyvernoNamespace ) . Update ( contextdefault . TODO ( ) , gr , metav1 . UpdateOptions { } )
if err != nil {
logger . Error ( err , "failed to update generate request for the resource" , "generate request" , gr . Name )
return
}
}
2021-07-09 18:01:46 -07:00
//handleUpdateGenerateTargetResource - handles update of target resource for generate policy
2022-04-06 22:43:07 +02:00
func ( ws * WebhookServer ) handleUpdateGenerateTargetResource ( request * admissionv1 . AdmissionRequest , policies [ ] kyverno . PolicyInterface , resLabels map [ string ] string , logger logr . Logger ) {
2021-01-27 23:41:22 +05:30
enqueueBool := false
newRes , err := enginutils . ConvertToUnstructured ( request . Object . Raw )
if err != nil {
logger . Error ( err , "failed to convert object resource to unstructured format" )
}
policyName := resLabels [ "policy.kyverno.io/policy-name" ]
targetSourceName := newRes . GetName ( )
targetSourceKind := newRes . GetKind ( )
2020-12-24 18:39:23 +05:30
2021-06-03 00:39:48 +05:30
policy , err := ws . kyvernoClient . KyvernoV1 ( ) . ClusterPolicies ( ) . Get ( contextdefault . TODO ( ) , policyName , metav1 . GetOptions { } )
if err != nil {
logger . Error ( err , "failed to get policy from kyverno client." , "policy name" , policyName )
return
}
2022-03-28 16:01:27 +02:00
for _ , rule := range autogen . ComputeRules ( policy ) {
2021-06-03 00:39:48 +05:30
if rule . Generation . Kind == targetSourceKind && rule . Generation . Name == targetSourceName {
updatedRule , err := getGeneratedByResource ( newRes , resLabels , ws . client , rule , logger )
if err != nil {
logger . V ( 4 ) . Info ( "skipping generate policy and resource pattern validaton" , "error" , err )
} else {
2022-03-06 20:07:51 +01:00
data := updatedRule . Generation . DeepCopy ( ) . GetData ( )
2021-06-03 00:39:48 +05:30
if data != nil {
if _ , err := gen . ValidateResourceWithPattern ( logger , newRes . Object , data ) ; err != nil {
enqueueBool = true
break
}
}
cloneName := updatedRule . Generation . Clone . Name
if cloneName != "" {
obj , err := ws . client . GetResource ( "" , rule . Generation . Kind , rule . Generation . Clone . Namespace , rule . Generation . Clone . Name )
2021-04-27 01:28:34 +05:30
if err != nil {
2021-06-03 00:39:48 +05:30
logger . Error ( err , fmt . Sprintf ( "source resource %s/%s/%s not found." , rule . Generation . Kind , rule . Generation . Clone . Namespace , rule . Generation . Clone . Name ) )
continue
}
sourceObj , newResObj := stripNonPolicyFields ( obj . Object , newRes . Object , logger )
if _ , err := gen . ValidateResourceWithPattern ( logger , newResObj , sourceObj ) ; err != nil {
enqueueBool = true
break
2021-01-27 23:41:22 +05:30
}
}
2020-12-24 18:39:23 +05:30
}
2021-01-27 23:41:22 +05:30
}
}
if enqueueBool {
grName := resLabels [ "policy.kyverno.io/gr-name" ]
gr , err := ws . grLister . Get ( grName )
if err != nil {
logger . Error ( err , "failed to get generate request" , "name" , grName )
2021-02-07 20:26:56 -08:00
return
2021-01-27 23:41:22 +05:30
}
2021-06-08 12:37:19 -07:00
ws . updateAnnotationInGR ( gr , logger )
2021-01-27 23:41:22 +05:30
}
}
2021-10-29 18:13:20 +02:00
func getGeneratedByResource ( newRes * unstructured . Unstructured , resLabels map [ string ] string , client * client . Client , rule kyverno . Rule , logger logr . Logger ) ( kyverno . Rule , error ) {
2021-04-27 01:28:34 +05:30
var apiVersion , kind , name , namespace string
2022-04-06 22:43:07 +02:00
sourceRequest := & admissionv1 . AdmissionRequest { }
2021-04-27 01:28:34 +05:30
kind = resLabels [ "kyverno.io/generated-by-kind" ]
name = resLabels [ "kyverno.io/generated-by-name" ]
if kind != "Namespace" {
namespace = resLabels [ "kyverno.io/generated-by-namespace" ]
}
obj , err := client . GetResource ( apiVersion , kind , namespace , name )
if err != nil {
logger . Error ( err , "source resource not found." )
return rule , err
}
rawObj , err := json . Marshal ( obj )
if err != nil {
logger . Error ( err , "failed to marshal resource" )
return rule , err
}
sourceRequest . Object . Raw = rawObj
sourceRequest . Operation = "CREATE"
ctx := enginectx . NewContext ( )
if err := ctx . AddRequest ( sourceRequest ) ; err != nil {
logger . Error ( err , "failed to load incoming request in context" )
return rule , err
}
if rule , err = variables . SubstituteAllInRule ( logger , ctx , rule ) ; err != nil {
logger . Error ( err , "variable substitution failed for rule %s" , rule . Name )
return rule , err
}
return rule , nil
}
2021-01-27 23:41:22 +05:30
//stripNonPolicyFields - remove feilds which get updated with each request by kyverno and are non policy fields
func stripNonPolicyFields ( obj , newRes map [ string ] interface { } , logger logr . Logger ) ( map [ string ] interface { } , map [ string ] interface { } ) {
2021-02-10 23:58:50 +05:30
if metadata , found := obj [ "metadata" ] ; found {
2021-02-10 00:04:57 +05:30
requiredMetadataInObj := make ( map [ string ] interface { } )
2021-02-10 23:58:50 +05:30
if annotations , found := metadata . ( map [ string ] interface { } ) [ "annotations" ] ; found {
delete ( annotations . ( map [ string ] interface { } ) , "kubectl.kubernetes.io/last-applied-configuration" )
requiredMetadataInObj [ "annotations" ] = annotations
2021-02-10 00:04:57 +05:30
}
2021-02-10 23:58:50 +05:30
if labels , found := metadata . ( map [ string ] interface { } ) [ "labels" ] ; found {
delete ( labels . ( map [ string ] interface { } ) , "generate.kyverno.io/clone-policy-name" )
requiredMetadataInObj [ "labels" ] = labels
2021-02-10 00:04:57 +05:30
}
obj [ "metadata" ] = requiredMetadataInObj
2021-01-27 23:41:22 +05:30
}
2021-02-10 00:04:57 +05:30
2021-02-10 23:58:50 +05:30
if metadata , found := newRes [ "metadata" ] ; found {
2021-02-10 00:04:57 +05:30
requiredMetadataInNewRes := make ( map [ string ] interface { } )
2021-02-10 23:58:50 +05:30
if annotations , found := metadata . ( map [ string ] interface { } ) [ "annotations" ] ; found {
requiredMetadataInNewRes [ "annotations" ] = annotations
2021-02-10 00:04:57 +05:30
}
2021-02-10 23:58:50 +05:30
if labels , found := metadata . ( map [ string ] interface { } ) [ "labels" ] ; found {
requiredMetadataInNewRes [ "labels" ] = labels
2021-02-10 00:04:57 +05:30
}
newRes [ "metadata" ] = requiredMetadataInNewRes
2021-01-27 23:41:22 +05:30
}
if _ , found := obj [ "status" ] ; found {
delete ( obj , "status" )
}
if _ , found := obj [ "spec" ] ; found {
delete ( obj [ "spec" ] . ( map [ string ] interface { } ) , "tolerations" )
}
if dataMap , found := obj [ "data" ] ; found {
keyInData := make ( [ ] string , 0 )
switch dataMap . ( type ) {
case map [ string ] interface { } :
2021-02-08 10:49:25 +05:30
for k := range dataMap . ( map [ string ] interface { } ) {
2021-01-27 23:41:22 +05:30
keyInData = append ( keyInData , k )
2020-12-24 18:39:23 +05:30
}
}
2021-01-27 23:41:22 +05:30
if len ( keyInData ) > 0 {
for _ , dataKey := range keyInData {
originalResourceData := dataMap . ( map [ string ] interface { } ) [ dataKey ]
replaceData := strings . Replace ( originalResourceData . ( string ) , "\n" , "" , - 1 )
dataMap . ( map [ string ] interface { } ) [ dataKey ] = replaceData
newResourceData := newRes [ "data" ] . ( map [ string ] interface { } ) [ dataKey ]
replacenewResourceData := strings . Replace ( newResourceData . ( string ) , "\n" , "" , - 1 )
newRes [ "data" ] . ( map [ string ] interface { } ) [ dataKey ] = replacenewResourceData
}
} else {
logger . V ( 4 ) . Info ( "data is not of type map[string]interface{}" )
}
2020-12-24 18:39:23 +05:30
}
2021-01-27 23:41:22 +05:30
return obj , newRes
2020-12-24 18:39:23 +05:30
}
2020-12-30 00:12:36 +05:30
//HandleDelete handles admission-requests for delete
2022-04-06 22:43:07 +02:00
func ( ws * WebhookServer ) handleDelete ( request * admissionv1 . AdmissionRequest ) {
2021-05-13 12:03:13 -07:00
logger := ws . log . WithValues ( "action" , "generation" , "uid" , request . UID , "kind" , request . Kind , "namespace" , request . Namespace , "name" , request . Name , "operation" , request . Operation , "gvk" , request . Kind . String ( ) )
2020-12-30 00:12:36 +05:30
resource , err := enginutils . ConvertToUnstructured ( request . OldObject . Raw )
if err != nil {
logger . Error ( err , "failed to convert object resource to unstructured format" )
}
resLabels := resource . GetLabels ( )
2022-04-06 22:43:07 +02:00
if resLabels [ "app.kubernetes.io/managed-by" ] == "kyverno" && request . Operation == admissionv1 . Delete {
2020-12-30 00:12:36 +05:30
grName := resLabels [ "policy.kyverno.io/gr-name" ]
gr , err := ws . grLister . Get ( grName )
if err != nil {
logger . Error ( err , "failed to get generate request" , "name" , grName )
2021-02-07 20:26:56 -08:00
return
2020-12-30 00:12:36 +05:30
}
2021-06-08 12:37:19 -07:00
ws . updateAnnotationInGR ( gr , logger )
2020-12-30 00:12:36 +05:30
}
}
2020-12-24 12:41:54 +05:30
func ( ws * WebhookServer ) deleteGR ( logger logr . Logger , engineResponse * response . EngineResponse ) {
2020-12-16 12:29:16 -08:00
logger . V ( 4 ) . Info ( "querying all generate requests" )
selector := labels . SelectorFromSet ( labels . Set ( map [ string ] string {
2021-06-30 00:43:11 +03:00
"generate.kyverno.io/policy-name" : engineResponse . PolicyResponse . Policy . Name ,
2020-12-23 13:06:48 +05:30
"generate.kyverno.io/resource-name" : engineResponse . PolicyResponse . Resource . Name ,
2020-12-23 12:20:29 +05:30
"generate.kyverno.io/resource-kind" : engineResponse . PolicyResponse . Resource . Kind ,
"generate.kyverno.io/resource-namespace" : engineResponse . PolicyResponse . Resource . Namespace ,
2020-12-16 12:29:16 -08:00
} ) )
grList , err := ws . grLister . List ( selector )
if err != nil {
logger . Error ( err , "failed to get generate request for the resource" , "kind" , engineResponse . PolicyResponse . Resource . Kind , "name" , engineResponse . PolicyResponse . Resource . Name , "namespace" , engineResponse . PolicyResponse . Resource . Namespace )
2021-02-07 20:26:56 -08:00
return
2020-12-16 12:29:16 -08:00
}
for _ , v := range grList {
err := ws . kyvernoClient . KyvernoV1 ( ) . GenerateRequests ( config . KyvernoNamespace ) . Delete ( contextdefault . TODO ( ) , v . GetName ( ) , metav1 . DeleteOptions { } )
if err != nil {
logger . Error ( err , "failed to update gr" )
}
}
}
2022-04-06 22:43:07 +02:00
func applyGenerateRequest ( request * admissionv1 . AdmissionRequest , gnGenerator generate . GenerateRequests , userRequestInfo kyverno . RequestInfo ,
action admissionv1 . Operation , engineResponses ... * response . EngineResponse ) ( failedGenerateRequest [ ] generateRequestResponse ) {
2020-07-09 11:48:34 -07:00
2021-10-02 00:09:29 +05:30
requestBytes , err := json . Marshal ( request )
if err != nil {
logger . Error ( err , "error loading request into context" )
}
admissionRequestInfo := kyverno . AdmissionRequestInfoObject {
AdmissionRequest : string ( requestBytes ) ,
Operation : action ,
}
2020-01-07 10:33:28 -08:00
for _ , er := range engineResponses {
2021-10-02 00:09:29 +05:30
gr := transform ( admissionRequestInfo , userRequestInfo , er )
2020-07-09 11:48:34 -07:00
if err := gnGenerator . Apply ( gr , action ) ; err != nil {
failedGenerateRequest = append ( failedGenerateRequest , generateRequestResponse { gr : gr , err : err } )
2020-01-07 10:33:28 -08:00
}
}
2020-12-01 12:30:08 -08:00
2020-07-09 11:48:34 -07:00
return
2020-01-07 10:33:28 -08:00
}
2021-10-02 00:09:29 +05:30
func transform ( admissionRequestInfo kyverno . AdmissionRequestInfoObject , userRequestInfo kyverno . RequestInfo , er * response . EngineResponse ) kyverno . GenerateRequestSpec {
2022-03-29 18:34:33 +05:30
var PolicyNameNamespaceKey string
if er . PolicyResponse . Policy . Namespace != "" {
PolicyNameNamespaceKey = fmt . Sprintf ( "%s" , er . PolicyResponse . Policy . Namespace + "/" + er . PolicyResponse . Policy . Name )
} else {
PolicyNameNamespaceKey = er . PolicyResponse . Policy . Name
}
2020-01-07 10:33:28 -08:00
gr := kyverno . GenerateRequestSpec {
2022-03-29 18:34:33 +05:30
Policy : PolicyNameNamespaceKey ,
2020-01-07 10:33:28 -08:00
Resource : kyverno . ResourceSpec {
2021-03-05 06:15:52 +05:30
Kind : er . PolicyResponse . Resource . Kind ,
Namespace : er . PolicyResponse . Resource . Namespace ,
Name : er . PolicyResponse . Resource . Name ,
APIVersion : er . PolicyResponse . Resource . APIVersion ,
2020-01-07 10:33:28 -08:00
} ,
Context : kyverno . GenerateRequestContext {
2021-10-02 00:09:29 +05:30
UserRequestInfo : userRequestInfo ,
AdmissionRequestInfo : admissionRequestInfo ,
2020-01-07 10:33:28 -08:00
} ,
}
2020-12-23 15:10:07 -08:00
2020-01-07 10:33:28 -08:00
return gr
}
2020-02-29 22:39:27 +05:30
2020-07-09 11:48:34 -07:00
type generateRequestResponse struct {
2021-10-29 18:13:20 +02:00
gr kyverno . GenerateRequestSpec
2020-07-09 11:48:34 -07:00
err error
}
func ( resp generateRequestResponse ) info ( ) string {
return strings . Join ( [ ] string { resp . gr . Resource . Kind , resp . gr . Resource . Namespace , resp . gr . Resource . Name } , "/" )
}
func ( resp generateRequestResponse ) error ( ) string {
return resp . err . Error ( )
}
func failedEvents ( err error , gr kyverno . GenerateRequestSpec , resource unstructured . Unstructured ) [ ] event . Info {
re := event . Info { }
re . Kind = resource . GetKind ( )
re . Namespace = resource . GetNamespace ( )
re . Name = resource . GetName ( )
re . Reason = event . PolicyFailed . String ( )
re . Source = event . GeneratePolicyController
re . Message = fmt . Sprintf ( "policy %s failed to apply: %v" , gr . Policy , err )
2020-07-20 08:00:02 -07:00
return [ ] event . Info { re }
2020-07-09 11:48:34 -07:00
}