1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-05 15:37:19 +00:00

NK-10: Implemented basic logic for mutation, added logs

This commit is contained in:
belyshevdenis 2019-02-15 20:00:49 +02:00
parent 5680480600
commit 3661e012a5
2 changed files with 116 additions and 8 deletions

View file

@ -14,11 +14,6 @@ case $i in
esac
done
if [ -z "${serverIp}" ]; then
# This is the standard IP of minikube
serverIp="192.168.10.117" #TODO: ! Read it from ~/.kube/config !
fi
hub_user_name="nirmata"
project_name="kube-policy"
@ -30,6 +25,11 @@ chmod +x "${certsGenerator}"
if [ -z "${namespace}" ]; then # controller is launched locally
if [ -z "${serverIp}" ]; then
echo "--serverIp should be explicitly specified if --namespace is empty"
exit 1
fi
${certsGenerator} "--serverIp=${serverIp}" || exit 2
echo "Applying webhook..."

View file

@ -1,13 +1,21 @@
package server
import (
"net/http/httputil"
"io/ioutil"
"net/http"
//"net/http/httputil"
"crypto/tls"
"context"
"time"
"log"
"os"
"fmt"
"encoding/json"
v1beta1 "k8s.io/api/admission/v1beta1"
//appsv1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kubernetes/pkg/apis/core"
)
// WebhookServer is a struct that describes
@ -17,9 +25,109 @@ type WebhookServer struct {
logger *log.Logger
}
type patchOperation struct {
Op string `json:"op"`
Path string `json:"path"`
Value interface{} `json:"value,omitempty"`
}
func (ws *WebhookServer) serve(w http.ResponseWriter, r *http.Request) {
dump, _ := httputil.DumpRequest(r, true)
ws.logger.Printf("%s", dump)
if r.URL.Path == "/mutate" {
admissionReview := ws.parseAdmissionReview(r, w)
if admissionReview == nil {
return
}
admissionResponse := ws.mutate(admissionReview)
if admissionResponse != nil {
admissionReview.Response = admissionResponse
if admissionReview.Request != nil {
admissionReview.Response.UID = admissionReview.Request.UID
}
}
responseJson, err := json.Marshal(admissionReview)
if err != nil {
http.Error(w, fmt.Sprintf("Could not encode response: %v", err), http.StatusInternalServerError)
}
ws.logger.Printf("Response body: %v", string(responseJson))
if _, err := w.Write(responseJson); err != nil {
http.Error(w, fmt.Sprintf("could not write response: %v", err), http.StatusInternalServerError)
}
}
http.Error(w, fmt.Sprintf("Unexpected method path: %v", r.URL.Path), http.StatusNotFound)
}
// Answers to the http.ResponseWriter if request is not valid
func (ws *WebhookServer) parseAdmissionReview(request *http.Request, writer http.ResponseWriter) *v1beta1.AdmissionReview {
var body []byte
if request.Body != nil {
if data, err := ioutil.ReadAll(request.Body); err == nil {
body = data
}
}
if len(body) == 0 {
http.Error(writer, "empty body", http.StatusBadRequest)
return nil
}
contentType := request.Header.Get("Content-Type")
if contentType != "application/json" {
http.Error(writer, "invalid Content-Type, expect `application/json`", http.StatusUnsupportedMediaType)
return nil
}
admissionReview := &v1beta1.AdmissionReview{}
if err := json.Unmarshal(body, &admissionReview); err != nil {
http.Error(writer, "Can't decode body as AdmissionReview", http.StatusExpectationFailed)
return nil
} else {
return admissionReview
}
}
func (ws *WebhookServer) mutate(ar *v1beta1.AdmissionReview) *v1beta1.AdmissionResponse {
req := ar.Request
ws.logger.Printf("AdmissionReview for Kind=%v, Namespace=%v Name=%v (%v) UID=%v patchOperation=%v UserInfo=%v",
req.Kind.Kind, req.Namespace, req.Name, req.UID, req.Operation, req.UserInfo)
if req.Kind.Kind == "ConfigMap" {
var configMap core.ConfigMap
if err := json.Unmarshal(req.Object.Raw, &configMap); err != nil {
ws.logger.Printf("Could not unmarshal raw object: %v", err)
return &v1beta1.AdmissionResponse{
Result: &metav1.Status{
Message: err.Error(),
},
}
}
for k, v := range configMap.Data {
ws.logger.Printf("CONFIG MAP DATA: %v=%v", k, v)
}
patch := patchOperation{
Path: "labels/isMutated",
Op: "Add",
Value: "TRUE",
}
patchBytes, _ := json.Marshal(patch)
ws.logger.Printf("AdmissionResponse: patch=%v\n", "TODO")
return &v1beta1.AdmissionResponse{
Allowed: true,
Patch: patchBytes,
PatchType: func() *v1beta1.PatchType {
pt := v1beta1.PatchTypeJSONPatch
return &pt
}(),
}
} else {
return &v1beta1.AdmissionResponse{
Allowed: true,
}
}
}
// RunAsync runs TLS server in separate