diff --git a/definitions/MutatingWebhookConfiguration.yaml b/definitions/MutatingWebhookConfiguration.yaml index e421733fdd..420ee023d5 100644 --- a/definitions/MutatingWebhookConfiguration.yaml +++ b/definitions/MutatingWebhookConfiguration.yaml @@ -1,4 +1,5 @@ # MutatingWebhookConfiguration document which should be used when placing controller inside the cluster +# This configuration is just an example. Webhook for in-cluster configuration is registered by controller (see webhooks/registration.go). apiVersion: admissionregistration.k8s.io/v1beta1 kind: MutatingWebhookConfiguration metadata: diff --git a/definitions/MutatingWebhookConfiguration_debug.yaml b/definitions/MutatingWebhookConfiguration_debug.yaml index cc235922c1..713fb9cb40 100644 --- a/definitions/MutatingWebhookConfiguration_debug.yaml +++ b/definitions/MutatingWebhookConfiguration_debug.yaml @@ -1,8 +1,9 @@ # Example of MutatingWebhookConfiguration which can be used for debug, when controller is placed on master node +# To register webhook for debug, replace ${CA_BUNDLE} with corresponding data from ~/.kube/config and create this resource apiVersion: admissionregistration.k8s.io/v1beta1 kind: MutatingWebhookConfiguration metadata: - name: nirmata-kube-policy-webhook-cfg + name: nirmata-kube-policy-webhook-cfg-debug labels: app: kube-policy webhooks: diff --git a/init.go b/init.go index ca32bbd693..609b64af7b 100644 --- a/init.go +++ b/init.go @@ -23,7 +23,27 @@ func createClientConfig(kubeconfig string) (*rest.Config, error) { } } -func readTlsPairFromFiles(certFile, keyFile string) *utils.TlsPemPair { +func initTlsPemPair(certFile, keyFile string, clientConfig *rest.Config, kubeclient *kubeclient.KubeClient) (*utils.TlsPemPair, error) { + var tlsPair *utils.TlsPemPair + if certFile != "" || keyFile != "" { + tlsPair = tlsPairFromFiles(certFile, keyFile) + } + + var err error + if tlsPair != nil { + log.Print("Using given TLS key/certificate pair") + return tlsPair, nil + } else { + tlsPair, err = tlsPairFromCluster(clientConfig, kubeclient) + if err == nil { + log.Printf("Using TLS key/certificate from cluster") + } + return tlsPair, err + } +} + +// Loads PEM private key and TLS certificate from given files +func tlsPairFromFiles(certFile, keyFile string) *utils.TlsPemPair { if certFile == "" || keyFile == "" { return nil } @@ -46,9 +66,10 @@ func readTlsPairFromFiles(certFile, keyFile string) *utils.TlsPemPair { } } -// Loads or creates PEM private key and TLS certificate for webhook server -// Returns struct with key/certificate pair -func initTlsPemsPair(configuration *rest.Config, client *kubeclient.KubeClient) (*utils.TlsPemPair, error) { +// Loads or creates PEM private key and TLS certificate for webhook server. +// Created pair is stored in cluster's secret. +// Returns struct with key/certificate pair. +func tlsPairFromCluster(configuration *rest.Config, client *kubeclient.KubeClient) (*utils.TlsPemPair, error) { apiServerUrl, err := url.Parse(configuration.Host) if err != nil { return nil, err diff --git a/main.go b/main.go index 0e93ed2192..3b518e41cc 100644 --- a/main.go +++ b/main.go @@ -6,8 +6,8 @@ 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" + "github.com/nirmata/kube-policy/webhooks" signals "k8s.io/sample-controller/pkg/signals" ) @@ -24,11 +24,6 @@ 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: %s\n", err) @@ -39,22 +34,17 @@ func main() { log.Fatalf("Error creating kubeclient: %v\n", err) } - tlsPair := readTlsPairFromFiles(cert, key) - if tlsPair != nil { - log.Print("Using given TLS key/certificate pair") - } else { - tlsPair, err = initTlsPemsPair(clientConfig, kubeclient) - if err != nil { - log.Fatalf("Failed to initialize TLS key/certificate pair: %v\n", err) - } + mutationWebhook, err := webhooks.CreateMutationWebhook(clientConfig, kubeclient, controller, nil) + if err != nil { + log.Fatalf("Error creating mutation webhook: %v\n", err) } - serverConfig := server.WebhookServerConfig{ - TlsPemPair: tlsPair, - Controller: controller, - Kubeclient: kubeclient, + tlsPair, err := initTlsPemPair(cert, key, clientConfig, kubeclient) + if err != nil { + log.Fatalf("Failed to initialize TLS key/certificate pair: %v\n", err) } - server, err := server.NewWebhookServer(serverConfig, nil) + + server, err := server.NewWebhookServer(tlsPair, mutationWebhook, nil) if err != nil { log.Fatalf("Unable to create webhook server: %v\n", err) } @@ -66,10 +56,15 @@ func main() { if err != nil { log.Fatalf("Error running PolicyController: %s\n", err) } - log.Println("Policy Controller has started") + <-stopCh server.Stop() + err = mutationWebhook.Deregister() + if err != nil { + log.Printf("Unable to deregister mutation webhook: %v", err) + } + log.Println("Policy Controller has stopped") } diff --git a/server/server.go b/server/server.go index ae02586664..f714f535ac 100644 --- a/server/server.go +++ b/server/server.go @@ -13,8 +13,6 @@ import ( "time" "github.com/nirmata/kube-policy/config" - "github.com/nirmata/kube-policy/controller" - "github.com/nirmata/kube-policy/kubeclient" "github.com/nirmata/kube-policy/utils" "github.com/nirmata/kube-policy/webhooks" @@ -24,46 +22,32 @@ 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 - policyController *controller.PolicyController - mutationWebhook *webhooks.MutationWebhook - logger *log.Logger -} - -// Configuration struct for WebhookServer used in NewWebhookServer -// Controller and Kubeclient should be initialized and valid -type WebhookServerConfig struct { - TlsPemPair *utils.TlsPemPair - Controller *controller.PolicyController - Kubeclient *kubeclient.KubeClient + server http.Server + mutationWebhook *webhooks.MutationWebhook + logger *log.Logger } // NewWebhookServer creates new instance of WebhookServer accordingly to given configuration // Policy Controller and Kubernetes Client should be initialized in configuration -func NewWebhookServer(configuration WebhookServerConfig, logger *log.Logger) (*WebhookServer, error) { +func NewWebhookServer(tlsPair *utils.TlsPemPair, mutationWebhook *webhooks.MutationWebhook, logger *log.Logger) (*WebhookServer, error) { if logger == nil { logger = log.New(os.Stdout, "HTTPS Server: ", log.LstdFlags|log.Lshortfile) } - if configuration.TlsPemPair == nil || configuration.Controller == nil || configuration.Kubeclient == nil { - return nil, errors.New("WebhookServerConfig is not initialized properly") + if tlsPair == nil || mutationWebhook == nil { + return nil, errors.New("NewWebhookServer is not initialized properly") } var tlsConfig tls.Config - pair, err := tls.X509KeyPair(configuration.TlsPemPair.Certificate, configuration.TlsPemPair.PrivateKey) + pair, err := tls.X509KeyPair(tlsPair.Certificate, tlsPair.PrivateKey) if err != nil { return nil, err } tlsConfig.Certificates = []tls.Certificate{pair} - mw, err := webhooks.NewMutationWebhook(configuration.Kubeclient, configuration.Controller, logger) - if err != nil { - return nil, err - } - ws := &WebhookServer{ logger: logger, - mutationWebhook: mw, + mutationWebhook: mutationWebhook, } mux := http.NewServeMux()