From c33cf97ed3a937300fde742a7b672a9b383143c0 Mon Sep 17 00:00:00 2001 From: Markus Opolka Date: Wed, 18 Oct 2023 14:05:25 +0200 Subject: [PATCH 1/4] Add option to load CLI flags via environment variables --- README.md | 8 ++++--- cmd/config.go | 52 +++++++++++++++++++++++++++++++++++++++------- cmd/config_test.go | 26 +++++++++++++++++++++++ cmd/root.go | 8 ++++--- 4 files changed, 80 insertions(+), 14 deletions(-) create mode 100644 cmd/config_test.go diff --git a/README.md b/README.md index dd88d14..2b59de9 100644 --- a/README.md +++ b/README.md @@ -15,10 +15,10 @@ Available Commands: query Checks the total hits/results of an Elasticsearch query Flags: - -H, --hostname string Hostname of the Elasticsearch instance (default "localhost") + -H, --hostname string Hostname of the Elasticsearch instance (CHECK_ELASTICSEARCH_HOSTNAME) (default "localhost") -p, --port int Port of the Elasticsearch instance (default 9200) - -U, --username string Username if authentication is required - -P, --password string Password if authentication is required + -U, --username string Username for HTTP Basic Authentication (CHECK_ELASTICSEARCH_USERNAME) + -P, --password string Password for HTTP Basic Authentication (CHECK_ELASTICSEARCH_PASSWORD) -S, --tls Use a HTTPS connection --insecure Skip the verification of the server's TLS certificate -t, --timeout int Timeout in seconds for the CheckPlugin (default 30) @@ -28,6 +28,8 @@ Flags: The check plugin respects the environment variables `HTTP_PROXY`, `HTTPS_PROXY` and `NO_PROXY`. +Various flags can be set with environment variables, refer to the help to see which flags. + ### Health Checks the health status of an Elasticsearch cluster. diff --git a/cmd/config.go b/cmd/config.go index fe1afa6..538c44a 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -5,6 +5,8 @@ import ( "net" "net/http" "net/url" + "os" + "reflect" "strconv" "time" @@ -14,19 +16,53 @@ import ( ) type Config struct { - Hostname string - BasicAuth string - Bearer string - CAFile string - CertFile string - KeyFile string - Username string - Password string + BasicAuth string // Currently unused in CLI + Bearer string // Currently unused in CLI + Hostname string `env:"CHECK_ELASTICSEARCH_HOSTNAME"` + CAFile string `env:"CHECK_ELASTICSEARCH_CA_FILE"` + CertFile string `env:"CHECK_ELASTICSEARCH_CERT_FILE"` + KeyFile string `env:"CHECK_ELASTICSEARCH_CERT_FILE"` + Username string `env:"CHECK_ELASTICSEARCH_USERNAME"` + Password string `env:"CHECK_ELASTICSEARCH_PASSWORD"` Port int TLS bool Insecure bool } +// LoadFromEnv can be used to load struct values from 'env' tags. +// Mainly used to avoid passing secrets via the CLI +// +// type Config struct { +// Token string `env:"BEARER_TOKEN"` +// } +func loadFromEnv(config interface{}) { + configValue := reflect.ValueOf(config).Elem() + configType := configValue.Type() + + for i := 0; i < configValue.NumField(); i++ { + field := configType.Field(i) + tag := field.Tag.Get("env") + + // If there's no "env" tag, skip this field. + if tag == "" { + continue + } + + envValue := os.Getenv(tag) + + if envValue == "" { + continue + } + + // Potential for addding different types + // nolint: exhaustive, gocritic + switch field.Type.Kind() { + case reflect.String: + configValue.Field(i).SetString(envValue) + } + } +} + var cliConfig Config func (c *Config) NewClient() *client.Client { diff --git a/cmd/config_test.go b/cmd/config_test.go new file mode 100644 index 0000000..2b5ea0c --- /dev/null +++ b/cmd/config_test.go @@ -0,0 +1,26 @@ +package cmd + +import ( + "os" + "testing" +) + +func TestLoadFromEnv(t *testing.T) { + c := Config{} + + err := os.Setenv("CHECK_ELASTICSEARCH_USERNAME", "foobar") + defer os.Unsetenv("CHECK_ELASTICSEARCH_USERNAME") // to not impact other tests + + if err != nil { + t.Error("Did not expect error, got: %w", err) + } + + loadFromEnv(&c) + + if "foobar" != c.Username { + t.Error("\nActual: ", c.Username, "\nExpected: ", "foobar") + } + if "" != c.Password { + t.Error("\nActual: ", c.Password, "\nExpected: ", "empty-string") + } +} diff --git a/cmd/root.go b/cmd/root.go index bd11625..ef577fc 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -42,13 +42,13 @@ func init() { pfs := rootCmd.PersistentFlags() pfs.StringVarP(&cliConfig.Hostname, "hostname", "H", "localhost", - "Hostname of the Elasticsearch instance") + "Hostname of the Elasticsearch instance (CHECK_ELASTICSEARCH_HOSTNAME)") pfs.IntVarP(&cliConfig.Port, "port", "p", 9200, "Port of the Elasticsearch instance") pfs.StringVarP(&cliConfig.Username, "username", "U", "", - "Username for HTTP Basic Authentication") + "Username for HTTP Basic Authentication (CHECK_ELASTICSEARCH_USERNAME)") pfs.StringVarP(&cliConfig.Password, "password", "P", "", - "Password for HTTP Basic Authentication") + "Password for HTTP Basic Authentication (CHECK_ELASTICSEARCH_PASSWORD)") pfs.BoolVarP(&cliConfig.TLS, "tls", "S", false, "Use a HTTPS connection") pfs.BoolVar(&cliConfig.Insecure, "insecure", false, @@ -58,6 +58,8 @@ func init() { rootCmd.Flags().SortFlags = false pfs.SortFlags = false + + loadFromEnv(&cliConfig) } func Help(cmd *cobra.Command, _ []string) { From 5a495b1e7a3727dde8222bd05d486752288be2b2 Mon Sep 17 00:00:00 2001 From: Markus Opolka Date: Wed, 18 Oct 2023 14:08:28 +0200 Subject: [PATCH 2/4] Add flags to adjust TLS configuration --- README.md | 3 +++ cmd/config.go | 2 +- cmd/root.go | 6 ++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2b59de9..d117eb5 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,9 @@ Flags: -P, --password string Password for HTTP Basic Authentication (CHECK_ELASTICSEARCH_PASSWORD) -S, --tls Use a HTTPS connection --insecure Skip the verification of the server's TLS certificate + --ca-file string Specify the CA File for TLS authentication (CHECK_ELASTICSEARCH_CA_FILE) + --cert-file string Specify the Certificate File for TLS authentication (CHECK_ELASTICSEARCH_CERT_FILE) + --key-file string Specify the Key File for TLS authentication (CHECK_ELASTICSEARCH_KEY_FILE) -t, --timeout int Timeout in seconds for the CheckPlugin (default 30) -h, --help help for check_elasticsearch -v, --version version for check_elasticsearch diff --git a/cmd/config.go b/cmd/config.go index 538c44a..f1ab48e 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -21,7 +21,7 @@ type Config struct { Hostname string `env:"CHECK_ELASTICSEARCH_HOSTNAME"` CAFile string `env:"CHECK_ELASTICSEARCH_CA_FILE"` CertFile string `env:"CHECK_ELASTICSEARCH_CERT_FILE"` - KeyFile string `env:"CHECK_ELASTICSEARCH_CERT_FILE"` + KeyFile string `env:"CHECK_ELASTICSEARCH_KEY_FILE"` Username string `env:"CHECK_ELASTICSEARCH_USERNAME"` Password string `env:"CHECK_ELASTICSEARCH_PASSWORD"` Port int diff --git a/cmd/root.go b/cmd/root.go index ef577fc..b395c3c 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -53,6 +53,12 @@ func init() { "Use a HTTPS connection") pfs.BoolVar(&cliConfig.Insecure, "insecure", false, "Skip the verification of the server's TLS certificate") + pfs.StringVarP(&cliConfig.CAFile, "ca-file", "", "", + "Specify the CA File for TLS authentication (CHECK_ELASTICSEARCH_CA_FILE)") + pfs.StringVarP(&cliConfig.CertFile, "cert-file", "", "", + "Specify the Certificate File for TLS authentication (CHECK_ELASTICSEARCH_CERT_FILE)") + pfs.StringVarP(&cliConfig.KeyFile, "key-file", "", "", + "Specify the Key File for TLS authentication (CHECK_ELASTICSEARCH_KEY_FILE)") pfs.IntVarP(&timeout, "timeout", "t", timeout, "Timeout in seconds for the CheckPlugin") From 44b343fab68c96aab629dfcfe1c93b1c29bbea14 Mon Sep 17 00:00:00 2001 From: Markus Opolka Date: Wed, 18 Oct 2023 14:08:52 +0200 Subject: [PATCH 3/4] Bump Go version and pin golang-ci-lint in GH Actions --- .github/workflows/build.yml | 2 +- .github/workflows/golangci-lint.yml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3d37564..370c660 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,7 +19,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: 1.19 + go-version: 1.21 - name: Test run: go test -v ./... diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 8d7fce1..b8ea0ae 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -16,3 +16,5 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@v3 + with: + version: v1.54 From 0b2ec88cdf7e99d31031fc2782fb34df4f9bab00 Mon Sep 17 00:00:00 2001 From: Markus Opolka Date: Wed, 18 Oct 2023 14:11:18 +0200 Subject: [PATCH 4/4] Remove unused attribute in Config struct --- cmd/config.go | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/cmd/config.go b/cmd/config.go index f1ab48e..d5c772a 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -16,17 +16,16 @@ import ( ) type Config struct { - BasicAuth string // Currently unused in CLI - Bearer string // Currently unused in CLI - Hostname string `env:"CHECK_ELASTICSEARCH_HOSTNAME"` - CAFile string `env:"CHECK_ELASTICSEARCH_CA_FILE"` - CertFile string `env:"CHECK_ELASTICSEARCH_CERT_FILE"` - KeyFile string `env:"CHECK_ELASTICSEARCH_KEY_FILE"` - Username string `env:"CHECK_ELASTICSEARCH_USERNAME"` - Password string `env:"CHECK_ELASTICSEARCH_PASSWORD"` - Port int - TLS bool - Insecure bool + Bearer string // Currently unused in CLI + Hostname string `env:"CHECK_ELASTICSEARCH_HOSTNAME"` + CAFile string `env:"CHECK_ELASTICSEARCH_CA_FILE"` + CertFile string `env:"CHECK_ELASTICSEARCH_CERT_FILE"` + KeyFile string `env:"CHECK_ELASTICSEARCH_KEY_FILE"` + Username string `env:"CHECK_ELASTICSEARCH_USERNAME"` + Password string `env:"CHECK_ELASTICSEARCH_PASSWORD"` + Port int + TLS bool + Insecure bool } // LoadFromEnv can be used to load struct values from 'env' tags.