Skip to content

Commit 459984c

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 459984c

File tree

1 file changed

+27
-3
lines changed

1 file changed

+27
-3
lines changed

controllers/helmrelease_controller_chart.go

+27-3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ package controllers
1818

1919
import (
2020
"context"
21+
"crypto/sha1"
22+
"crypto/sha256"
2123
"fmt"
2224
"io"
23-
"io/ioutil"
2425
"net/http"
2526
"net/url"
2627
"os"
@@ -94,7 +95,7 @@ func (r *HelmReleaseReconciler) getHelmChart(ctx context.Context, hr *v2.HelmRel
9495
// loads it into a chart.Chart, and removes the downloaded artifact.
9596
// It returns the loaded chart.Chart on success, or an error.
9697
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()))
9899
if err != nil {
99100
return nil, err
100101
}
@@ -126,13 +127,36 @@ func (r *HelmReleaseReconciler) loadHelmChart(source *sourcev1.HelmChart) (*char
126127
return nil, fmt.Errorf("artifact '%s' download failed (status code: %s)", source.GetArtifact().URL, resp.Status)
127128
}
128129

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 {
130132
return nil, err
131133
}
132134

133135
return loader.Load(f.Name())
134136
}
135137

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+
136160
// deleteHelmChart deletes the v1beta1.HelmChart of the v2beta1.HelmRelease.
137161
func (r *HelmReleaseReconciler) deleteHelmChart(ctx context.Context, hr *v2.HelmRelease) error {
138162
if hr.Status.HelmChart == "" {

0 commit comments

Comments
 (0)