Skip to content
Permalink
Browse files

fix(getter): set up TLS options during .Get()

Signed-off-by: Matthew Fisher <matt.fisher@microsoft.com>
  • Loading branch information
bacongobbler committed Oct 31, 2019
1 parent bf8318e commit c9b127c3ee2fd6832c02c645600fc0caff7827c2
@@ -25,7 +25,7 @@ import (
const tlsTestDir = "../../testdata"

const (
testCaCertFile = "ca.pem"
testCaCertFile = "rootca.crt"
testCertFile = "crt.pem"
testKeyFile = "key.pem"
)
@@ -29,8 +29,7 @@ import (

// HTTPGetter is the efault HTTP(/S) backend handler
type HTTPGetter struct {
client *http.Client
opts options
opts options
}

//Get performs a Get from repo.Getter and returns the body.
@@ -60,7 +59,12 @@ func (g *HTTPGetter) get(href string) (*bytes.Buffer, error) {
req.SetBasicAuth(g.opts.username, g.opts.password)
}

resp, err := g.client.Do(req)
client, err := g.httpClient()
if err != nil {
return nil, err
}

resp, err := client.Do(req)
if err != nil {
return buf, err
}
@@ -81,28 +85,31 @@ func NewHTTPGetter(options ...Option) (Getter, error) {
opt(&client.opts)
}

if client.opts.certFile != "" && client.opts.keyFile != "" {
tlsConf, err := tlsutil.NewClientTLS(client.opts.certFile, client.opts.keyFile, client.opts.caFile)
return &client, nil
}

func (g *HTTPGetter) httpClient() (*http.Client, error) {
if g.opts.certFile != "" && g.opts.keyFile != "" {
tlsConf, err := tlsutil.NewClientTLS(g.opts.certFile, g.opts.keyFile, g.opts.caFile)
if err != nil {
return &client, errors.Wrap(err, "can't create TLS config for client")
return nil, errors.Wrap(err, "can't create TLS config for client")
}
tlsConf.BuildNameToCertificate()

sni, err := urlutil.ExtractHostname(client.opts.url)
sni, err := urlutil.ExtractHostname(g.opts.url)
if err != nil {
return &client, err
return nil, err
}
tlsConf.ServerName = sni

client.client = &http.Client{
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: tlsConf,
Proxy: http.ProxyFromEnvironment,
},
}
} else {
client.client = http.DefaultClient
}

return &client, nil
return client, nil
}
return http.DefaultClient, nil
}
@@ -24,7 +24,9 @@ import (
"strings"
"testing"

"helm.sh/helm/v3/internal/test"
"github.com/pkg/errors"

"helm.sh/helm/v3/internal/tlsutil"
"helm.sh/helm/v3/internal/version"
"helm.sh/helm/v3/pkg/cli"
)
@@ -35,46 +37,25 @@ func TestHTTPGetter(t *testing.T) {
t.Fatal(err)
}

