From aee0bb2c644ba5bca0f819b796765f58168bd6a9 Mon Sep 17 00:00:00 2001 From: Ondrej Kokes Date: Fri, 20 Dec 2024 19:46:17 +0100 Subject: [PATCH] NewClient panics if http.client is nil and LINODE_CA is set (#635) I tried a new linodego with a custom CA and a nil HTTP client and encountered a panic. Co-authored-by: Zhiwei Liang <121905282+zliang-akamai@users.noreply.github.com> --- client.go | 9 ++++++--- client_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/client.go b/client.go index beafdbc1f..014a86213 100644 --- a/client.go +++ b/client.go @@ -738,7 +738,7 @@ func NewClient(hc *http.Client) (client Client) { certPath, certPathExists := os.LookupEnv(APIHostCert) - if certPathExists && !isCustomTransport(hc.Transport) { + if certPathExists && !hasCustomTransport(hc) { cert, err := os.ReadFile(filepath.Clean(certPath)) if err != nil { log.Fatalf("[ERROR] Error when reading cert at %s: %s\n", certPath, err.Error()) @@ -881,8 +881,11 @@ func generateListCacheURL(endpoint string, opts *ListOptions) (string, error) { return fmt.Sprintf("%s:%s", endpoint, hashedOpts), nil } -func isCustomTransport(transport http.RoundTripper) bool { - if transport != http.DefaultTransport.(*http.Transport) { +func hasCustomTransport(hc *http.Client) bool { + if hc == nil { + return false + } + if hc.Transport != http.DefaultTransport.(*http.Transport) { log.Println("[WARN] Custom transport is not allowed with a custom root CA.") return true } diff --git a/client_test.go b/client_test.go index 5b0694e55..fda3d5d90 100644 --- a/client_test.go +++ b/client_test.go @@ -576,3 +576,30 @@ func TestClient_CustomRootCAWithCustomRoundTripper(t *testing.T) { log.SetOutput(os.Stderr) } + +func TestClient_CustomRootCAWithoutCustomRoundTripper(t *testing.T) { + caFile, err := os.CreateTemp(t.TempDir(), "linodego_test_ca_*") + if err != nil { + t.Fatalf("Failed to create temp ca file: %s", err) + } + defer os.Remove(caFile.Name()) + + for _, setCA := range []bool{false, true} { + if setCA { + t.Setenv(APIHostCert, caFile.Name()) + } + + client := NewClient(nil) + + transport, err := client.resty.Transport() + if err != nil { + t.Fatal(err) + } + if setCA && (transport.TLSClientConfig == nil || transport.TLSClientConfig.RootCAs == nil) { + t.Error("expected root CAs to be set") + } + if !setCA && transport.TLSClientConfig != nil { + t.Errorf("didn't set a custom CA, but client TLS config is not nil: %#v", transport.TLSClientConfig) + } + } +}