From 5d837a29dd012cef48a28cfbed2f829d349634de Mon Sep 17 00:00:00 2001 From: Matthias Loibl Date: Fri, 23 Nov 2018 17:25:22 +0100 Subject: [PATCH 1/4] Add --prometheus-ca-file flag for specific ca --- cmd/adapter/adapter.go | 57 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/cmd/adapter/adapter.go b/cmd/adapter/adapter.go index 19731222e..39b6f9a34 100644 --- a/cmd/adapter/adapter.go +++ b/cmd/adapter/adapter.go @@ -17,8 +17,12 @@ limitations under the License. package main import ( + "crypto/tls" + "crypto/x509" "flag" "fmt" + "io/ioutil" + "log" "net/http" "net/url" "os" @@ -49,6 +53,8 @@ type PrometheusAdapter struct { PrometheusAuthInCluster bool // PrometheusAuthConf is the kubeconfig file that contains auth details used to connect to Prometheus PrometheusAuthConf string + // PrometheusCAFile points to the file containing the ca-root for connecting with Prometheus + PrometheusCAFile string // AdapterConfigFile points to the file containing the metrics discovery configuration. AdapterConfigFile string // MetricsRelistInterval is the interval at which to relist the set of available metrics @@ -62,11 +68,26 @@ func (cmd *PrometheusAdapter) makePromClient() (prom.Client, error) { if err != nil { return nil, fmt.Errorf("invalid Prometheus URL %q: %v", baseURL, err) } - promHTTPClient, err := makeHTTPClient(cmd.PrometheusAuthInCluster, cmd.PrometheusAuthConf) - if err != nil { - return nil, err + + var httpClient *http.Client + + if cmd.PrometheusCAFile != "" { + prometheusCAClient, err := makePrometheusCAClient(cmd.PrometheusCAFile) + if err != nil { + return nil, err + } + httpClient = prometheusCAClient + fmt.Println("successfully loaded ca file") + } else { + kubeconfigHTTPClient, err := makeKubeconfigHTTPClient(cmd.PrometheusAuthInCluster, cmd.PrometheusAuthConf) + if err != nil { + return nil, err + } + httpClient = kubeconfigHTTPClient + fmt.Println("successfully using in cluster") } - genericPromClient := prom.NewGenericAPIClient(promHTTPClient, baseURL) + + genericPromClient := prom.NewGenericAPIClient(httpClient, baseURL) instrumentedGenericPromClient := mprom.InstrumentGenericAPIClient(genericPromClient, baseURL.String()) return prom.NewClientForAPI(instrumentedGenericPromClient), nil } @@ -78,6 +99,8 @@ func (cmd *PrometheusAdapter) addFlags() { "use auth details from the in-cluster kubeconfig when connecting to prometheus.") cmd.Flags().StringVar(&cmd.PrometheusAuthConf, "prometheus-auth-config", cmd.PrometheusAuthConf, "kubeconfig file used to configure auth when connecting to Prometheus.") + cmd.Flags().StringVar(&cmd.PrometheusCAFile, "prometheus-ca-file", cmd.PrometheusCAFile, + "Optional CA file to use when connecting with Prometheus") cmd.Flags().StringVar(&cmd.AdapterConfigFile, "config", cmd.AdapterConfigFile, "Configuration file containing details of how to transform between Prometheus metrics "+ "and custom metrics API resources") @@ -212,8 +235,8 @@ func main() { } } -// makeHTTPClient constructs an HTTP for connecting with the given auth options. -func makeHTTPClient(inClusterAuth bool, kubeConfigPath string) (*http.Client, error) { +// makeKubeconfigHTTPClient constructs an HTTP for connecting with the given auth options. +func makeKubeconfigHTTPClient(inClusterAuth bool, kubeConfigPath string) (*http.Client, error) { // make sure we're not trying to use two different sources of auth if inClusterAuth && kubeConfigPath != "" { return nil, fmt.Errorf("may not use both in-cluster auth and an explicit kubeconfig at the same time") @@ -246,3 +269,25 @@ func makeHTTPClient(inClusterAuth bool, kubeConfigPath string) (*http.Client, er } return &http.Client{Transport: tr}, nil } + +func makePrometheusCAClient(caFilename string) (*http.Client, error) { + pool, err := x509.SystemCertPool() + if err != nil { + return nil, fmt.Errorf("failed to read system certificates: %v", err) + } + data, err := ioutil.ReadFile(caFilename) + if err != nil { + return nil, fmt.Errorf("failed to read prometheus-ca-file: %v", err) + } + if !pool.AppendCertsFromPEM(data) { + log.Printf("warning: no certs found in prometheus-ca-file") + } + + return &http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{ + RootCAs: pool, + }, + }, + }, nil +} From bef034e699d9340833c72aecf1327799a2c8cffd Mon Sep 17 00:00:00 2001 From: Matthias Loibl Date: Mon, 3 Dec 2018 17:18:53 +0100 Subject: [PATCH 2/4] Improve error handling in adapter.go --- cmd/adapter/adapter.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cmd/adapter/adapter.go b/cmd/adapter/adapter.go index 39b6f9a34..2e1974986 100644 --- a/cmd/adapter/adapter.go +++ b/cmd/adapter/adapter.go @@ -22,7 +22,6 @@ import ( "flag" "fmt" "io/ioutil" - "log" "net/http" "net/url" "os" @@ -200,7 +199,9 @@ func main() { cmd.Name = "prometheus-metrics-adapter" cmd.addFlags() cmd.Flags().AddGoFlagSet(flag.CommandLine) // make sure we get the glog flags - cmd.Flags().Parse(os.Args) + if err := cmd.Flags().Parse(os.Args); err != nil { + glog.Fatalf("unable to parse flags: %v", err) + } // make the prometheus client promClient, err := cmd.makePromClient() @@ -280,7 +281,7 @@ func makePrometheusCAClient(caFilename string) (*http.Client, error) { return nil, fmt.Errorf("failed to read prometheus-ca-file: %v", err) } if !pool.AppendCertsFromPEM(data) { - log.Printf("warning: no certs found in prometheus-ca-file") + return nil, fmt.Errorf("no certs found in prometheus-ca-file") } return &http.Client{ From 4a16ae6d9afdefe145da427bd9c043f393ed9b39 Mon Sep 17 00:00:00 2001 From: Matthias Loibl Date: Mon, 3 Dec 2018 17:57:19 +0100 Subject: [PATCH 3/4] Log info when successfully loading certificates --- cmd/adapter/adapter.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/adapter/adapter.go b/cmd/adapter/adapter.go index 2e1974986..95985b97a 100644 --- a/cmd/adapter/adapter.go +++ b/cmd/adapter/adapter.go @@ -76,14 +76,14 @@ func (cmd *PrometheusAdapter) makePromClient() (prom.Client, error) { return nil, err } httpClient = prometheusCAClient - fmt.Println("successfully loaded ca file") + glog.Info("successfully loaded ca from file") } else { kubeconfigHTTPClient, err := makeKubeconfigHTTPClient(cmd.PrometheusAuthInCluster, cmd.PrometheusAuthConf) if err != nil { return nil, err } httpClient = kubeconfigHTTPClient - fmt.Println("successfully using in cluster") + glog.Info("successfully using in-cluster auth") } genericPromClient := prom.NewGenericAPIClient(httpClient, baseURL) From 9fb46c3c552d82d926c581c6b6fc4b01617a7cb3 Mon Sep 17 00:00:00 2001 From: Matthias Loibl Date: Mon, 3 Dec 2018 19:47:37 +0100 Subject: [PATCH 4/4] Create a NewCertPool for custom CA certificate --- cmd/adapter/adapter.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cmd/adapter/adapter.go b/cmd/adapter/adapter.go index 95985b97a..7fa378587 100644 --- a/cmd/adapter/adapter.go +++ b/cmd/adapter/adapter.go @@ -272,14 +272,12 @@ func makeKubeconfigHTTPClient(inClusterAuth bool, kubeConfigPath string) (*http. } func makePrometheusCAClient(caFilename string) (*http.Client, error) { - pool, err := x509.SystemCertPool() - if err != nil { - return nil, fmt.Errorf("failed to read system certificates: %v", err) - } data, err := ioutil.ReadFile(caFilename) if err != nil { return nil, fmt.Errorf("failed to read prometheus-ca-file: %v", err) } + + pool := x509.NewCertPool() if !pool.AppendCertsFromPEM(data) { return nil, fmt.Errorf("no certs found in prometheus-ca-file") }