2019-07-15 16:07:56 -07:00
package webhooks
import (
"github.com/golang/glog"
engine "github.com/nirmata/kyverno/pkg/engine"
"github.com/nirmata/kyverno/pkg/info"
v1beta1 "k8s.io/api/admission/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
)
// HandleMutation handles mutating webhook admission request
func ( ws * WebhookServer ) HandleMutation ( request * v1beta1 . AdmissionRequest ) * v1beta1 . AdmissionResponse {
2019-07-23 17:54:31 -07:00
glog . V ( 4 ) . Infof ( "Receive request in mutating webhook: Kind=%s, Namespace=%s Name=%s UID=%s patchOperation=%s" ,
2019-07-21 14:13:00 -07:00
request . Kind . Kind , request . Namespace , request . Name , request . UID , request . Operation )
2019-07-15 16:07:56 -07:00
policies , err := ws . policyLister . List ( labels . NewSelector ( ) )
if err != nil {
// Unable to connect to policy Lister to access policies
glog . Error ( "Unable to connect to policy controller to access policies. Mutation Rules are NOT being applied" )
glog . Warning ( err )
return & v1beta1 . AdmissionResponse {
Allowed : true ,
}
}
2019-07-19 20:30:55 -07:00
rname := engine . ParseNameFromObject ( request . Object . Raw )
rns := engine . ParseNamespaceFromObject ( request . Object . Raw )
2019-07-20 23:58:46 -07:00
rkind := request . Kind . Kind
if rkind == "" {
2019-07-21 14:13:00 -07:00
glog . Errorf ( "failed to parse KIND from request: Namespace=%s Name=%s UID=%s patchOperation=%s\n" , request . Namespace , request . Name , request . UID , request . Operation )
2019-07-20 23:58:46 -07:00
}
2019-07-15 16:07:56 -07:00
var allPatches [ ] [ ] byte
policyInfos := [ ] * info . PolicyInfo { }
for _ , policy := range policies {
// check if policy has a rule for the admission request kind
if ! StringInSlice ( request . Kind . Kind , getApplicableKindsForPolicy ( policy ) ) {
continue
}
2019-07-19 12:47:20 -07:00
//TODO: HACK Check if an update of annotations
if checkIfOnlyAnnotationsUpdate ( request ) {
return & v1beta1 . AdmissionResponse {
Allowed : true ,
}
}
2019-07-15 16:07:56 -07:00
policyInfo := info . NewPolicyInfo ( policy . Name ,
rkind ,
rname ,
2019-07-15 19:14:42 -07:00
rns ,
policy . Spec . ValidationFailureAction )
2019-07-15 16:07:56 -07:00
glog . V ( 3 ) . Infof ( "Handling mutation for Kind=%s, Namespace=%s Name=%s UID=%s patchOperation=%s" ,
request . Kind . Kind , rns , rname , request . UID , request . Operation )
glog . Infof ( "Applying policy %s with %d rules\n" , policy . ObjectMeta . Name , len ( policy . Spec . Rules ) )
policyPatches , ruleInfos := engine . Mutate ( * policy , request . Object . Raw , request . Kind )
policyInfo . AddRuleInfos ( ruleInfos )
if ! policyInfo . IsSuccessful ( ) {
glog . Infof ( "Failed to apply policy %s on resource %s/%s" , policy . Name , rname , rns )
for _ , r := range ruleInfos {
2019-07-19 17:52:24 -07:00
glog . Warningf ( "%s: %s\n" , r . Name , r . Msgs )
2019-07-15 16:07:56 -07:00
}
} else {
2019-07-22 18:50:09 -04:00
// CleanUp Violations if exists
err := ws . violationBuilder . RemoveInactiveViolation ( policy . Name , request . Kind . Kind , rns , rname , info . Mutation )
if err != nil {
glog . Info ( err )
}
2019-07-19 20:30:55 -07:00
allPatches = append ( allPatches , policyPatches ... )
glog . Infof ( "Mutation from policy %s has applied succesfully to %s %s/%s" , policy . Name , request . Kind . Kind , rname , rns )
2019-07-15 16:07:56 -07:00
}
policyInfos = append ( policyInfos , policyInfo )
2019-07-19 20:30:55 -07:00
2019-07-17 15:04:02 -07:00
annPatch := addAnnotationsToResource ( request . Object . Raw , policyInfo , info . Mutation )
if annPatch != nil {
2019-07-24 14:25:28 -04:00
// add annotations
ws . annotationsController . Add ( rkind , rns , rname , annPatch )
2019-07-17 15:04:02 -07:00
}
2019-07-15 16:07:56 -07:00
}
if len ( allPatches ) > 0 {
2019-07-18 10:22:20 -07:00
eventsInfo , _ := newEventInfoFromPolicyInfo ( policyInfos , ( request . Operation == v1beta1 . Update ) , info . Mutation )
2019-07-15 16:07:56 -07:00
ws . eventController . Add ( eventsInfo ... )
}
ok , msg := isAdmSuccesful ( policyInfos )
if ok {
patchType := v1beta1 . PatchTypeJSONPatch
return & v1beta1 . AdmissionResponse {
Allowed : true ,
2019-07-19 20:30:55 -07:00
Patch : engine . JoinPatches ( allPatches ) ,
2019-07-15 16:07:56 -07:00
PatchType : & patchType ,
}
}
return & v1beta1 . AdmissionResponse {
Allowed : false ,
Result : & metav1 . Status {
Message : msg ,
} ,
}
}