diff --git a/api/v1beta1/helmrepository_types.go b/api/v1beta1/helmrepository_types.go index a2aef56a..40f918d2 100644 --- a/api/v1beta1/helmrepository_types.go +++ b/api/v1beta1/helmrepository_types.go @@ -45,6 +45,15 @@ type HelmRepositorySpec struct { // +optional SecretRef *meta.LocalObjectReference `json:"secretRef,omitempty"` + // PassCredentials allows the credentials from the SecretRef to be passed on to + // a host that does not match the host as defined in URL. + // This may be required if the host of the advertised chart URLs in the index + // differ from the defined URL. + // Enabling this should be done with caution, as it can potentially result in + // credentials getting stolen in a MITM-attack. + // +optional + PassCredentials bool `json:"passCredentials,omitempty"` + // The interval at which to check the upstream for updates. // +required Interval metav1.Duration `json:"interval"` diff --git a/config/crd/bases/source.toolkit.fluxcd.io_helmrepositories.yaml b/config/crd/bases/source.toolkit.fluxcd.io_helmrepositories.yaml index 1052694d..4409c0f9 100644 --- a/config/crd/bases/source.toolkit.fluxcd.io_helmrepositories.yaml +++ b/config/crd/bases/source.toolkit.fluxcd.io_helmrepositories.yaml @@ -50,6 +50,9 @@ spec: interval: description: The interval at which to check the upstream for updates. type: string + passCredentials: + description: PassCredentials allows the credentials from the SecretRef to be passed on to a host that does not match the host as defined in URL. This may be required if the host of the advertised chart URLs in the index differ from the defined URL. Enabling this should be done with caution, as it can potentially result in credentials getting stolen in a MITM-attack. + type: boolean secretRef: description: The name of the secret containing authentication credentials for the Helm repository. For HTTP/S basic auth the secret must contain username and password fields. For TLS the secret must contain a certFile and keyFile, and/or caCert fields. properties: diff --git a/controllers/helmchart_controller.go b/controllers/helmchart_controller.go index 2d59e9bf..93a79509 100644 --- a/controllers/helmchart_controller.go +++ b/controllers/helmchart_controller.go @@ -301,7 +301,11 @@ func (r *HelmChartReconciler) getSource(ctx context.Context, chart sourcev1.Helm func (r *HelmChartReconciler) reconcileFromHelmRepository(ctx context.Context, repository sourcev1.HelmRepository, chart sourcev1.HelmChart, force bool) (sourcev1.HelmChart, error) { // Configure ChartRepository getter options - var clientOpts []getter.Option + clientOpts := []getter.Option{ + getter.WithURL(repository.Spec.URL), + getter.WithTimeout(repository.Spec.Timeout.Duration), + getter.WithPassCredentialsAll(repository.Spec.PassCredentials), + } if secret, err := r.getHelmRepositorySecret(ctx, &repository); err != nil { return sourcev1.HelmChartNotReady(chart, sourcev1.AuthenticationFailedReason, err.Error()), err } else if secret != nil { @@ -311,10 +315,8 @@ func (r *HelmChartReconciler) reconcileFromHelmRepository(ctx context.Context, return sourcev1.HelmChartNotReady(chart, sourcev1.AuthenticationFailedReason, err.Error()), err } defer cleanup() - - clientOpts = opts + clientOpts = append(clientOpts, opts...) } - clientOpts = append(clientOpts, getter.WithTimeout(repository.Spec.Timeout.Duration)) // Initialize the chart repository and load the index file chartRepo, err := helm.NewChartRepository(repository.Spec.URL, r.Getters, clientOpts) @@ -619,13 +621,18 @@ func (r *HelmChartReconciler) reconcileFromTarballArtifact(ctx context.Context, if err != nil { repository = &sourcev1.HelmRepository{ Spec: sourcev1.HelmRepositorySpec{ - URL: dep.Repository, + URL: dep.Repository, + Timeout: &metav1.Duration{Duration: 60 * time.Second}, }, } } // Configure ChartRepository getter options - var clientOpts []getter.Option + clientOpts := []getter.Option{ + getter.WithURL(repository.Spec.URL), + getter.WithTimeout(repository.Spec.Timeout.Duration), + getter.WithPassCredentialsAll(repository.Spec.PassCredentials), + } if secret, err := r.getHelmRepositorySecret(ctx, repository); err != nil { return sourcev1.HelmChartNotReady(chart, sourcev1.AuthenticationFailedReason, err.Error()), err } else if secret != nil { @@ -635,8 +642,7 @@ func (r *HelmChartReconciler) reconcileFromTarballArtifact(ctx context.Context, return sourcev1.HelmChartNotReady(chart, sourcev1.AuthenticationFailedReason, err.Error()), err } defer cleanup() - - clientOpts = opts + clientOpts = append(clientOpts, opts...) } // Initialize the chart repository and load the index file diff --git a/controllers/helmchart_controller_test.go b/controllers/helmchart_controller_test.go index 65af83b3..c88fa339 100644 --- a/controllers/helmchart_controller_test.go +++ b/controllers/helmchart_controller_test.go @@ -1015,9 +1015,9 @@ var _ = Describe("HelmChartReconciler", func() { Name: secretKey.Name, Namespace: secretKey.Namespace, }, - Data: map[string][]byte{ - "username": []byte(username), - "password": []byte(password), + StringData: map[string]string{ + "username": username, + "password": password, }, } Expect(k8sClient.Create(context.Background(), secret)).Should(Succeed()) diff --git a/controllers/helmrepository_controller.go b/controllers/helmrepository_controller.go index d7f3bdf1..b7f8cd51 100644 --- a/controllers/helmrepository_controller.go +++ b/controllers/helmrepository_controller.go @@ -171,7 +171,11 @@ func (r *HelmRepositoryReconciler) Reconcile(ctx context.Context, req ctrl.Reque } func (r *HelmRepositoryReconciler) reconcile(ctx context.Context, repository sourcev1.HelmRepository) (sourcev1.HelmRepository, error) { - var clientOpts []getter.Option + clientOpts := []getter.Option{ + getter.WithURL(repository.Spec.URL), + getter.WithTimeout(repository.Spec.Timeout.Duration), + getter.WithPassCredentialsAll(repository.Spec.PassCredentials), + } if repository.Spec.SecretRef != nil { name := types.NamespacedName{ Namespace: repository.GetNamespace(), @@ -191,9 +195,8 @@ func (r *HelmRepositoryReconciler) reconcile(ctx context.Context, repository sou return sourcev1.HelmRepositoryNotReady(repository, sourcev1.AuthenticationFailedReason, err.Error()), err } defer cleanup() - clientOpts = opts + clientOpts = append(clientOpts, opts...) } - clientOpts = append(clientOpts, getter.WithTimeout(repository.Spec.Timeout.Duration)) chartRepo, err := helm.NewChartRepository(repository.Spec.URL, r.Getters, clientOpts) if err != nil { diff --git a/docs/api/source.md b/docs/api/source.md index 53793291..7b1fede4 100644 --- a/docs/api/source.md +++ b/docs/api/source.md @@ -703,6 +703,23 @@ caCert fields.
passCredentials
PassCredentials allows the credentials from the SecretRef to be passed on to +a host that does not match the host as defined in URL. +This may be required if the host of the advertised chart URLs in the index +differ from the defined URL. +Enabling this should be done with caution, as it can potentially result in +credentials getting stolen in a MITM-attack.
+interval
passCredentials
PassCredentials allows the credentials from the SecretRef to be passed on to +a host that does not match the host as defined in URL. +This may be required if the host of the advertised chart URLs in the index +differ from the defined URL. +Enabling this should be done with caution, as it can potentially result in +credentials getting stolen in a MITM-attack.
+interval