From 0f78f5cb82acb63371e0fc40c5ab89ae8b0460ea Mon Sep 17 00:00:00 2001 From: belyshevdenis Date: Tue, 19 Feb 2019 18:01:47 +0200 Subject: [PATCH] NK-10: Small fixes after dev testing --- .gitignore | 1 + controller/controller.go | 6 ++-- scripts/README.md | 17 ++++++---- scripts/deploy-controller.sh | 19 ++++++----- scripts/generate-server-cert.sh | 17 +++++----- server/server.go | 59 ++++++++++++++++++--------------- 6 files changed, 63 insertions(+), 56 deletions(-) diff --git a/.gitignore b/.gitignore index 883a7fa73b..2d94abef18 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ pkg/apis/policy/v1alpha1/zz_generated.deepcopy.go certs kube-policy Gopkg.lock +Dockerfile \ No newline at end of file diff --git a/controller/controller.go b/controller/controller.go index 15e86e601a..2ea3ab2a86 100644 --- a/controller/controller.go +++ b/controller/controller.go @@ -54,7 +54,7 @@ func NewController(masterURL, kubeconfigPath string, logger *log.Logger) (*Contr // Run is main controller thread func (c *Controller) Run(stopCh <-chan struct{}) { - c.policyInformerFactory.Start(stopCh) + //c.policyInformerFactory.Start(stopCh) } // GetPolicies retrieves all policy resources @@ -62,13 +62,11 @@ func (c *Controller) Run(stopCh <-chan struct{}) { func (c *Controller) GetPolicies() ([]*types.Policy, error) { // Create nil Selector to grab all the policies cachedPolicies, err := c.policyLister.List(labels.NewSelector()) - - var policies []*types.Policy - if err != nil { return nil, err } + var policies []*types.Policy for _, elem := range cachedPolicies { policies = append(policies, elem.DeepCopy()) } diff --git a/scripts/README.md b/scripts/README.md index f336e95ec5..9452b1796e 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -8,15 +8,18 @@ Compiles the project to go executable, generates docker image and pushes it to t ### generate-server-cert.sh ### Generates TLS certificate and key that used by webhook server. Example: `scripts/generate-server-cert.sh --service=kube-policy-svc --namespace=my_namespace --serverIp=192.168.10.117` -* `--service` identifies the service for in-cluster webhook server. Do not specify it if you plan to run webhook server outside the cluster. -* `--namespace` identifies the namespace for in-cluster webhook server. Default value is "default". -* `--serverIp` is the IP of master node, it can be found in `~/.kube/config`: clusters.cluster[0].server. **The default is hardcoded value**, so you should explicitly specify it. +* `--service` identifies the service for in-cluster webhook server. Do not specify it if you plan to run webhook server outside the cluster, or cpecify 'localhost' if you want to run controller locally. +* `--namespace` identifies the namespace for in-cluster webhook server. Do not specify it if you plan to run controller locally. +* `--serverIp` is the IP of master node, it can be found in `~/.kube/config`: clusters.cluster[0].server. You should explicitly specify it. ### deploy-controller.sh ### -Prepares controller for current environment in 1 of 2 possible modes: free (local) and in-cluster. Usage: -`scripts/deploy-controller.sh --namespace=my_namespace --serverIp=192.168.10.117` -* --namespace identifies the namespace for in-cluster webhook server. Do not specify it if you plan to run webhook server outside the cluster. -* --serverIp is the IP of master node, means the same as for `generate-server-cert.sh`. +Prepares controller for free (local) or in-cluster use. Uses `generate-server-cert.sh` inside and has the same parameters with almost same meaning: +* `--service` - the name of the service which will be created for the controller. Use 'localhost' value to deploy controller locally. The default is 'kube-policu-svc' +* `--namespace` - the target namespace to deploy the controller. Do not specify it if you want to depoloy controller locally. +* `--serverIp` means the same as for `generate-server-cert.sh` +Examples: +`scripts/deploy-controller.sh --service=my-kube-policy --namespace=my_namespace --serverIp=192.168.10.117` - deploy controller to the cluster with master node '192.168.10.117' to the namespace 'my_namespace' as a service 'my-kube-policy' +`scripts/deploy-controller.sh --service=localhost --serverIp=192.168.10.117` - deploy controller locally for usage in cluster with mnaster node at '192.168.10.117' ### test-web-hook.sh ### Quickly creates and deletes test config map. If your webhook server is running, you should see the corresponding output from it. Use this script after `deploy-controller.sh`. diff --git a/scripts/deploy-controller.sh b/scripts/deploy-controller.sh index 061865d0fd..fe33018a47 100755 --- a/scripts/deploy-controller.sh +++ b/scripts/deploy-controller.sh @@ -3,6 +3,10 @@ for i in "$@" do case $i in + --service=*) + service_name="${i#*=}" + shift + ;; --namespace=*) namespace="${i#*=}" shift @@ -17,20 +21,17 @@ done hub_user_name="nirmata" project_name="kube-policy" -service_name="${project_name}-svc" +if [ -z "${service_name}" ]; then + service_name="${project_name}-svc" +fi echo "Generating certificate for the service ${service_name}..." certsGenerator="./scripts/generate-server-cert.sh" chmod +x "${certsGenerator}" -if [ -z "${namespace}" ]; then # controller is launched locally +if [ -z "${namespace}" ]; then # controller should be 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} "--service=${service_name}" "--serverIp=${serverIp}" || exit 2 echo "Applying webhook..." kubectl delete -f crd/MutatingWebhookConfiguration_local.yaml @@ -38,7 +39,7 @@ if [ -z "${namespace}" ]; then # controller is launched locally echo -e "\n### You can build and run kube-policy project locally.\n### To check its work, run it with parameters -cert and -key, which contain generated TLS certificate and key (see their paths in log above)." -else # controller is launched within a cluster +else # controller should be launched within a cluster ${certsGenerator} "--service=${service_name}" "--namespace=${namespace}" "--serverIp=${serverIp}" || exit 2 diff --git a/scripts/generate-server-cert.sh b/scripts/generate-server-cert.sh index 2dee26f47a..4e707b04f2 100755 --- a/scripts/generate-server-cert.sh +++ b/scripts/generate-server-cert.sh @@ -18,10 +18,6 @@ case $i in esac done -if [ -z "${namespace}" ]; then - namespace="default" -fi - echo "service is $service" echo "namespace is $namespace" echo "serverIp is $serverIp" @@ -53,15 +49,18 @@ outKeyFile=${destdir}/server-key.pem outCertFile=${destdir}/server.crt openssl genrsa -out ${outKeyFile} 2048 || exit 2 + if [ ! -z "${service}" ]; then - subjectCN="${service}.${namespace}.svc" - echo "Configuring work WITHIN a cluster with CN=${subjectCN}" + if [ ! -z "${namespace}" ]; then + subjectCN="${service}.${namespace}.svc" + else + subjectCN="${service}" + fi else subjectCN=${serverIp} - echo "Configuring work OUTSIDE a cluster with CN=${subjectCN}" fi - -openssl req -new -key ${destdir}/server-key.pem -subj "/CN=${subjectCN}" -out ${tmpdir}/server.csr -config ${tmpdir}/csr.conf || exit 3 +echo "Generating certificate for CN=${subjectCN}" +openssl req -new -key ${destdir}/server-key.pem -subj "/CN=${service}.${namespace}.svc" -out ${tmpdir}/server.csr -config ${tmpdir}/csr.conf || exit 3 CSR_NAME=${service}.cert-request kubectl delete csr ${CSR_NAME} 2>/dev/null diff --git a/server/server.go b/server/server.go index 8a246cc44f..7a55a7ee77 100644 --- a/server/server.go +++ b/server/server.go @@ -1,24 +1,22 @@ package server import ( - "io/ioutil" - "net/http" - //"net/http/httputil" - "crypto/tls" "context" - "time" - "log" - "os" - "fmt" + "crypto/tls" "encoding/json" + "fmt" + "io/ioutil" + "log" + "net/http" + "os" + "time" 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" + coreTypes "k8s.io/kubernetes/pkg/apis/core" ) -// WebhookServer is a struct that describes +// WebhookServer is a struct that describes // TLS server with mutation webhook type WebhookServer struct { server http.Server @@ -37,7 +35,7 @@ func (ws *WebhookServer) serve(w http.ResponseWriter, r *http.Request) { if admissionReview == nil { return } - + admissionResponse := ws.mutate(admissionReview) if admissionResponse != nil { admissionReview.Response = admissionResponse @@ -53,7 +51,7 @@ func (ws *WebhookServer) serve(w http.ResponseWriter, r *http.Request) { 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("could not write response: %v", err), http.StatusOK) } } @@ -84,19 +82,20 @@ func (ws *WebhookServer) parseAdmissionReview(request *http.Request, writer http http.Error(writer, "Can't decode body as AdmissionReview", http.StatusExpectationFailed) return nil } else { + ws.logger.Printf("Request body:\n%v", string(body)) return admissionReview } } func (ws *WebhookServer) mutate(ar *v1beta1.AdmissionReview) *v1beta1.AdmissionResponse { - req := ar.Request + request := 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) + ws.logger.Printf("AdmissionReview for Kind=%v, Namespace=%v Name=%v UID=%v patchOperation=%v UserInfo=%v", + request.Kind.Kind, request.Namespace, request.Name, request.UID, request.Operation, request.UserInfo) - if req.Kind.Kind == "ConfigMap" { - var configMap core.ConfigMap - if err := json.Unmarshal(req.Object.Raw, &configMap); err != nil { + if admissionRequired(request) { + var configMap coreTypes.ConfigMap + if err := json.Unmarshal(request.Object.Raw, &configMap); err != nil { ws.logger.Printf("Could not unmarshal raw object: %v", err) return &v1beta1.AdmissionResponse{ Result: &metav1.Status{ @@ -108,9 +107,11 @@ func (ws *WebhookServer) mutate(ar *v1beta1.AdmissionReview) *v1beta1.AdmissionR ws.logger.Printf("CONFIG MAP DATA: %v=%v", k, v) } patch := patchOperation{ - Path: "labels/isMutated", - Op: "Add", - Value: "TRUE", + Path: "labels", + Op: "Add", + Value: map[string]string{ + "IS_MUTATED": "TRUE", + }, } patchBytes, _ := json.Marshal(patch) ws.logger.Printf("AdmissionResponse: patch=%v\n", "TODO") @@ -130,7 +131,11 @@ func (ws *WebhookServer) mutate(ar *v1beta1.AdmissionReview) *v1beta1.AdmissionR } } -// RunAsync runs TLS server in separate +func admissionRequired(request *v1beta1.AdmissionRequest) bool { + return request.Kind.Kind == "ConfigMap" +} + +// RunAsync runs TLS server in separate // thread and returns control immediately func (ws *WebhookServer) RunAsync() { go func(ws *WebhookServer) { @@ -156,7 +161,7 @@ func NewWebhookServer(certFile string, keyFile string, logger *log.Logger) *Webh if logger == nil { logger = log.New(os.Stdout, "", log.LstdFlags|log.Lshortfile) } - + var config tls.Config pair, err := tls.LoadX509KeyPair(certFile, keyFile) if err != nil { @@ -165,9 +170,9 @@ func NewWebhookServer(certFile string, keyFile string, logger *log.Logger) *Webh config.Certificates = []tls.Certificate{pair} mux := http.NewServeMux() - - ws := &WebhookServer { - server: http.Server { + + ws := &WebhookServer{ + server: http.Server{ Addr: ":443", // Listen on port for HTTPS requests TLSConfig: &config, Handler: mux,