1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-04-09 02:29:22 +00:00

Merge branch '160_generate_events' into proposal_result_structure

# Conflicts:
#	pkg/engine/engine.go
#	pkg/event/controller.go
#	pkg/event/msgbuilder.go
#	pkg/event/util.go
#	pkg/info/info.go
#	pkg/webhooks/server.go
This commit is contained in:
Shuting Zhao 2019-06-26 18:16:06 -07:00
commit 639882dc06
13 changed files with 199 additions and 32 deletions

View file

@ -16,4 +16,4 @@ spec:
containers:
# if the image tag is latest, set the imagePullPolicy to Always
- (image): "*:latest"
imagePullPolicy: "Always"
imagePullPolicy: "IfNotPresent"

View file

@ -51,7 +51,7 @@ func main() {
if err != nil {
glog.Fatalf("Failed to initialize TLS key/certificate pair: %v\n", err)
}
server, err := webhooks.NewWebhookServer(client, tlsPair, policyInformerFactory, filterK8Kinds)
server, err := webhooks.NewWebhookServer(client, tlsPair, policyInformerFactory, eventController, filterK8Kinds)
if err != nil {
glog.Fatalf("Unable to create webhook server: %v\n", err)
}

View file

@ -181,14 +181,12 @@ func (pc *PolicyController) syncHandler(obj interface{}) error {
glog.Infof("process policy %s on existing resources", policy.GetName())
policyInfos := engine.ProcessExisting(pc.client, policy)
events := createEvents(pc.eventController, policyInfos)
for _, e := range events {
pc.eventController.Add(e)
}
pc.eventController.Add(events)
return nil
}
func createEvents(eventController event.Generator, policyInfos []*info.PolicyInfo) []event.Info {
events := []event.Info{}
func createEvents(eventController event.Generator, policyInfos []*info.PolicyInfo) []*event.Info {
events := []*event.Info{}
// Create events from the policyInfo
for _, policyInfo := range policyInfos {
fruleNames := []string{}
@ -196,7 +194,7 @@ func createEvents(eventController event.Generator, policyInfos []*info.PolicyInf
for _, rule := range policyInfo.Rules {
if !rule.IsSuccessful() {
e := event.Info{}
e := &event.Info{}
fruleNames = append(fruleNames, rule.Name)
switch rule.RuleType {
case info.Mutation, info.Validation, info.Generation:

View file

@ -58,7 +58,7 @@ func ProcessExisting(client *client.Client, policy *types.Policy) []*info.Policy
policyInfo, err := applyPolicy(client, policy, r)
if err != nil {
glog.Error("unable to apply policy %s on resource %s/%s", policy.Name, r.resource.GetName(), r.resource.GetNamespace())
glog.Errorf("unable to apply policy %s on resource %s/%s", policy.Name, r.resource.GetName(), r.resource.GetNamespace())
glog.Error(err)
continue
}

View file

@ -30,9 +30,9 @@ func Generate(client *client.Client, policy kubepolicy.Policy, rawResource []byt
err := applyRuleGenerator(client, rawResource, rule.Generation, gvk, processExisting)
if err != nil {
ri.Fail()
ri.Addf(" Failed to apply rule generator. err %v", err)
ri.Addf("Rule %s: Failed to apply rule generator, err %v.", rule.Name, err)
} else {
ri.Add("Generation succesfully")
ri.Addf("Rule %s: Generation succesfully.", rule.Name)
}
ris = append(ris, ri)
}

View file

@ -29,9 +29,9 @@ func Mutate(policy kubepolicy.Policy, rawResource []byte, gvk metav1.GroupVersio
overlayPatches, err := ProcessOverlay(rule, rawResource, gvk)
if err != nil {
ri.Fail()
ri.Addf("Overlay application has failed. err %s", err)
ri.Addf("Rule %s: Overlay application has failed, err %s.", rule.Name, err)
} else {
ri.Add("Overlay succesfully applied")
ri.Addf("Rule %s: Overlay succesfully applied.", rule.Name)
//TODO: patchbytes -> string
//glog.V(3).Info(" Overlay succesfully applied. Patch %s", string(overlayPatches))
allPatches = append(allPatches, overlayPatches...)
@ -44,10 +44,10 @@ func Mutate(policy kubepolicy.Policy, rawResource []byte, gvk metav1.GroupVersio
if len(errs) > 0 {
ri.Fail()
for _, err := range errs {
ri.Addf("Patches application has failed. err %s", err)
ri.Addf("Rule %s: Patches application has failed, err %s.", rule.Name, err)
}
} else {
ri.Add("Patches succesfully applied")
ri.Addf("Rule %s: Patches succesfully applied.", rule.Name)
//TODO: patchbytes -> string
//glog.V(3).Info("Patches succesfully applied. Patch %s", string(overlayPatches))
allPatches = append(allPatches, rulePatches...)

View file

@ -41,9 +41,9 @@ func Validate(policy kubepolicy.Policy, rawResource []byte, gvk metav1.GroupVers
err := validateResourceWithPattern(resource, rule.Validation.Pattern)
if err != nil {
ri.Fail()
ri.Addf("Validation has failed. err %s", err)
ri.Addf("Rule %s: Validation has failed, err %s.", rule.Name, err)
} else {
ri.Add("Validation succesfully")
ri.Addf("Rule %s: Validation succesfully.", rule.Name)
}
ris = append(ris, ri)

View file

@ -28,7 +28,7 @@ type controller struct {
//Generator to generate event
type Generator interface {
Add(info Info)
Add(infoList []*Info)
}
//Controller api
@ -74,8 +74,10 @@ func initRecorder(client *client.Client) record.EventRecorder {
return recorder
}
func (c *controller) Add(info Info) {
c.queue.Add(info)
func (c *controller) Add(infoList []*Info) {
for _, info := range infoList {
c.queue.Add(*info)
}
}
func (c *controller) Run(stopCh <-chan struct{}) {
@ -153,12 +155,12 @@ func (c *controller) SyncHandler(key Info) error {
}
//NewEvent returns a new event
func NewEvent(rkind string, rnamespace string, rname string, reason Reason, message MsgKey, args ...interface{}) Info {
func NewEvent(rkind string, rnamespace string, rname string, reason Reason, message MsgKey, args ...interface{}) *Info {
msgText, err := getEventMsg(message, args...)
if err != nil {
glog.Error(err)
}
return Info{
return &Info{
Kind: rkind,
Name: rname,
Namespace: rnamespace,

View file

@ -7,9 +7,14 @@ import (
//PolicyInfo defines policy information
type PolicyInfo struct {
Name string
RKind string
RName string
// Name is policy name
Name string
// RKind represents the resource kind
RKind string
// RName is resource name
RName string
// Namespace is the ns of resource
// empty on non-namespaced resources
RNamespace string
Rules []*RuleInfo
success bool

View file

@ -16,6 +16,7 @@ import (
"github.com/nirmata/kyverno/pkg/config"
client "github.com/nirmata/kyverno/pkg/dclient"
engine "github.com/nirmata/kyverno/pkg/engine"
"github.com/nirmata/kyverno/pkg/event"
"github.com/nirmata/kyverno/pkg/info"
"github.com/nirmata/kyverno/pkg/sharedinformer"
tlsutils "github.com/nirmata/kyverno/pkg/tls"
@ -27,10 +28,11 @@ import (
// WebhookServer contains configured TLS server with MutationWebhook.
// MutationWebhook gets policies from policyController and takes control of the cluster with kubeclient.
type WebhookServer struct {
server http.Server
client *client.Client
policyLister v1alpha1.PolicyLister
filterKinds []string
server http.Server
client *client.Client
policyLister v1alpha1.PolicyLister
eventController event.Generator
filterKinds []string
}
// NewWebhookServer creates new instance of WebhookServer accordingly to given configuration
@ -39,6 +41,7 @@ func NewWebhookServer(
client *client.Client,
tlsPair *tlsutils.TlsPemPair,
shareInformer sharedinformer.PolicyInformer,
eventController event.Generator,
filterKinds []string) (*WebhookServer, error) {
if tlsPair == nil {
@ -53,9 +56,10 @@ func NewWebhookServer(
tlsConfig.Certificates = []tls.Certificate{pair}
ws := &WebhookServer{
client: client,
policyLister: shareInformer.GetLister(),
filterKinds: parseKinds(filterKinds),
client: client,
policyLister: shareInformer.GetLister(),
eventController: eventController,
filterKinds: parseKinds(filterKinds),
}
mux := http.NewServeMux()
mux.HandleFunc(config.MutatingWebhookServicePath, ws.serve)
@ -164,7 +168,9 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest) *v1be
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 {
@ -177,6 +183,9 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest) *v1be
policyInfos = append(policyInfos, policyInfo)
}
// eventsInfo := NewEventInfoFromPolicyInfo(policyInfos)
// ws.eventController.Add(eventsInfo)
ok, msg := isAdmSuccesful(policyInfos)
if ok {
patchType := v1beta1.PatchTypeJSONPatch
@ -370,3 +379,49 @@ func (ws *WebhookServer) bodyToAdmissionReview(request *http.Request, writer htt
return admissionReview
}
const policyKind = "Policy"
// func NewEventInfoFromPolicyInfo(policyInfoList []*info.PolicyInfo) []*event.Info {
// var eventsInfo []*event.Info
// ok, msg := isAdmSuccesful(policyInfoList)
// if ok {
// for _, pi := range policyInfoList {
// ruleNames := getRuleNames(*pi, true)
// eventsInfo = append(eventsInfo,
// event.NewEvent(pi.Kind, pi.Namespace+"/"+pi.Resource, event.PolicyApplied, event.SRulesApply, ruleNames, pi.Name))
// eventsInfo = append(eventsInfo,
// event.NewEvent(policyKind, pi.Name, event.PolicyApplied, event.SPolicyApply, pi.Name, pi.Resource))
// glog.V(3).Infof("Success events info prepared for %s/%s and %s/%s\n", policyKind, pi.Name, pi.Kind, pi.Resource)
// }
// return eventsInfo
// }
// for _, pi := range policyInfoList {
// ruleNames := getRuleNames(*pi, false)
// eventsInfo = append(eventsInfo,
// event.NewEvent(policyKind, pi.Name, event.RequestBlocked, event.FPolicyApplyBlockCreate, pi.Resource, ruleNames))
// glog.V(3).Infof("Rule(s) %s of policy %s blocked resource creation, error: %s\n", ruleNames, pi.Name, msg)
// }
// return eventsInfo
// }
func getRuleNames(policyInfo info.PolicyInfo, onSuccess bool) string {
var ruleNames []string
for _, rule := range policyInfo.Rules {
if onSuccess {
if rule.IsSuccessful() {
ruleNames = append(ruleNames, rule.Name)
}
} else {
if !rule.IsSuccessful() {
ruleNames = append(ruleNames, rule.Name)
}
}
}
return strings.Join(ruleNames, ",")
}

View file

@ -34,3 +34,4 @@ chmod +x "${certsGenerator}"
${certsGenerator} "--service=${service}" "--serverIP=${serverIP}" || exit 2
echo -e "\n### You can build and run kyverno project locally.\n### To check its work, run it with flags --kubeconfig and --serverIP parameters."
sudo ./kyverno --kubeconfig ~/.kube/config --serverIP=10.0.0.11 -v 4

25
test/mix/nginx.yaml Normal file
View file

@ -0,0 +1,25 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
cli: test
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nirmata/nginx:green
# imagePullPolicy: Always
ports:
- containerPort: 80
- name: nginx1
image: launcher.gcr.io/google/nginx1

81
test/mix/policy.yaml Normal file
View file

@ -0,0 +1,81 @@
apiVersion : kyverno.io/v1alpha1
kind : Policy
metadata :
name : policy-deployment
spec :
rules:
- name: add-label
resource:
kinds :
- Deployment
selector :
matchLabels :
cli: test
mutate:
patches:
- path: /metadata/labels/isMutated
op: add
value: "true"
overlay:
spec:
template:
spec:
containers:
# if the image nginx, set the imagePullPolicy to Always
- (image): "*nginx*"
imagePullPolicy: "Always"
- name: add-label2
resource:
kinds :
- Deployment
selector :
matchLabels :
cli: test
mutate:
patches:
- path: /metadata/labels/app1
op: replace
value: "nginx_is_mutated"
- name: add-label3
resource:
kinds :
- Deployment
selector :
matchLabels :
cli: test
mutate:
patches:
- path: /metadata/labels/app2
op: add
value: "nginx_is_mutated2"
- name: check-image
resource:
kinds :
- Deployment
selector :
matchLabels :
cli: test
validate:
message: "The imagePullPolicy must be Always when using image nginx"
pattern:
spec:
template:
spec:
containers:
- (image): "*nginx*"
imagePullPolicy: "Always"
- name: check-registries
resource:
kinds:
- Deployment
- StatefulSet
validate:
message: "Registry is not allowed"
pattern:
spec:
template:
spec:
containers:
- name: "*"
# Check allowed registries
image: "*nirmata/* | launcher.gcr.io/*"