2019-07-15 16:07:56 -07:00
package webhooks
import (
2019-11-12 14:41:29 -08:00
"fmt"
2019-07-15 16:07:56 -07:00
"strings"
2019-08-26 13:34:42 -07:00
kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1alpha1"
"github.com/nirmata/kyverno/pkg/engine"
2019-11-12 14:41:29 -08:00
"github.com/nirmata/kyverno/pkg/policyviolation"
2019-08-26 13:34:42 -07:00
2019-07-15 16:07:56 -07:00
"github.com/golang/glog"
"github.com/nirmata/kyverno/pkg/event"
)
2019-08-26 13:34:42 -07:00
//generateEvents generates event info for the engine responses
2019-10-08 10:57:24 -07:00
func generateEvents ( engineResponses [ ] engine . EngineResponse , onUpdate bool ) [ ] event . Info {
2019-08-26 13:34:42 -07:00
var events [ ] event . Info
if ! isResponseSuccesful ( engineResponses ) {
for _ , er := range engineResponses {
if er . IsSuccesful ( ) {
// dont create events on success
2019-07-16 15:53:14 -07:00
continue
}
2019-08-26 13:34:42 -07:00
failedRules := er . GetFailedRules ( )
filedRulesStr := strings . Join ( failedRules , ";" )
if onUpdate {
var e event . Info
// UPDATE
// event on resource
e = event . NewEventNew (
er . PolicyResponse . Resource . Kind ,
er . PolicyResponse . Resource . APIVersion ,
er . PolicyResponse . Resource . Namespace ,
er . PolicyResponse . Resource . Name ,
event . RequestBlocked . String ( ) ,
event . FPolicyApplyBlockUpdate ,
filedRulesStr ,
er . PolicyResponse . Policy ,
)
glog . V ( 4 ) . Infof ( "UPDATE event on resource %s/%s/%s with policy %s" , er . PolicyResponse . Resource . Kind , er . PolicyResponse . Resource . Namespace , er . PolicyResponse . Resource . Name , er . PolicyResponse . Policy )
events = append ( events , e )
// event on policy
e = event . NewEventNew (
2019-09-12 15:04:35 -07:00
"ClusterPolicy" ,
2019-08-26 13:34:42 -07:00
kyverno . SchemeGroupVersion . String ( ) ,
"" ,
er . PolicyResponse . Policy ,
event . RequestBlocked . String ( ) ,
event . FPolicyBlockResourceUpdate ,
er . PolicyResponse . Resource . Namespace + "/" + er . PolicyResponse . Resource . Name ,
filedRulesStr ,
)
glog . V ( 4 ) . Infof ( "UPDATE event on policy %s" , er . PolicyResponse . Policy )
events = append ( events , e )
2019-07-15 16:07:56 -07:00
} else {
2019-08-26 13:34:42 -07:00
// CREATE
// event on policy
e := event . NewEventNew (
2019-09-12 15:04:35 -07:00
"ClusterPolicy" ,
2019-08-26 13:34:42 -07:00
kyverno . SchemeGroupVersion . String ( ) ,
"" ,
er . PolicyResponse . Policy ,
event . RequestBlocked . String ( ) ,
event . FPolicyApplyBlockCreate ,
er . PolicyResponse . Resource . Namespace + "/" + er . PolicyResponse . Resource . Name ,
filedRulesStr ,
)
glog . V ( 4 ) . Infof ( "CREATE event on policy %s" , er . PolicyResponse . Policy )
events = append ( events , e )
2019-07-15 16:07:56 -07:00
}
}
2019-08-26 13:34:42 -07:00
return events
}
if ! onUpdate {
// All policies were applied succesfully
// CREATE
for _ , er := range engineResponses {
successRules := er . GetSuccessRules ( )
successRulesStr := strings . Join ( successRules , ";" )
// event on resource
e := event . NewEventNew (
er . PolicyResponse . Resource . Kind ,
er . PolicyResponse . Resource . APIVersion ,
er . PolicyResponse . Resource . Namespace ,
er . PolicyResponse . Resource . Name ,
event . PolicyApplied . String ( ) ,
event . SRulesApply ,
successRulesStr ,
er . PolicyResponse . Policy ,
)
events = append ( events , e )
2019-07-15 16:07:56 -07:00
}
2019-08-26 13:34:42 -07:00
2019-07-15 16:07:56 -07:00
}
2019-08-26 13:34:42 -07:00
return events
2019-07-17 17:53:13 -07:00
}
2019-11-12 14:41:29 -08:00
func generatePV ( ers [ ] engine . EngineResponse , blocked bool ) [ ] policyviolation . Info {
var pvInfos [ ] policyviolation . Info
// generate PV for each
for _ , er := range ers {
// ignore creation of PV for resoruces that are yet to be assigned a name
if er . IsSuccesful ( ) {
continue
}
glog . V ( 4 ) . Infof ( "Building policy violation for engine response %v" , er )
// build policy violation info
pvInfos = append ( pvInfos , buildPVInfo ( er , blocked ) )
}
2019-11-12 18:25:50 -08:00
return pvInfos
2019-11-12 14:41:29 -08:00
}
func buildPVInfo ( er engine . EngineResponse , blocked bool ) policyviolation . Info {
info := policyviolation . Info {
Blocked : blocked ,
PolicyName : er . PolicyResponse . Policy ,
Resource : er . PatchedResource ,
Rules : buildViolatedRules ( er , blocked ) ,
}
return info
}
func buildViolatedRules ( er engine . EngineResponse , blocked bool ) [ ] kyverno . ViolatedRule {
blockMsg := fmt . Sprintf ( "Request Blocked for resource %s/%s; " , er . PolicyResponse . Resource . Kind , er . PolicyResponse . Resource . Name )
var violatedRules [ ] kyverno . ViolatedRule
// if resource was blocked we create dependent
dependant := kyverno . ManagedResourceSpec {
Kind : er . PolicyResponse . Resource . Kind ,
Namespace : er . PolicyResponse . Resource . Namespace ,
CreationBlocked : true ,
}
for _ , rule := range er . PolicyResponse . Rules {
if rule . Success {
continue
}
vrule := kyverno . ViolatedRule {
Name : rule . Name ,
Type : rule . Type ,
}
if blocked {
vrule . Message = blockMsg + rule . Message
vrule . ManagedResource = dependant
} else {
vrule . Message = rule . Message
}
violatedRules = append ( violatedRules , vrule )
}
return violatedRules
}