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:
commit
639882dc06
13 changed files with 199 additions and 32 deletions
|
@ -16,4 +16,4 @@ spec:
|
|||
containers:
|
||||
# if the image tag is latest, set the imagePullPolicy to Always
|
||||
- (image): "*:latest"
|
||||
imagePullPolicy: "Always"
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
|
|
2
main.go
2
main.go
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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...)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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, ",")
|
||||
}
|
||||
|
|
|
@ -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
25
test/mix/nginx.yaml
Normal 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
81
test/mix/policy.yaml
Normal 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/*"
|
Loading…
Add table
Reference in a new issue