From b741f3288a66791d6529326228dee0cf25b3fda0 Mon Sep 17 00:00:00 2001 From: Joshua Powers Date: Tue, 2 Aug 2022 15:29:33 -0600 Subject: [PATCH] fix(inputs.kube_inventory): send file location to enable token auto-refresh (#11577) --- plugins/inputs/kube_inventory/README.md | 7 ++++++- plugins/inputs/kube_inventory/client.go | 15 +++++++++++---- plugins/inputs/kube_inventory/client_test.go | 5 ++++- plugins/inputs/kube_inventory/kube_inventory.go | 14 ++++---------- plugins/inputs/kube_inventory/sample.conf | 7 ++++++- 5 files changed, 31 insertions(+), 17 deletions(-) diff --git a/plugins/inputs/kube_inventory/README.md b/plugins/inputs/kube_inventory/README.md index 711ba4d60..d8cdc1193 100644 --- a/plugins/inputs/kube_inventory/README.md +++ b/plugins/inputs/kube_inventory/README.md @@ -44,10 +44,15 @@ avoid cardinality issues: # namespace = "default" ## Use bearer token for authorization. ('bearer_token' takes priority) + ## ## If both of these are empty, we'll use the default serviceaccount: ## at: /run/secrets/kubernetes.io/serviceaccount/token - # bearer_token = "/path/to/bearer/token" + ## + ## To auto-refresh the token, please use a file with the bearer_token option. + ## If given a string, Telegraf cannot refresh the token periodically. + # bearer_token = "/run/secrets/kubernetes.io/serviceaccount/token" ## OR + ## deprecated in 1.24.0; use bearer_token with a file # bearer_token_string = "abc_123" ## Set response_timeout (default 5 seconds) diff --git a/plugins/inputs/kube_inventory/client.go b/plugins/inputs/kube_inventory/client.go index da03c6432..2fa51da42 100644 --- a/plugins/inputs/kube_inventory/client.go +++ b/plugins/inputs/kube_inventory/client.go @@ -20,8 +20,8 @@ type client struct { *kubernetes.Clientset } -func newClient(baseURL, namespace, bearerToken string, timeout time.Duration, tlsConfig tls.ClientConfig) (*client, error) { - c, err := kubernetes.NewForConfig(&rest.Config{ +func newClient(baseURL, namespace, bearerTokenFile string, bearerToken string, timeout time.Duration, tlsConfig tls.ClientConfig) (*client, error) { + config := &rest.Config{ TLSClientConfig: rest.TLSClientConfig{ ServerName: tlsConfig.ServerName, Insecure: tlsConfig.InsecureSkipVerify, @@ -30,9 +30,16 @@ func newClient(baseURL, namespace, bearerToken string, timeout time.Duration, tl KeyFile: tlsConfig.TLSKey, }, Host: baseURL, - BearerToken: bearerToken, ContentConfig: rest.ContentConfig{}, - }) + } + + if bearerTokenFile != "" { + config.BearerTokenFile = bearerTokenFile + } else if bearerToken != "" { + config.BearerToken = bearerToken + } + + c, err := kubernetes.NewForConfig(config) if err != nil { return nil, err } diff --git a/plugins/inputs/kube_inventory/client_test.go b/plugins/inputs/kube_inventory/client_test.go index 0462c0222..d70f36038 100644 --- a/plugins/inputs/kube_inventory/client_test.go +++ b/plugins/inputs/kube_inventory/client_test.go @@ -25,6 +25,9 @@ func toBoolPtr(b bool) *bool { } func TestNewClient(t *testing.T) { - _, err := newClient("https://127.0.0.1:443/", "default", "abc123", time.Second, tls.ClientConfig{}) + _, err := newClient("https://127.0.0.1:443/", "default", "", "abc123", time.Second, tls.ClientConfig{}) require.NoErrorf(t, err, "Failed to create new client - %v", err) + + _, err = newClient("https://127.0.0.1:443/", "default", "nonexistantFile", "", time.Second, tls.ClientConfig{}) + require.Errorf(t, err, "failed to read token file \"file\": open file: no such file or directory", err) } diff --git a/plugins/inputs/kube_inventory/kube_inventory.go b/plugins/inputs/kube_inventory/kube_inventory.go index de8321607..963c7deee 100644 --- a/plugins/inputs/kube_inventory/kube_inventory.go +++ b/plugins/inputs/kube_inventory/kube_inventory.go @@ -5,9 +5,7 @@ import ( "context" _ "embed" "fmt" - "os" "strconv" - "strings" "sync" "time" @@ -32,7 +30,7 @@ const ( type KubernetesInventory struct { URL string `toml:"url"` BearerToken string `toml:"bearer_token"` - BearerTokenString string `toml:"bearer_token_string"` + BearerTokenString string `toml:"bearer_token_string" deprecated:"1.24.0;use 'BearerToken' with a file instead"` Namespace string `toml:"namespace"` ResponseTimeout config.Duration `toml:"response_timeout"` // Timeout specified as a string - 3s, 1m, 1h ResourceExclude []string `toml:"resource_exclude"` @@ -60,16 +58,12 @@ func (ki *KubernetesInventory) Init() error { ki.BearerToken = defaultServiceAccountPath } - if ki.BearerToken != "" { - token, err := os.ReadFile(ki.BearerToken) - if err != nil { - return err - } - ki.BearerTokenString = strings.TrimSpace(string(token)) + if ki.BearerTokenString != "" { + ki.Log.Warn("Telegraf cannot auto-refresh a bearer token string, use BearerToken file instead") } var err error - ki.client, err = newClient(ki.URL, ki.Namespace, ki.BearerTokenString, time.Duration(ki.ResponseTimeout), ki.ClientConfig) + ki.client, err = newClient(ki.URL, ki.Namespace, ki.BearerToken, ki.BearerTokenString, time.Duration(ki.ResponseTimeout), ki.ClientConfig) if err != nil { return err diff --git a/plugins/inputs/kube_inventory/sample.conf b/plugins/inputs/kube_inventory/sample.conf index d9c508a08..c1963209d 100644 --- a/plugins/inputs/kube_inventory/sample.conf +++ b/plugins/inputs/kube_inventory/sample.conf @@ -7,10 +7,15 @@ # namespace = "default" ## Use bearer token for authorization. ('bearer_token' takes priority) + ## ## If both of these are empty, we'll use the default serviceaccount: ## at: /run/secrets/kubernetes.io/serviceaccount/token - # bearer_token = "/path/to/bearer/token" + ## + ## To auto-refresh the token, please use a file with the bearer_token option. + ## If given a string, Telegraf cannot refresh the token periodically. + # bearer_token = "/run/secrets/kubernetes.io/serviceaccount/token" ## OR + ## deprecated in 1.24.0; use bearer_token with a file # bearer_token_string = "abc_123" ## Set response_timeout (default 5 seconds)