Skip to content

Commit e285033

Browse files
committed
Verify artifacts integrity
After downloading an artifact, compute its checksum and verify that it matches the original checksum advertised by source-controller. Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
1 parent 9e51c3a commit e285033

File tree

1 file changed

+34
-3
lines changed

1 file changed

+34
-3
lines changed

controllers/helmrelease_controller_chart.go

+34-3
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ limitations under the License.
1717
package controllers
1818

1919
import (
20+
"bytes"
2021
"context"
22+
"crypto/sha1"
23+
"crypto/sha256"
2124
"fmt"
2225
"io"
23-
"io/ioutil"
2426
"net/http"
2527
"net/url"
2628
"os"
@@ -94,7 +96,7 @@ func (r *HelmReleaseReconciler) getHelmChart(ctx context.Context, hr *v2.HelmRel
9496
// loads it into a chart.Chart, and removes the downloaded artifact.
9597
// It returns the loaded chart.Chart on success, or an error.
9698
func (r *HelmReleaseReconciler) loadHelmChart(source *sourcev1.HelmChart) (*chart.Chart, error) {
97-
f, err := ioutil.TempFile("", fmt.Sprintf("%s-%s-*.tgz", source.GetNamespace(), source.GetName()))
99+
f, err := os.CreateTemp("", fmt.Sprintf("%s-%s-*.tgz", source.GetNamespace(), source.GetName()))
98100
if err != nil {
99101
return nil, err
100102
}
@@ -126,13 +128,42 @@ func (r *HelmReleaseReconciler) loadHelmChart(source *sourcev1.HelmChart) (*char
126128
return nil, fmt.Errorf("artifact '%s' download failed (status code: %s)", source.GetArtifact().URL, resp.Status)
127129
}
128130

129-
if _, err = io.Copy(f, resp.Body); err != nil {
131+
var buf bytes.Buffer
132+
133+
// verify checksum matches origin
134+
if err := r.verifyArtifact(source.GetArtifact(), &buf, resp.Body); err != nil {
135+
return nil, err
136+
}
137+
138+
if _, err = io.Copy(f, &buf); err != nil {
130139
return nil, err
131140
}
132141

133142
return loader.Load(f.Name())
134143
}
135144

145+
func (r *HelmReleaseReconciler) verifyArtifact(artifact *sourcev1.Artifact, buf *bytes.Buffer, reader io.Reader) error {
146+
hasher := sha256.New()
147+
148+
// for backwards compatibility with source-controller v0.17.2 and older
149+
if len(artifact.Checksum) == 40 {
150+
hasher = sha1.New()
151+
}
152+
153+
// compute checksum
154+
mw := io.MultiWriter(hasher, buf)
155+
if _, err := io.Copy(mw, reader); err != nil {
156+
return err
157+
}
158+
159+
if checksum := fmt.Sprintf("%x", hasher.Sum(nil)); checksum != artifact.Checksum {
160+
return fmt.Errorf("failed to verify artifact: computed checksum '%s' doesn't match advertised '%s'",
161+
checksum, artifact.Checksum)
162+
}
163+
164+
return nil
165+
}
166+
136167
// deleteHelmChart deletes the v1beta1.HelmChart of the v2beta1.HelmRelease.
137168
func (r *HelmReleaseReconciler) deleteHelmChart(ctx context.Context, hr *v2.HelmRelease) error {
138169
if hr.Status.HelmChart == "" {

0 commit comments

Comments
 (0)