Repository: helm/helm (go)

Issue:
Helm dep build/update doesn't inherit --ca-file --cert-file --key-file from helm repo add
After adding a repo with `helm repo add --ca-file pathToCA.pem https://example.com/helm`, helm dependency update on an umbrella chart will fail with `x509: certificate signed by unknown authority`

It looks like the same problem as for https://github.com/helm/helm/issues/8868. Fixing this one could also fix https://github.com/helm/helm/issues/9568

Output of `helm version`: 3.6.0

Output of `kubectl version`: 1.20.7

Cloud Provider/Platform (AKS, GKE, Minikube etc.): minikube




Pull request:
use TLS client information from repo config when downloading a chart
Signed-off-by: Christophe VILA <christophe.vila@thalesgroup.com>

<!--  Thanks for sending a pull request!  Here are some tips for you:
1. Make sure to read the Contributing Guide before submitting your PR: https://github.com/helm/helm/blob/main/CONTRIBUTING.md
2. If this PR closes another issue, add 'closes #<issue number>' somewhere in the PR summary. GitHub will automatically close that issue when this PR gets merged. Alternatively, adding 'refs #<issue number>' will not close the issue, but help provide the reviewer more context.-->

**What this PR does / why we need it**: closes #9826

**Special notes for your reviewer**: there seems to be some TLS client config logic already in place in https://github.com/helm/helm/blob/179f90151d5ecb4aa3d35ada35e82b5c1e791752/pkg/downloader/chart_downloader.go#L156 but I think it is useless (either the downloader options configuration is already set by the caller, either this logic is not reached because of a possible bug in https://github.com/helm/helm/blob/179f90151d5ecb4aa3d35ada35e82b5c1e791752/pkg/downloader/chart_downloader.go#L344 around URL comparison which fails because one is relative and the other is absolute)

**If applicable**:
- [ ] this PR contains documentation
- [ ] this PR contains unit tests
- [ ] this PR has been tested for backwards compatibility


Patch:
diff --git a/pkg/downloader/manager.go b/pkg/downloader/manager.go
index 22db8bfdd..ff5f9c4e7 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, passcredentialsall, err := m.findChartURL(dep.Name, dep.Version, dep.Repository, repos)
+		churl, username, password, insecureskiptlsverify, passcredentialsall, caFile, certFile, keyFile, err := m.findChartURL(dep.Name, dep.Version, dep.Repository, repos)
 		if err != nil {
 			saveError = errors.Wrapf(err, "could not find %s", churl)
 			break
@@ -334,6 +334,7 @@ func (m *Manager) downloadAll(deps []*chart.Dependency) error {
 				getter.WithBasicAuth(username, password),
 				getter.WithPassCredentialsAll(passcredentialsall),
 				getter.WithInsecureSkipVerifyTLS(insecureskiptlsverify),
+				getter.WithTLSClientConfig(certFile, keyFile, caFile),
 			},
 		}
 
@@ -687,9 +688,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, passcredentialsall bool, err error) {
+func (m *Manager) findChartURL(name, version, repoURL string, repos map[string]*repo.ChartRepository) (url, username, password string, insecureskiptlsverify, passcredentialsall bool, caFile, certFile, keyFile string, err error) {
 	if strings.HasPrefix(repoURL, "oci://") {
-		return fmt.Sprintf("%s/%s:%s", repoURL, name, version), "", "", false, false, nil
+		return fmt.Sprintf("%s/%s:%s", repoURL, name, version), "", "", false, false, "", "", "", nil
 	}
 
 	for _, cr := range repos {
@@ -713,15 +714,18 @@ func (m *Manager) findChartURL(name, version, repoURL string, repos map[string]*
 			password = cr.Config.Password
 			passcredentialsall = cr.Config.PassCredentialsAll
 			insecureskiptlsverify = cr.Config.InsecureSkipTLSverify
+			caFile = cr.Config.CAFile
+			certFile = cr.Config.CertFile
+			keyFile = cr.Config.KeyFile
 			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, false, err
+		return url, username, password, false, false, "", "", "", err
 	}
 	err = errors.Errorf("chart %s not found in %s: %s", name, repoURL, err)
-	return url, username, password, false, false, err
+	return url, username, password, false, false, "", "", "", err
 }
 
 // findEntryByName finds an entry in the chart repository whose name matches the given name.


Test patch:
diff --git a/pkg/downloader/manager_test.go b/pkg/downloader/manager_test.go
index 0cc6d6f12..b8da42cd2 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, passcredentialsall, err := m.findChartURL(name, version, repoURL, repos)
+	churl, username, password, insecureSkipTLSVerify, passcredentialsall, _, _, _, err := m.findChartURL(name, version, repoURL, repos)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -106,7 +106,7 @@ func TestFindChartURL(t *testing.T) {
 	version = "1.2.3"
 	repoURL = "https://example-https-insecureskiptlsverify.com"
 
-	churl, username, password, insecureSkipTLSVerify, passcredentialsall, err = m.findChartURL(name, version, repoURL, repos)
+	churl, username, password, insecureSkipTLSVerify, passcredentialsall, _, _, _, err = m.findChartURL(name, version, repoURL, repos)
 	if err != nil {
 		t.Fatal(err)
 	}