diff --git a/pkg/downloader/manager.go b/pkg/downloader/manager.go index 2dedc5757..468d670c4 100644 --- a/pkg/downloader/manager.go +++ b/pkg/downloader/manager.go @@ -310,7 +310,7 @@ func (m *Manager) downloadAll(deps []*chart.Dependency) error { // Any failure to resolve/download a chart should fail: // https://github.com/helm/helm/issues/1439 - churl, username, password, insecureskiptlsverify, err := m.findChartURL(dep.Name, dep.Version, dep.Repository, repos) + churl, username, password, certfile, keyfile, cafile, insecureskiptlsverify, err := m.findChartURL(dep.Name, dep.Version, dep.Repository, repos) if err != nil { saveError = errors.Wrapf(err, "could not find %s", churl) break @@ -332,6 +332,7 @@ func (m *Manager) downloadAll(deps []*chart.Dependency) error { Getters: m.Getters, Options: []getter.Option{ getter.WithBasicAuth(username, password), + getter.WithTLSClientConfig(certfile, keyfile, cafile), getter.WithInsecureSkipVerifyTLS(insecureskiptlsverify), }, } @@ -686,9 +687,9 @@ func (m *Manager) parallelRepoUpdate(repos []*repo.Entry) error { // repoURL is the repository to search // // If it finds a URL that is "relative", it will prepend the repoURL. -func (m *Manager) findChartURL(name, version, repoURL string, repos map[string]*repo.ChartRepository) (url, username, password string, insecureskiptlsverify bool, err error) { +func (m *Manager) findChartURL(name, version, repoURL string, repos map[string]*repo.ChartRepository) (url, username, password, certfile, keyfile, cafile string, insecureskiptlsverify bool, err error) { if strings.HasPrefix(repoURL, "oci://") { - return fmt.Sprintf("%s/%s:%s", repoURL, name, version), "", "", false, nil + return fmt.Sprintf("%s/%s:%s", repoURL, name, version), "", "", "", "", "", false, nil } for _, cr := range repos { @@ -710,16 +711,19 @@ func (m *Manager) findChartURL(name, version, repoURL string, repos map[string]* } username = cr.Config.Username password = cr.Config.Password + keyfile = cr.Config.KeyFile + certfile = cr.Config.CertFile + cafile = cr.Config.CAFile insecureskiptlsverify = cr.Config.InsecureSkipTLSverify return } } - url, err = repo.FindChartInRepoURL(repoURL, name, version, "", "", "", m.Getters) + url, err = repo.FindChartInRepoURL(repoURL, name, version, certfile, keyfile, cafile, m.Getters) if err == nil { - return url, username, password, false, err + return url, username, password, certfile, keyfile, cafile, false, err } err = errors.Errorf("chart %s not found in %s: %s", name, repoURL, err) - return url, username, password, false, err + return url, username, password, certfile, keyfile, cafile, false, err } // findEntryByName finds an entry in the chart repository whose name matches the given name. diff --git a/pkg/downloader/manager_test.go b/pkg/downloader/manager_test.go index ba6ecedf5..edd253abc 100644 --- a/pkg/downloader/manager_test.go +++ b/pkg/downloader/manager_test.go @@ -81,7 +81,7 @@ func TestFindChartURL(t *testing.T) { version := "0.1.0" repoURL := "http://example.com/charts" - churl, username, password, insecureSkipTLSVerify, err := m.findChartURL(name, version, repoURL, repos) + churl, username, password, certname, keyname, cafile, insecureSkipTLSVerify, err := m.findChartURL(name, version, repoURL, repos) if err != nil { t.Fatal(err) } @@ -95,6 +95,15 @@ func TestFindChartURL(t *testing.T) { if password != "" { t.Errorf("Unexpected password %q", password) } + if certname != "" { + t.Errorf("Unexpected certname %q", certname) + } + if keyname != "" { + t.Errorf("Unexpected keyname %q", keyname) + } + if cafile != "" { + t.Errorf("Unexpected cafile %q", cafile) + } if insecureSkipTLSVerify { t.Errorf("Unexpected insecureSkipTLSVerify %t", insecureSkipTLSVerify) } @@ -103,7 +112,7 @@ func TestFindChartURL(t *testing.T) { version = "1.2.3" repoURL = "https://example-https-insecureskiptlsverify.com" - churl, username, password, insecureSkipTLSVerify, err = m.findChartURL(name, version, repoURL, repos) + churl, username, password, certname, keyname, cafile, insecureSkipTLSVerify, err = m.findChartURL(name, version, repoURL, repos) if err != nil { t.Fatal(err) } @@ -120,6 +129,46 @@ func TestFindChartURL(t *testing.T) { if password != "" { t.Errorf("Unexpected password %q", password) } + if certname != "" { + t.Errorf("Unexpected certname %q", certname) + } + if keyname != "" { + t.Errorf("Unexpected keyname %q", keyname) + } + if cafile != "" { + t.Errorf("Unexpected cafile %q", cafile) + } + + name = "privatechart" + version = "1.2.3" + repoURL = "https://private.example.com" + + churl, username, password, certname, keyname, cafile, insecureSkipTLSVerify, err = m.findChartURL(name, version, repoURL, repos) + if err != nil { + t.Fatal(err) + } + + if insecureSkipTLSVerify { + t.Errorf("Unexpected insecureSkipTLSVerify %t", insecureSkipTLSVerify) + } + if churl != "https://private.example.com/privatechart-1.2.3.tgz" { + t.Errorf("Unexpected URL %q", churl) + } + if username != "" { + t.Errorf("Unexpected username %q", username) + } + if password != "" { + t.Errorf("Unexpected password %q", password) + } + if certname != "cert" { + t.Errorf("Unexpected certname %q", certname) + } + if keyname != "key" { + t.Errorf("Unexpected keyname %q", keyname) + } + if cafile != "ca" { + t.Errorf("Unexpected cafile %q", cafile) + } } func TestGetRepoNames(t *testing.T) { diff --git a/pkg/downloader/testdata/repositories.yaml b/pkg/downloader/testdata/repositories.yaml index 32bc395a0..8d213bbdd 100644 --- a/pkg/downloader/testdata/repositories.yaml +++ b/pkg/downloader/testdata/repositories.yaml @@ -24,3 +24,8 @@ repositories: - name: testing-https-insecureskip-tls-verify url: "https://example-https-insecureskiptlsverify.com" insecure_skip_tls_verify: true + - name: testing-cert-key + url: "https://private.example.com" + certFile: "cert" + keyFile: "key" + caFile: "ca" diff --git a/pkg/downloader/testdata/repository/testing-cert-key-index.yaml b/pkg/downloader/testdata/repository/testing-cert-key-index.yaml new file mode 100644 index 000000000..732130aa0 --- /dev/null +++ b/pkg/downloader/testdata/repository/testing-cert-key-index.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +entries: + privatechart: + - name: privatechart + description: Private Chart protected by client certificate + home: https://helm.sh/helm + keywords: [] + maintainers: [] + sources: + - https://github.com/helm/charts + urls: + - https://private.example.com/privatechart-1.2.3.tgz + version: 1.2.3 + checksum: 0e6661f193211d7a5206918d42f5c2a9470b737d + apiVersion: v2