Update Helm to v3.6.1
v3.6.1 is a a security update from Helm, ensuring that credentials are always only passed to the defined repository host. Based on Helm user reports, disabling this behavior may be required for some Helm repository solutions like Artifactory, and may be done by setting `PassCredentials` in the `HelmRepositorySpec`. For more information, see: https://github.com/helm/helm/security/advisories/GHSA-56hp-xqp3-w2jf Signed-off-by: Hidde Beydals <hello@hidde.co>
This commit is contained in:
parent
1a75415103
commit
1f27410b34
|
@ -45,6 +45,15 @@ type HelmRepositorySpec struct {
|
||||||
// +optional
|
// +optional
|
||||||
SecretRef *meta.LocalObjectReference `json:"secretRef,omitempty"`
|
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.
|
// The interval at which to check the upstream for updates.
|
||||||
// +required
|
// +required
|
||||||
Interval metav1.Duration `json:"interval"`
|
Interval metav1.Duration `json:"interval"`
|
||||||
|
|
|
@ -50,6 +50,9 @@ spec:
|
||||||
interval:
|
interval:
|
||||||
description: The interval at which to check the upstream for updates.
|
description: The interval at which to check the upstream for updates.
|
||||||
type: string
|
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:
|
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.
|
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:
|
properties:
|
||||||
|
|
|
@ -301,7 +301,11 @@ func (r *HelmChartReconciler) getSource(ctx context.Context, chart sourcev1.Helm
|
||||||
func (r *HelmChartReconciler) reconcileFromHelmRepository(ctx context.Context,
|
func (r *HelmChartReconciler) reconcileFromHelmRepository(ctx context.Context,
|
||||||
repository sourcev1.HelmRepository, chart sourcev1.HelmChart, force bool) (sourcev1.HelmChart, error) {
|
repository sourcev1.HelmRepository, chart sourcev1.HelmChart, force bool) (sourcev1.HelmChart, error) {
|
||||||
// Configure ChartRepository getter options
|
// 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 {
|
if secret, err := r.getHelmRepositorySecret(ctx, &repository); err != nil {
|
||||||
return sourcev1.HelmChartNotReady(chart, sourcev1.AuthenticationFailedReason, err.Error()), err
|
return sourcev1.HelmChartNotReady(chart, sourcev1.AuthenticationFailedReason, err.Error()), err
|
||||||
} else if secret != nil {
|
} else if secret != nil {
|
||||||
|
@ -311,10 +315,8 @@ func (r *HelmChartReconciler) reconcileFromHelmRepository(ctx context.Context,
|
||||||
return sourcev1.HelmChartNotReady(chart, sourcev1.AuthenticationFailedReason, err.Error()), err
|
return sourcev1.HelmChartNotReady(chart, sourcev1.AuthenticationFailedReason, err.Error()), err
|
||||||
}
|
}
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
clientOpts = append(clientOpts, opts...)
|
||||||
clientOpts = opts
|
|
||||||
}
|
}
|
||||||
clientOpts = append(clientOpts, getter.WithTimeout(repository.Spec.Timeout.Duration))
|
|
||||||
|
|
||||||
// Initialize the chart repository and load the index file
|
// Initialize the chart repository and load the index file
|
||||||
chartRepo, err := helm.NewChartRepository(repository.Spec.URL, r.Getters, clientOpts)
|
chartRepo, err := helm.NewChartRepository(repository.Spec.URL, r.Getters, clientOpts)
|
||||||
|
@ -619,13 +621,18 @@ func (r *HelmChartReconciler) reconcileFromTarballArtifact(ctx context.Context,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
repository = &sourcev1.HelmRepository{
|
repository = &sourcev1.HelmRepository{
|
||||||
Spec: sourcev1.HelmRepositorySpec{
|
Spec: sourcev1.HelmRepositorySpec{
|
||||||
URL: dep.Repository,
|
URL: dep.Repository,
|
||||||
|
Timeout: &metav1.Duration{Duration: 60 * time.Second},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure ChartRepository getter options
|
// 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 {
|
if secret, err := r.getHelmRepositorySecret(ctx, repository); err != nil {
|
||||||
return sourcev1.HelmChartNotReady(chart, sourcev1.AuthenticationFailedReason, err.Error()), err
|
return sourcev1.HelmChartNotReady(chart, sourcev1.AuthenticationFailedReason, err.Error()), err
|
||||||
} else if secret != nil {
|
} else if secret != nil {
|
||||||
|
@ -635,8 +642,7 @@ func (r *HelmChartReconciler) reconcileFromTarballArtifact(ctx context.Context,
|
||||||
return sourcev1.HelmChartNotReady(chart, sourcev1.AuthenticationFailedReason, err.Error()), err
|
return sourcev1.HelmChartNotReady(chart, sourcev1.AuthenticationFailedReason, err.Error()), err
|
||||||
}
|
}
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
|
clientOpts = append(clientOpts, opts...)
|
||||||
clientOpts = opts
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the chart repository and load the index file
|
// Initialize the chart repository and load the index file
|
||||||
|
|
|
@ -1015,9 +1015,9 @@ var _ = Describe("HelmChartReconciler", func() {
|
||||||
Name: secretKey.Name,
|
Name: secretKey.Name,
|
||||||
Namespace: secretKey.Namespace,
|
Namespace: secretKey.Namespace,
|
||||||
},
|
},
|
||||||
Data: map[string][]byte{
|
StringData: map[string]string{
|
||||||
"username": []byte(username),
|
"username": username,
|
||||||
"password": []byte(password),
|
"password": password,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
Expect(k8sClient.Create(context.Background(), secret)).Should(Succeed())
|
Expect(k8sClient.Create(context.Background(), secret)).Should(Succeed())
|
||||||
|
|
|
@ -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) {
|
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 {
|
if repository.Spec.SecretRef != nil {
|
||||||
name := types.NamespacedName{
|
name := types.NamespacedName{
|
||||||
Namespace: repository.GetNamespace(),
|
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
|
return sourcev1.HelmRepositoryNotReady(repository, sourcev1.AuthenticationFailedReason, err.Error()), err
|
||||||
}
|
}
|
||||||
defer cleanup()
|
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)
|
chartRepo, err := helm.NewChartRepository(repository.Spec.URL, r.Getters, clientOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -703,6 +703,23 @@ caCert fields.</p>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
|
<code>passCredentials</code><br>
|
||||||
|
<em>
|
||||||
|
bool
|
||||||
|
</em>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<em>(Optional)</em>
|
||||||
|
<p>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.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
<code>interval</code><br>
|
<code>interval</code><br>
|
||||||
<em>
|
<em>
|
||||||
<a href="https://godoc.org/k8s.io/apimachinery/pkg/apis/meta/v1#Duration">
|
<a href="https://godoc.org/k8s.io/apimachinery/pkg/apis/meta/v1#Duration">
|
||||||
|
@ -1777,6 +1794,23 @@ caCert fields.</p>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
|
<code>passCredentials</code><br>
|
||||||
|
<em>
|
||||||
|
bool
|
||||||
|
</em>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<em>(Optional)</em>
|
||||||
|
<p>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.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
<code>interval</code><br>
|
<code>interval</code><br>
|
||||||
<em>
|
<em>
|
||||||
<a href="https://godoc.org/k8s.io/apimachinery/pkg/apis/meta/v1#Duration">
|
<a href="https://godoc.org/k8s.io/apimachinery/pkg/apis/meta/v1#Duration">
|
||||||
|
|
|
@ -21,9 +21,18 @@ type HelmRepositorySpec struct {
|
||||||
// password fields.
|
// password fields.
|
||||||
// For TLS the secret must contain a certFile and keyFile, and/or
|
// For TLS the secret must contain a certFile and keyFile, and/or
|
||||||
// caCert fields.
|
// caCert fields.
|
||||||
// +optional
|
// +optional
|
||||||
SecretRef *corev1.LocalObjectReference `json:"secretRef,omitempty"`
|
SecretRef *corev1.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.
|
// The interval at which to check the upstream for updates.
|
||||||
// +required
|
// +required
|
||||||
Interval metav1.Duration `json:"interval"`
|
Interval metav1.Duration `json:"interval"`
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -29,7 +29,7 @@ require (
|
||||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b
|
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
|
||||||
gotest.tools v2.2.0+incompatible
|
gotest.tools v2.2.0+incompatible
|
||||||
helm.sh/helm/v3 v3.6.0
|
helm.sh/helm/v3 v3.6.1
|
||||||
k8s.io/api v0.21.1
|
k8s.io/api v0.21.1
|
||||||
k8s.io/apimachinery v0.21.1
|
k8s.io/apimachinery v0.21.1
|
||||||
k8s.io/client-go v0.21.1
|
k8s.io/client-go v0.21.1
|
||||||
|
|
3
go.sum
3
go.sum
|
@ -1247,8 +1247,9 @@ gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81
|
||||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||||
gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
|
gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
|
||||||
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
|
||||||
helm.sh/helm/v3 v3.6.0 h1:/9IMxJ2lXJHbvTMHcW1AO71lXQHqDC+3bcpGp7yCsb8=
|
|
||||||
helm.sh/helm/v3 v3.6.0/go.mod h1:mIIus8EOqj+obtycw3sidsR4ORr2aFDmXMSI3k+oeVY=
|
helm.sh/helm/v3 v3.6.0/go.mod h1:mIIus8EOqj+obtycw3sidsR4ORr2aFDmXMSI3k+oeVY=
|
||||||
|
helm.sh/helm/v3 v3.6.1 h1:TQ6q4pAatXr7qh2fbLcb0oNd0I3J7kv26oo5cExKTtc=
|
||||||
|
helm.sh/helm/v3 v3.6.1/go.mod h1:mIIus8EOqj+obtycw3sidsR4ORr2aFDmXMSI3k+oeVY=
|
||||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
|
Loading…
Reference in New Issue