From 809481691102192c62e22196af4e8f47a7281074 Mon Sep 17 00:00:00 2001 From: nhyatt Date: Fri, 24 Mar 2023 09:38:00 -0500 Subject: [PATCH] Enable ability to flip configuration of allownomutate --- cmd/webhook/httpServer.go | 20 ++++++-------------- cmd/webhook/httpServerTemplates.go | 4 +--- cmd/webhook/main.go | 7 +++++-- internal/config/config.go | 8 ++++---- internal/config/initialize.go | 14 +++++++------- internal/operations/deploymentsValidation.go | 12 ++++++------ internal/operations/hook.go | 16 ++++++++-------- internal/operations/podsMutation.go | 12 ++++++------ internal/operations/podsValidation.go | 14 +++++++------- 9 files changed, 50 insertions(+), 57 deletions(-) diff --git a/cmd/webhook/httpServer.go b/cmd/webhook/httpServer.go index 30cd702..05bd7a1 100644 --- a/cmd/webhook/httpServer.go +++ b/cmd/webhook/httpServer.go @@ -37,7 +37,7 @@ func strictTransport(w http.ResponseWriter) { w.Header().Add("Strict-Transport-Security", "max-age=63072000") } -func httpServer(cfg *config.Config) { +func httpServer() { var serverCertificate tls.Certificate if config.DefaultConfig().WebServerCertificate == "" || cfg.WebServerKey == "" { log.Printf("[INFO] No webserver certificate configured, automatically generating self signed certificate.") @@ -73,11 +73,7 @@ func httpServer(cfg *config.Config) { ah := &admissionHandler{ decoder: serializer.NewCodecFactory(runtime.NewScheme()).UniversalDeserializer(), - config: cfg, - } - - wh := &webHandler{ - config: cfg, + config: &cfg, } // pod admission @@ -87,18 +83,14 @@ func httpServer(cfg *config.Config) { // pod mutation path.HandleFunc("/api/v1/mutate/pod", ah.ahServe(operations.PodsMutation())) // web root - path.HandleFunc("/", wh.webServe()) + path.HandleFunc("/", webServe()) if err := connection.ListenAndServeTLS("", ""); err != nil { log.Fatalf("[ERROR] %s\n", err) } } -type webHandler struct { - config *config.Config -} - -func (h *webHandler) webServe() http.HandlerFunc { +func webServe() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { httpAccessLog(r) crossSiteOrigin(w) @@ -112,7 +104,7 @@ func (h *webHandler) webServe() http.HandlerFunc { case r.URL.Path == "/healthcheck": tmpltHealthCheck(w) case r.URL.Path == "/": - tmpltWebRoot(w, r.URL.Query(), *h.config) + tmpltWebRoot(w, r.URL.Query()) default: msg := fmt.Sprintf("Unable to locate requested path: '%s'", r.URL.Path) log.Printf("[DEBUG] %s", msg) @@ -170,7 +162,7 @@ func (h *admissionHandler) ahServe(hook operations.Hook) http.HandlerFunc { return } - result, err := hook.Execute(review.Request, h.config) + result, err := hook.Execute(review.Request, &cfg) if err != nil { msg := err.Error() log.Printf("[ERROR] Internal Server Error: %s", msg) diff --git a/cmd/webhook/httpServerTemplates.go b/cmd/webhook/httpServerTemplates.go index d4851a4..66a969e 100644 --- a/cmd/webhook/httpServerTemplates.go +++ b/cmd/webhook/httpServerTemplates.go @@ -7,8 +7,6 @@ import ( "encoding/json" "net/http" "net/url" - - "mutating-webhook/internal/config" ) const cT string = "Content-Type" @@ -56,7 +54,7 @@ func tmpltHealthCheck(w http.ResponseWriter) { w.Write(output) //nolint:errcheck } -func tmpltWebRoot(w http.ResponseWriter, urlPrams url.Values, cfg config.Config) { +func tmpltWebRoot(w http.ResponseWriter, urlPrams url.Values) { o := struct { Application string `json:"application" yaml:"application"` Description string `json:"description" yaml:"description"` diff --git a/cmd/webhook/main.go b/cmd/webhook/main.go index a4a188d..207e054 100644 --- a/cmd/webhook/main.go +++ b/cmd/webhook/main.go @@ -10,6 +10,9 @@ import ( "mutating-webhook/internal/config" ) +// global configuration +var cfg config.Config + func forever() { c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) @@ -24,9 +27,9 @@ func main() { }() // initialize application configuration - cfg := config.Init() + cfg = config.Init() - go httpServer(cfg) + go httpServer() forever() } diff --git a/internal/config/config.go b/internal/config/config.go index 407f143..1aef179 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -41,8 +41,8 @@ type Config struct { } // DefaultConfig initializes the config variable for use with a prepared set of defaults. -func DefaultConfig() *Config { - return &Config{ +func DefaultConfig() Config { + return Config{ Log: &logutils.LevelFilter{ Levels: []logutils.LogLevel{"TRACE", "DEBUG", "INFO", "WARNING", "ERROR"}, Writer: os.Stderr, @@ -50,7 +50,7 @@ func DefaultConfig() *Config { } } -func (cfg *Config) setLogLevel() { +func setLogLevel(cfg Config) { switch { case cfg.LogLevel <= 20: cfg.Log.SetMinLevel(logutils.LogLevel("ERROR")) @@ -66,7 +66,7 @@ func (cfg *Config) setLogLevel() { log.SetOutput(cfg.Log) } -func (cfg *Config) printRunningConfig(cfgInfo []StructInfo) { +func printRunningConfig(cfg *Config, cfgInfo []StructInfo) { log.Printf("[DEBUG] Current Running Configuration Values:") for _, info := range cfgInfo { switch info.Type.String() { diff --git a/internal/config/initialize.go b/internal/config/initialize.go index 253013e..b0e594e 100644 --- a/internal/config/initialize.go +++ b/internal/config/initialize.go @@ -19,10 +19,10 @@ func getOSEnv(env, def string) string { // Init initializes the application configuration by reading default values from the struct's tags // and environment variables. Tags processed by this process are as follows: // `ignored:"true" env:"ENVIRONMENT_VARIABLE" default:"default value"` -func Init() *Config { +func Init() Config { cfg := DefaultConfig() - cfgInfo, err := getStructInfo(cfg) + cfgInfo, err := getStructInfo(&cfg) if err != nil { log.Fatalf("[FATAL] %v", err) } @@ -34,7 +34,7 @@ func Init() *Config { if info.DefaultValue != nil { dv = info.DefaultValue.(string) } - p := reflect.ValueOf(cfg).Elem().FieldByName(info.Name).Addr().Interface().(*string) + p := reflect.ValueOf(&cfg).Elem().FieldByName(info.Name).Addr().Interface().(*string) flag.StringVar(p, info.Name, dv, "("+info.Key+")") case "bool": @@ -42,7 +42,7 @@ func Init() *Config { if info.DefaultValue != nil { dv = info.DefaultValue.(bool) } - p := reflect.ValueOf(cfg).Elem().FieldByName(info.Name).Addr().Interface().(*bool) + p := reflect.ValueOf(&cfg).Elem().FieldByName(info.Name).Addr().Interface().(*bool) flag.BoolVar(p, info.Name, dv, "("+info.Key+")") case "int": @@ -50,14 +50,14 @@ func Init() *Config { if info.DefaultValue != nil { dv = int(info.DefaultValue.(int64)) } - p := reflect.ValueOf(cfg).Elem().FieldByName(info.Name).Addr().Interface().(*int) + p := reflect.ValueOf(&cfg).Elem().FieldByName(info.Name).Addr().Interface().(*int) flag.IntVar(p, info.Name, dv, "("+info.Key+")") } } flag.Parse() // set logging level - cfg.setLogLevel() + setLogLevel(cfg) // timezone & format configuration cfg.TZoneUTC, _ = time.LoadLocation("UTC") @@ -71,7 +71,7 @@ func Init() *Config { time.Now().Format(cfg.TimeFormat) // print running config - cfg.printRunningConfig(cfgInfo) + printRunningConfig(&cfg, cfgInfo) // read config file configFileData, err := getConfigFileData(cfg.ConfigFile) diff --git a/internal/operations/deploymentsValidation.go b/internal/operations/deploymentsValidation.go index 240685e..d02598a 100644 --- a/internal/operations/deploymentsValidation.go +++ b/internal/operations/deploymentsValidation.go @@ -1,24 +1,24 @@ package operations import ( - "mutating-webhook/internal/config" - admission "k8s.io/api/admission/v1" + + "mutating-webhook/internal/config" ) func DeploymentsValidation() Hook { return Hook{ // default allow - Create: func(r *admission.AdmissionRequest, cfg config.Config) (*Result, error) { + Create: func(r *admission.AdmissionRequest, cfg *config.Config) (*Result, error) { return &Result{Allowed: true}, nil }, - Delete: func(r *admission.AdmissionRequest, cfg config.Config) (*Result, error) { + Delete: func(r *admission.AdmissionRequest, cfg *config.Config) (*Result, error) { return &Result{Allowed: true}, nil }, - Update: func(r *admission.AdmissionRequest, cfg config.Config) (*Result, error) { + Update: func(r *admission.AdmissionRequest, cfg *config.Config) (*Result, error) { return &Result{Allowed: true}, nil }, - Connect: func(r *admission.AdmissionRequest, cfg config.Config) (*Result, error) { + Connect: func(r *admission.AdmissionRequest, cfg *config.Config) (*Result, error) { return &Result{Allowed: true}, nil }, } diff --git a/internal/operations/hook.go b/internal/operations/hook.go index f46b565..d2235b6 100644 --- a/internal/operations/hook.go +++ b/internal/operations/hook.go @@ -5,9 +5,9 @@ package operations import ( "fmt" - "mutating-webhook/internal/config" - admission "k8s.io/api/admission/v1" + + "mutating-webhook/internal/config" ) // Result contains the result of an admission request @@ -18,7 +18,7 @@ type Result struct { } // AdmitFunc defines how to process an admission request -type AdmitFunc func(request *admission.AdmissionRequest, cfg config.Config) (*Result, error) +type AdmitFunc func(request *admission.AdmissionRequest, cfg *config.Config) (*Result, error) // Hook represents the set of functions for each operation in an admission webhook. type Hook struct { @@ -32,19 +32,19 @@ type Hook struct { func (h *Hook) Execute(r *admission.AdmissionRequest, cfg *config.Config) (*Result, error) { switch r.Operation { case admission.Create: - return wrapperExecution(h.Create, r, *cfg) + return wrapperExecution(h.Create, r, cfg) case admission.Update: - return wrapperExecution(h.Update, r, *cfg) + return wrapperExecution(h.Update, r, cfg) case admission.Delete: - return wrapperExecution(h.Delete, r, *cfg) + return wrapperExecution(h.Delete, r, cfg) case admission.Connect: - return wrapperExecution(h.Connect, r, *cfg) + return wrapperExecution(h.Connect, r, cfg) } return &Result{Msg: fmt.Sprintf("Invalid operation: %s", r.Operation)}, nil } -func wrapperExecution(fn AdmitFunc, r *admission.AdmissionRequest, cfg config.Config) (*Result, error) { +func wrapperExecution(fn AdmitFunc, r *admission.AdmissionRequest, cfg *config.Config) (*Result, error) { if fn == nil { return nil, fmt.Errorf("operation %s is not registered", r.Operation) } diff --git a/internal/operations/podsMutation.go b/internal/operations/podsMutation.go index c649b53..238a7c0 100644 --- a/internal/operations/podsMutation.go +++ b/internal/operations/podsMutation.go @@ -3,30 +3,30 @@ package operations import ( "fmt" - "mutating-webhook/internal/config" - admission "k8s.io/api/admission/v1" core "k8s.io/api/core/v1" + + "mutating-webhook/internal/config" ) func PodsMutation() Hook { return Hook{ Create: podMutationCreate(), // default allow - Delete: func(r *admission.AdmissionRequest, cfg config.Config) (*Result, error) { + Delete: func(r *admission.AdmissionRequest, cfg *config.Config) (*Result, error) { return &Result{Allowed: true}, nil }, - Update: func(r *admission.AdmissionRequest, cfg config.Config) (*Result, error) { + Update: func(r *admission.AdmissionRequest, cfg *config.Config) (*Result, error) { return &Result{Allowed: true}, nil }, - Connect: func(r *admission.AdmissionRequest, cfg config.Config) (*Result, error) { + Connect: func(r *admission.AdmissionRequest, cfg *config.Config) (*Result, error) { return &Result{Allowed: true}, nil }, } } func podMutationCreate() AdmitFunc { - return func(r *admission.AdmissionRequest, cfg config.Config) (*Result, error) { + return func(r *admission.AdmissionRequest, cfg *config.Config) (*Result, error) { var operations []PatchOperation pod, err := parsePod(r.Object.Raw) if err != nil { diff --git a/internal/operations/podsValidation.go b/internal/operations/podsValidation.go index 1b132c3..250ef44 100644 --- a/internal/operations/podsValidation.go +++ b/internal/operations/podsValidation.go @@ -4,31 +4,31 @@ import ( "log" "strings" - "mutating-webhook/internal/config" - admission "k8s.io/api/admission/v1" + + "mutating-webhook/internal/config" ) func PodsValidation() Hook { return Hook{ // default allow - Create: func(r *admission.AdmissionRequest, cfg config.Config) (*Result, error) { + Create: func(r *admission.AdmissionRequest, cfg *config.Config) (*Result, error) { return &Result{Allowed: true}, nil }, - Delete: func(r *admission.AdmissionRequest, cfg config.Config) (*Result, error) { + Delete: func(r *admission.AdmissionRequest, cfg *config.Config) (*Result, error) { return &Result{Allowed: true}, nil }, - Update: func(r *admission.AdmissionRequest, cfg config.Config) (*Result, error) { + Update: func(r *admission.AdmissionRequest, cfg *config.Config) (*Result, error) { return &Result{Allowed: true}, nil }, - Connect: func(r *admission.AdmissionRequest, cfg config.Config) (*Result, error) { + Connect: func(r *admission.AdmissionRequest, cfg *config.Config) (*Result, error) { return &Result{Allowed: true}, nil }, } } func podValidationCreate() AdmitFunc { - return func(r *admission.AdmissionRequest, cfg config.Config) (*Result, error) { + return func(r *admission.AdmissionRequest, cfg *config.Config) (*Result, error) { pod, err := parsePod(r.Object.Raw) if err != nil { return &Result{Msg: err.Error()}, nil