if hg, ok := g.(*HTTPGetter); !ok {
if _, ok := g.(*HTTPGetter); !ok {
t.Fatal("Expected NewHTTPGetter to produce an *HTTPGetter")
} else if hg.client != http.DefaultClient {
t.Fatal("Expected NewHTTPGetter to return a default HTTP client.")
}

// Test with SSL:
cd := "../../testdata"
join := filepath.Join
ca, pub, priv := join(cd, "ca.pem"), join(cd, "crt.pem"), join(cd, "key.pem")
g, err = NewHTTPGetter(
WithURL("http://example.com"),
WithTLSClientConfig(pub, priv, ca),
)
if err != nil {
t.Fatal(err)
}

hg, ok := g.(*HTTPGetter)
if !ok {
t.Fatal("Expected NewHTTPGetter to produce an *HTTPGetter")
}
ca, pub, priv := join(cd, "rootca.crt"), join(cd, "crt.pem"), join(cd, "key.pem")

transport, ok := hg.client.Transport.(*http.Transport)
if !ok {
t.Errorf("Expected NewHTTPGetter to set up an HTTP transport")
}

test.AssertGoldenString(t, transport.TLSClientConfig.ServerName, "output/httpgetter-servername.txt")

// Test other options
// Test with options
g, err = NewHTTPGetter(
WithBasicAuth("I", "Am"),
WithUserAgent("Groot"),
WithTLSClientConfig(pub, priv, ca),
)
if err != nil {
t.Fatal(err)
}

hg, ok = g.(*HTTPGetter)
hg, ok := g.(*HTTPGetter)
if !ok {
t.Fatal("expected NewHTTPGetter to produce an *HTTPGetter")
}
@@ -90,6 +71,18 @@ func TestHTTPGetter(t *testing.T) {
if hg.opts.userAgent != "Groot" {
t.Errorf("Expected NewHTTPGetter to contain %q as the user agent, got %q", "Groot", hg.opts.userAgent)
}

if hg.opts.certFile != pub {
t.Errorf("Expected NewHTTPGetter to contain %q as the public key file, got %q", pub, hg.opts.certFile)
}

if hg.opts.keyFile != priv {
t.Errorf("Expected NewHTTPGetter to contain %q as the private key file, got %q", priv, hg.opts.keyFile)
}

if hg.opts.caFile != ca {
t.Errorf("Expected NewHTTPGetter to contain %q as the CA file, got %q", ca, hg.opts.caFile)
}
}

func TestDownload(t *testing.T) {
@@ -149,3 +142,42 @@ func TestDownload(t *testing.T) {
t.Errorf("Expected %q, got %q", expect, got.String())
}
}

func TestDownloadTLS(t *testing.T) {
cd := "../../testdata"
ca, pub, priv := filepath.Join(cd, "rootca.crt"), filepath.Join(cd, "crt.pem"), filepath.Join(cd, "key.pem")

tlsSrv := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
tlsConf, err := tlsutil.NewClientTLS(pub, priv, ca)
if err != nil {
t.Fatal(errors.Wrap(err, "can't create TLS config for client"))
}
tlsConf.BuildNameToCertificate()
tlsConf.ServerName = "helm.sh"
tlsSrv.TLS = tlsConf
tlsSrv.StartTLS()
defer tlsSrv.Close()

u, _ := url.ParseRequestURI(tlsSrv.URL)
g, err := NewHTTPGetter(
WithURL(u.String()),
WithTLSClientConfig(pub, priv, ca),
)
if err != nil {
t.Fatal(err)
}

if _, err := g.Get(u.String()); err != nil {
t.Error(err)
}

// now test with TLS config being passed along in .Get (see #6635)
g, err = NewHTTPGetter()
if err != nil {
t.Fatal(err)
}

if _, err := g.Get(u.String(), WithURL(u.String()), WithTLSClientConfig(pub, priv, ca)); err != nil {
t.Error(err)
}
}

This file was deleted.

This file was deleted.

@@ -1,29 +1,73 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
55:31:53:9b:41:72:05:dc:90:49:bd:48:13:7c:59:9e:5a:53:5e:86
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, ST=CO, L=Boulder, O=Helm, CN=helm.sh
Validity
Not Before: Nov 1 22:51:49 2019 GMT
Not After : Oct 29 22:51:49 2029 GMT
Subject: C=US, ST=CO, L=Boulder, O=Helm, CN=helm.sh
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:c8:89:55:0d:0b:f1:da:e6:c0:70:7d:d3:27:cd:
b8:a8:81:8b:7c:a4:89:e5:d1:b1:78:01:1d:df:44:
88:0b:fc:d6:81:35:3d:d1:3b:5e:8f:bb:93:b3:7e:
28:db:ed:ff:a0:13:3a:70:a3:fe:94:6b:0b:fe:fb:
63:00:b0:cb:dc:81:cd:80:dc:d0:2f:bf:b2:4f:9a:
81:d4:22:dc:97:c8:8f:27:86:59:91:fa:92:05:75:
c4:cc:6b:f5:a9:6b:74:1e:f5:db:a9:f8:bf:8c:a2:
25:fd:a0:cc:79:f4:25:57:74:a9:23:9b:e2:b7:22:
7a:14:7a:3d:ea:f1:7e:32:6b:57:6c:2e:c6:4f:75:
54:f9:6b:54:d2:ca:eb:54:1c:af:39:15:9b:d0:7c:
0f:f8:55:51:04:ea:da:fa:7b:8b:63:0f:ac:39:b1:
f6:4b:8e:4e:f6:ea:e9:7b:e6:ba:5e:5a:8e:91:ef:
dc:b1:7d:52:3f:73:83:52:46:83:48:49:ff:f2:2d:
ca:54:f2:36:bb:49:cc:59:99:c0:9e:cf:8e:78:55:
6c:ed:7d:7e:83:b8:59:2c:7d:f8:1a:81:f0:7d:f5:
27:f2:db:ae:d4:31:54:38:fe:47:b2:ee:16:20:0f:
f1:db:2d:28:bf:6f:38:eb:11:bb:9a:d4:b2:5a:3a:
4a:7f
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:helm.sh, IP Address:127.0.0.1
Signature Algorithm: sha256WithRSAEncryption
4e:17:27:3d:36:4e:6c:2b:f7:d4:28:33:7e:05:26:7a:42:a0:
2c:44:57:04:a0:de:df:40:fb:af:70:27:e6:55:20:f1:f8:c0:
50:63:ab:b8:f1:31:5d:1e:f4:ca:8d:65:0b:d4:5e:5b:77:2f:
2a:af:74:5f:18:2d:92:29:7f:2d:97:fb:ec:aa:e3:1e:db:b3:
8d:01:aa:82:1a:f6:28:a8:b3:ee:15:9f:9a:f5:76:37:30:f2:
3b:38:13:b2:d4:14:94:c6:38:fa:f9:6e:94:e8:1f:11:0b:b0:
69:1a:b3:f9:f1:27:b4:d2:f5:64:54:7c:8f:e7:83:31:f6:0d:
a7:0e:0e:66:d8:33:2f:e0:a1:93:56:92:58:bf:50:da:56:8e:
db:42:22:f5:0c:6f:f8:4c:ef:f5:7c:2d:a6:b8:60:e4:bb:df:
a3:6c:c2:6b:99:0b:d3:0a:ad:7c:f4:74:72:9a:52:5e:81:d9:
a2:a2:dd:68:38:fb:b7:54:7f:f6:aa:ee:53:de:3d:3a:0e:86:
53:ad:af:72:db:fb:6b:18:ce:ac:e4:64:70:13:68:da:be:e1:
6b:46:dd:a0:72:96:9b:3f:ba:cf:11:6e:98:03:0a:69:83:9e:
37:25:c9:36:b9:68:4f:73:ca:c6:32:5c:be:46:64:bb:a8:cc:
71:25:8f:be
-----BEGIN CERTIFICATE-----
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
g543Jck2uWhPc8rGMly+RmS7qMxxJY++
-----END CERTIFICATE-----
@@ -0,0 +1,4 @@
#!/bin/sh

openssl req -new -config openssl.conf -key key.pem -out key.csr
openssl ca -config openssl.conf -create_serial -batch -in key.csr -out crt.pem -key rootca.key -cert rootca.crt

0 comments on commit c9b127c

Please sign in to comment.
You can’t perform that action at this time.