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-20 12:51:25 -07:00
policyctr "github.com/nirmata/kyverno/pkg/policy"
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"
2019-08-14 19:00:37 -07:00
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2019-07-15 16:07:56 -07:00
"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
2019-08-14 19:00:37 -07:00
func ( ws * WebhookServer ) HandleValidation ( request * v1beta1 . AdmissionRequest , resource unstructured . Unstructured ) * v1beta1 . AdmissionResponse {
2019-08-09 16:55:43 -07:00
var policyInfos [ ] info . PolicyInfo
2019-08-20 12:51:25 -07:00
var policyStats [ ] policyctr . PolicyStat
// gather stats from the engine response
gatherStat := func ( policyName string , er engine . EngineResponse ) {
ps := policyctr . PolicyStat { }
ps . PolicyName = policyName
ps . ValidationExecutionTime = er . ExecutionTime
ps . RulesAppliedCount = er . RulesAppliedCount
policyStats = append ( policyStats , ps )
}
// send stats for aggregation
sendStat := func ( blocked bool ) {
for _ , stat := range policyStats {
stat . ResourceBlocked = blocked
//SEND
ws . policyStatus . SendStat ( stat )
}
}
2019-07-23 17:54:31 -07:00
2019-08-14 19:00:37 -07:00
glog . V ( 5 ) . 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
//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 )
2019-08-14 19:00:37 -07:00
glog . V ( 4 ) . Infof ( "Validating resource %s/%s/%s with policy %s with %d rules\n" , resource . GetKind ( ) , resource . GetNamespace ( ) , resource . GetName ( ) , policy . ObjectMeta . Name , len ( policy . Spec . Rules ) )
2019-07-15 16:07:56 -07:00
2019-08-14 19:00:37 -07:00
engineResponse := engine . Validate ( * policy , resource )
if len ( engineResponse . RuleInfos ) == 0 {
2019-07-15 16:07:56 -07:00
continue
}
2019-08-20 12:51:25 -07:00
gatherStat ( policy . Name , engineResponse )
2019-08-14 19:00:37 -07:00
if len ( engineResponse . 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-08-14 15:18:46 -07:00
policyInfo . AddRuleInfos ( engineResponse . RuleInfos )
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 ( ) )
2019-08-14 15:18:46 -07:00
for _ , r := range engineResponse . 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
}
}
2019-08-14 19:00:37 -07:00
2019-07-15 16:07:56 -07:00
policyInfos = append ( policyInfos , policyInfo )
2019-08-14 19:00:37 -07:00
2019-07-15 16:07:56 -07:00
}
2019-08-09 13:41:56 -07:00
// ADD EVENTS
2019-07-15 16:07:56 -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-07-23 18:29:44 -04:00
// If the validationFailureAction flag is set "audit",
2019-07-15 19:14:42 -07:00
// then we dont block the request and report the violations
2019-08-09 17:28:49 -07:00
ws . eventGen . Add ( eventsInfo ... )
2019-07-15 16:07:56 -07:00
}
2019-08-09 16:55:43 -07:00
2019-07-15 16:07:56 -07:00
// If Validation fails then reject the request
2019-07-23 18:29:44 -04:00
// violations are created if "audit" flag is set
2019-08-02 11:18:02 -07:00
// and if there are any then we dont block the resource creation
2019-07-15 19:14:42 -07:00
// Even if one the policy being applied
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-08-20 12:51:25 -07:00
sendStat ( true )
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-08-20 12:51:25 -07:00
sendStat ( false )
2019-07-15 16:07:56 -07:00
return & v1beta1 . AdmissionResponse {
Allowed : true ,
}
}