Skip to content

Commit 697a587

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 697a587

File tree

1 file changed

+33
-3
lines changed

1 file changed

+33
-3
lines changed

controllers/helmrelease_controller_chart.go

+33-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,41 @@ 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+
if _, err = io.Copy(f, &buf); err != nil {
133+
return nil, err
134+
}
135+
136+
// verify checksum matches origin
137+
if err := r.verifyArtifact(source.GetArtifact(), f, resp.Body); err != nil {
130138
return nil, err
131139
}
132140

133141
return loader.Load(f.Name())
134142
}
135143

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

0 commit comments

Comments
 (0)