From 89b211d1f951664cefd148daf2341f5634019fde Mon Sep 17 00:00:00 2001
From: belyshevdenis <belyshev.denis@apriorit.com>
Date: Tue, 19 Mar 2019 21:32:31 +0200
Subject: [PATCH] NK-31: Implemented webhook registration logic.

---
 definitions/examples/selector-policy.yaml | 21 +++++
 init.go                                   |  7 +-
 main.go                                   |  8 +-
 webhooks/registration.go                  | 98 +++++++++++++++++++++++
 4 files changed, 127 insertions(+), 7 deletions(-)
 create mode 100644 definitions/examples/selector-policy.yaml
 create mode 100644 webhooks/registration.go

diff --git a/definitions/examples/selector-policy.yaml b/definitions/examples/selector-policy.yaml
new file mode 100644
index 0000000000..d15312b76d
--- /dev/null
+++ b/definitions/examples/selector-policy.yaml
@@ -0,0 +1,21 @@
+apiVersion: policy.nirmata.io/v1alpha1
+kind : Policy
+metadata:
+  name: selector-policy
+spec:
+  failurePolicy: continueOnError
+  rules:
+  - resource:
+      kind: ConfigMap 
+      selector: 
+        matchLabels:
+          label1: test1
+        matchExpressions:
+        - key: label2
+          operator: In
+          values:
+          - test2
+    patch: 
+    - path: /
+      op : add
+      value : "20"
diff --git a/init.go b/init.go
index cd729e91dc..8940b39c8c 100644
--- a/init.go
+++ b/init.go
@@ -72,9 +72,4 @@ func initTlsPemsPair(config *rest.Config, client *kubeclient.KubeClient) (*utils
 	}
 
 	return tlsPair, nil
-}
-
-func registerWebhook(client *kubeclient.KubeClient) error {
-	// TODO
-	return nil
-}
+}
\ No newline at end of file
diff --git a/main.go b/main.go
index 1cf206a68d..d3dea750e1 100644
--- a/main.go
+++ b/main.go
@@ -6,6 +6,7 @@ import (
 
 	"github.com/nirmata/kube-policy/controller"
 	"github.com/nirmata/kube-policy/kubeclient"
+	"github.com/nirmata/kube-policy/webhooks"
 	"github.com/nirmata/kube-policy/server"
 
 	signals "k8s.io/sample-controller/pkg/signals"
@@ -23,9 +24,14 @@ func main() {
 		log.Fatalf("Error building kubeconfig: %v\n", err)
 	}
 
+	_, err = webhooks.RegisterMutationWebhook(clientConfig)
+	if err != nil {
+		log.Fatalf("Error registering mutation webhook server: %v\n", err)
+	}
+
 	controller, err := controller.NewPolicyController(clientConfig, nil)
 	if err != nil {
-		log.Fatalf("Error creating PolicyController! Error: %s\n", err)
+		log.Fatalf("Error creating PolicyController: %s\n", err)
 	}
 
 	kubeclient, err := kubeclient.NewKubeClient(clientConfig, nil)
diff --git a/webhooks/registration.go b/webhooks/registration.go
new file mode 100644
index 0000000000..db8912bf45
--- /dev/null
+++ b/webhooks/registration.go
@@ -0,0 +1,98 @@
+package webhooks
+import (
+	"io/ioutil"
+	"encoding/base64"
+
+	rest "k8s.io/client-go/rest"
+	meta "k8s.io/apimachinery/pkg/apis/meta/v1"
+	adm "k8s.io/api/admissionregistration/v1beta1"
+	types "k8s.io/api/admissionregistration/v1beta1"
+	admreg "k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1"
+)
+
+const (
+	webhookName = "nirmata-kube-policy-webhook-cfg"
+	mutationWebhookName = "webhook.nirmata.kube-policy"
+	webhookServiceNamespace = "default"
+	webhookServiceName = "kube-policy-svc"
+)
+
+var (
+	webhookPath = "mutate"
+	webhookLabels = map[string]string {
+	    "app": "kube-policy",
+    }
+)
+
+func RegisterMutationWebhook(config *rest.Config) (*types.MutatingWebhookConfiguration, error) {
+var result *types.MutatingWebhookConfiguration = nil
+
+	registrationClient, err := admreg.NewForConfig(config)
+	if err != nil {
+		return nil, err
+	}
+
+	result, err = registrationClient.MutatingWebhookConfigurations().Create(constructWebhookConfig(config))
+	if err != nil {
+		return nil, err
+	}
+
+	return result, nil
+}
+
+func constructWebhookConfig(config *rest.Config) *adm.MutatingWebhookConfiguration {
+	return &adm.MutatingWebhookConfiguration {
+		ObjectMeta: meta.ObjectMeta {
+			Name: webhookName,
+			Labels: webhookLabels,
+		},
+		Webhooks: []adm.Webhook {
+			adm.Webhook {
+				Name: mutationWebhookName,
+				ClientConfig: adm.WebhookClientConfig {
+                    Service: &adm.ServiceReference {
+						Namespace: webhookServiceNamespace,
+						Name: webhookServiceName,
+						Path: &webhookPath,
+					},
+					CABundle: extractCA(config),
+				},
+				Rules: []adm.RuleWithOperations {
+					adm.RuleWithOperations {
+						Operations: []adm.OperationType {
+							adm.Create,
+						},
+						Rule: adm.Rule {
+							APIGroups: []string {
+								"*",
+							},
+							APIVersions: []string {
+								"*",
+							},
+							Resources: []string {
+								"*/*",
+							},
+						},
+					},
+				},
+			},
+		},
+	}
+}
+
+func extractCA(config *rest.Config) (result []byte) {
+	
+	if config.TLSClientConfig.CAData != nil {
+		return config.TLSClientConfig.CAData
+	} else {
+		fileName := config.TLSClientConfig.CAFile
+		bytes, err := ioutil.ReadFile(fileName)
+
+		if err != nil {
+			return nil
+		}
+
+		base64.StdEncoding.Encode(result, bytes)
+		return
+	}
+}
\ No newline at end of file