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:
parent
5680480600
commit
3661e012a5
2 changed files with 116 additions and 8 deletions
|
@ -14,11 +14,6 @@ case $i in
|
||||||
esac
|
esac
|
||||||
done
|
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"
|
hub_user_name="nirmata"
|
||||||
project_name="kube-policy"
|
project_name="kube-policy"
|
||||||
|
|
||||||
|
@ -30,6 +25,11 @@ chmod +x "${certsGenerator}"
|
||||||
|
|
||||||
if [ -z "${namespace}" ]; then # controller is launched locally
|
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
|
${certsGenerator} "--serverIp=${serverIp}" || exit 2
|
||||||
|
|
||||||
echo "Applying webhook..."
|
echo "Applying webhook..."
|
||||||
|
|
114
server/server.go
114
server/server.go
|
@ -1,13 +1,21 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http/httputil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
//"net/http/httputil"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"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
|
// WebhookServer is a struct that describes
|
||||||
|
@ -17,9 +25,109 @@ type WebhookServer struct {
|
||||||
logger *log.Logger
|
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) {
|
func (ws *WebhookServer) serve(w http.ResponseWriter, r *http.Request) {
|
||||||
dump, _ := httputil.DumpRequest(r, true)
|
if r.URL.Path == "/mutate" {
|
||||||
ws.logger.Printf("%s", dump)
|
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
|
// RunAsync runs TLS server in separate
|
||||||
|
|
Loading…
Add table
Reference in a new issue