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"
2019-08-13 13:15:04 -07:00
"github.com/nirmata/kyverno/pkg/policyviolation"
2019-08-17 09:45:57 -07:00
"github.com/nirmata/kyverno/pkg/utils"
2019-07-15 16:07:56 -07:00
v1beta1 "k8s.io/api/admission/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
2019-08-09 13:41:56 -07:00
"k8s.io/apimachinery/pkg/runtime/schema"
2019-07-15 16:07:56 -07:00
)
// HandleValidation handles validating webhook admission request
// If there are no errors in validating rule we apply generation rules
func ( ws * WebhookServer ) HandleValidation ( request * v1beta1 . AdmissionRequest ) * v1beta1 . AdmissionResponse {
2019-08-09 16:55:43 -07:00
var policyInfos [ ] info . PolicyInfo
2019-07-23 17:54:31 -07:00
glog . V ( 4 ) . Infof ( "Receive request in validating 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-08-09 16:55:43 -07:00
policies , err := ws . pLister . List ( labels . NewSelector ( ) )
2019-07-15 16:07:56 -07:00
if err != nil {
2019-08-09 13:41:56 -07:00
//TODO check if the CRD is created ?
2019-07-15 16:07:56 -07:00
// Unable to connect to policy Lister to access policies
glog . Error ( "Unable to connect to policy controller to access policies. Validation Rules are NOT being applied" )
glog . Warning ( err )
return & v1beta1 . AdmissionResponse {
Allowed : true ,
}
}
2019-07-17 23:13:28 -07:00
2019-08-09 13:41:56 -07:00
resource , err := convertToUnstructured ( request . Object . Raw )
if err != nil {
glog . Errorf ( "unable to convert raw resource to unstructured: %v" , err )
2019-07-20 23:58:46 -07:00
}
2019-08-09 13:41:56 -07:00
//TODO: check if resource gvk is available in raw resource,
// if not then set it from the api request
resource . SetGroupVersionKind ( schema . GroupVersionKind { Group : request . Kind . Group , Version : request . Kind . Version , Kind : request . Kind . Kind } )
//TODO: check if the name and namespace is also passed right in the resource?
// all the patches to be applied on the resource
2019-07-15 16:07:56 -07:00
for _ , policy := range policies {
2019-08-17 09:45:57 -07:00
if ! utils . Contains ( getApplicableKindsForPolicy ( policy ) , request . Kind . Kind ) {
2019-07-15 16:07:56 -07:00
continue
}
2019-08-09 13:41:56 -07:00
policyInfo := info . NewPolicyInfo ( policy . Name , resource . GetKind ( ) , resource . GetName ( ) , resource . GetNamespace ( ) , policy . Spec . ValidationFailureAction )
2019-07-15 16:07:56 -07:00
2019-08-09 13:41:56 -07:00
glog . V ( 4 ) . Infof ( "Handling validation for Kind=%s, Namespace=%s Name=%s UID=%s patchOperation=%s" ,
resource . GetKind ( ) , resource . GetNamespace ( ) , resource . GetName ( ) , request . UID , request . Operation )
glog . V ( 4 ) . Infof ( "Applying policy %s with %d rules\n" , policy . ObjectMeta . Name , len ( policy . Spec . Rules ) )
2019-07-15 16:07:56 -07:00
2019-08-13 11:32:12 -07:00
ruleInfos , err := engine . Validate ( * policy , * resource )
2019-07-15 16:07:56 -07:00
if err != nil {
// This is not policy error
// but if unable to parse request raw resource
// TODO : create event ? dont think so
glog . Error ( err )
continue
}
policyInfo . AddRuleInfos ( ruleInfos )
2019-08-09 16:55:43 -07:00
policyInfos = append ( policyInfos , policyInfo )
2019-07-15 16:07:56 -07:00
if ! policyInfo . IsSuccessful ( ) {
2019-08-09 13:41:56 -07:00
glog . Infof ( "Failed to apply policy %s on resource %s/%s" , policy . Name , resource . GetNamespace ( ) , resource . GetName ( ) )
glog . V ( 4 ) . Info ( "Failed rule details" )
2019-07-15 16:07:56 -07:00
for _ , r := range ruleInfos {
2019-08-09 13:41:56 -07:00
glog . V ( 4 ) . Infof ( "%s: %s\n" , r . Name , r . Msgs )
2019-07-15 16:07:56 -07:00
}
2019-08-09 13:41:56 -07:00
continue
2019-07-15 16:07:56 -07:00
}
2019-08-09 13:41:56 -07:00
if len ( ruleInfos ) > 0 {
glog . V ( 4 ) . Infof ( "Validation from policy %s has applied succesfully to %s %s/%s" , policy . Name , request . Kind . Kind , resource . GetNamespace ( ) , resource . GetName ( ) )
2019-07-17 17:53:13 -07:00
}
2019-07-15 16:07:56 -07:00
}
2019-08-09 13:41:56 -07:00
// ADD EVENTS
2019-08-09 17:28:49 -07:00
if len ( policyInfos ) > 0 && len ( policyInfos [ 0 ] . Rules ) != 0 {
2019-08-14 10:01:47 -07:00
eventsInfo := newEventInfoFromPolicyInfo ( policyInfos , ( request . Operation == v1beta1 . Update ) , info . Validation )
2019-08-09 17:28:49 -07:00
// If the validationFailureAction flag is set "audit",
// then we dont block the request and report the violations
ws . eventGen . Add ( eventsInfo ... )
}
2019-08-09 16:55:43 -07:00
2019-07-15 16:07:56 -07:00
ok , msg := isAdmSuccesful ( policyInfos )
2019-07-16 15:53:14 -07:00
if ! ok && toBlock ( policyInfos ) {
2019-07-15 16:07:56 -07:00
return & v1beta1 . AdmissionResponse {
Allowed : false ,
Result : & metav1 . Status {
Message : msg ,
} ,
}
}
2019-08-09 19:12:50 -07:00
// ADD POLICY VIOLATIONS
2019-08-13 13:15:04 -07:00
policyviolation . GeneratePolicyViolations ( ws . pvListerSynced , ws . pvLister , ws . kyvernoClient , policyInfos )
2019-08-09 19:12:50 -07:00
2019-07-15 16:07:56 -07:00
return & v1beta1 . AdmissionResponse {
Allowed : true ,
}
// Generation rules applied via generation controller
}