@@ -18,9 +18,10 @@ package controllers
18
18
19
19
import (
20
20
"context"
21
+ "crypto/sha1"
22
+ "crypto/sha256"
21
23
"fmt"
22
24
"io"
23
- "io/ioutil"
24
25
"net/http"
25
26
"net/url"
26
27
"os"
@@ -94,7 +95,7 @@ func (r *HelmReleaseReconciler) getHelmChart(ctx context.Context, hr *v2.HelmRel
94
95
// loads it into a chart.Chart, and removes the downloaded artifact.
95
96
// It returns the loaded chart.Chart on success, or an error.
96
97
func (r * HelmReleaseReconciler ) loadHelmChart (source * sourcev1.HelmChart ) (* chart.Chart , error ) {
97
- f , err := ioutil . TempFile ("" , fmt .Sprintf ("%s-%s-*.tgz" , source .GetNamespace (), source .GetName ()))
98
+ f , err := os . CreateTemp ("" , fmt .Sprintf ("%s-%s-*.tgz" , source .GetNamespace (), source .GetName ()))
98
99
if err != nil {
99
100
return nil , err
100
101
}
@@ -126,13 +127,36 @@ func (r *HelmReleaseReconciler) loadHelmChart(source *sourcev1.HelmChart) (*char
126
127
return nil , fmt .Errorf ("artifact '%s' download failed (status code: %s)" , source .GetArtifact ().URL , resp .Status )
127
128
}
128
129
129
- if _ , err = io .Copy (f , resp .Body ); err != nil {
130
+ // verify checksum matches origin
131
+ if err := r .copyAndVerifyArtifact (source .GetArtifact (), resp .Body , f ); err != nil {
130
132
return nil , err
131
133
}
132
134
133
135
return loader .Load (f .Name ())
134
136
}
135
137
138
+ func (r * HelmReleaseReconciler ) copyAndVerifyArtifact (artifact * sourcev1.Artifact , reader io.Reader , writer io.Writer ) error {
139
+ hasher := sha256 .New ()
140
+
141
+ // for backwards compatibility with source-controller v0.17.2 and older
142
+ if len (artifact .Checksum ) == 40 {
143
+ hasher = sha1 .New ()
144
+ }
145
+
146
+ // compute checksum
147
+ mw := io .MultiWriter (hasher , writer )
148
+ if _ , err := io .Copy (mw , reader ); err != nil {
149
+ return err
150
+ }
151
+
152
+ if checksum := fmt .Sprintf ("%x" , hasher .Sum (nil )); checksum != artifact .Checksum {
153
+ return fmt .Errorf ("failed to verify artifact: computed checksum '%s' doesn't match advertised '%s'" ,
154
+ checksum , artifact .Checksum )
155
+ }
156
+
157
+ return nil
158
+ }
159
+
136
160
// deleteHelmChart deletes the v1beta1.HelmChart of the v2beta1.HelmRelease.
137
161
func (r * HelmReleaseReconciler ) deleteHelmChart (ctx context.Context , hr * v2.HelmRelease ) error {
138
162
if hr .Status .HelmChart == "" {
0 commit comments