Skip to content

Commit 005988c

Browse files
feat: print hashes for imports in yaml format (#608)
For import types that will be checked, save the calculated hash of the downloaded file and print them together in the format of a yaml imports section for easy copy and pasting to add hashes to a file. Because we only the parse file contents after the substitution placeholders are replaced, this isn't a direct copy and paste replacement, but it is an improvement, and it should be easy enough to tell which expanded paths come from what input. Signed-off-by: Michael McCracken <mikmccra@cisco.com>
1 parent 98ca66e commit 005988c

File tree

3 files changed

+50
-31
lines changed

3 files changed

+50
-31
lines changed

pkg/stacker/base.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func GetBase(o BaseLayerOpts) error {
4040
return err
4141
}
4242

43-
_, err := acquireUrl(o.Config, o.Storage, o.Layer.From.Url, cacheDir, "", "", nil, -1, -1, o.Progress)
43+
_, _, err := acquireUrl(o.Config, o.Storage, o.Layer.From.Url, cacheDir, "", "", nil, -1, -1, o.Progress)
4444
return err
4545
/* now we can do all the containers/image types */
4646
case types.OCILayer:

pkg/stacker/import.go

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -72,22 +72,26 @@ func filesDiffer(p1 string, info1 os.FileInfo, p2 string, info2 os.FileInfo) (bo
7272
return !eq, nil
7373
}
7474

75-
func verifyImportFileHash(imp string, hash string) error {
76-
if len(hash) == 0 {
77-
return nil
78-
}
75+
// check that the file's hash matches the given hash.
76+
// If the given hash is "", that is treated as a match.
77+
// always return the actual hash.
78+
func verifyImportFileHash(imp string, hash string) (string, error) {
7979
actualHash, err := lib.HashFile(imp, false)
8080
if err != nil {
81-
return err
81+
return actualHash, err
8282
}
8383

8484
actualHash = strings.TrimPrefix(actualHash, "sha256:")
85+
if len(hash) == 0 {
86+
return actualHash, nil
87+
}
88+
8589
if actualHash != strings.ToLower(hash) {
86-
return errors.Errorf("The requested hash of %s import is different than the actual hash: %s != %s",
90+
return actualHash, errors.Errorf("The requested hash of %s import is different than the actual hash: %s != %s",
8791
imp, hash, actualHash)
8892
}
8993

90-
return nil
94+
return actualHash, nil
9195
}
9296

9397
func importFile(imp string, cacheDir string, hash string, idest string, mode *fs.FileMode, uid, gid int) (string, error) {
@@ -97,7 +101,7 @@ func importFile(imp string, cacheDir string, hash string, idest string, mode *fs
97101
}
98102

99103
if !e1.IsDir() {
100-
err := verifyImportFileHash(imp, hash)
104+
_, err := verifyImportFileHash(imp, hash)
101105
if err != nil {
102106
return "", err
103107
}
@@ -245,22 +249,25 @@ func validateHash(hash string) error {
245249
return nil
246250
}
247251

252+
// downloads or copies import url depending on scheme, and returns the path and
253+
// hash of the downloaded file
248254
func acquireUrl(c types.StackerConfig, storage types.Storage, i string, cache string, expectedHash string,
249255
idest string, mode *fs.FileMode, uid, gid int, progress bool,
250-
) (string, error) {
256+
) (string, string, error) {
251257
url, err := types.NewDockerishUrl(i)
252258
if err != nil {
253-
return "", err
259+
return "", "", err
254260
}
255261

256262
// validate the given hash
257263
if err = validateHash(expectedHash); err != nil {
258-
return "", err
264+
return "", "", err
259265
}
260266

261267
// It's just a path, let's copy it to .stacker.
262268
if url.Scheme == "" {
263-
return importFile(i, cache, expectedHash, idest, mode, uid, gid)
269+
path, err := importFile(i, cache, expectedHash, idest, mode, uid, gid)
270+
return path, "", err
264271
} else if url.Scheme == "http" || url.Scheme == "https" {
265272
// otherwise, we need to download it
266273
// first verify the hashes
@@ -273,10 +280,11 @@ func acquireUrl(c types.StackerConfig, storage types.Storage, i string, cache st
273280
log.Debugf("Remote file: hash: %s length: %s", remoteHash, remoteSize)
274281
// verify if the given hash from stackerfile matches the remote one.
275282
if len(expectedHash) > 0 && len(remoteHash) > 0 && strings.ToLower(expectedHash) != remoteHash {
276-
return "", errors.Errorf("The requested hash of %s import is different than the actual hash: %s != %s",
283+
return "", "", errors.Errorf("The requested hash of %s import is different than the actual hash: %s != %s",
277284
i, expectedHash, remoteHash)
278285
}
279-
return Download(cache, i, progress, expectedHash, remoteHash, remoteSize, idest, mode, uid, gid)
286+
path, err := Download(cache, i, progress, expectedHash, remoteHash, remoteSize, idest, mode, uid, gid)
287+
return path, remoteHash, err
280288
} else if url.Scheme == "stacker" {
281289
// we always Grab() things from stacker://, because we need to
282290
// mount the container's rootfs to get them and don't
@@ -285,23 +293,19 @@ func acquireUrl(c types.StackerConfig, storage types.Storage, i string, cache st
285293
p := path.Join(cache, path.Base(url.Path))
286294
snap, cleanup, err := storage.TemporaryWritableSnapshot(url.Host)
287295
if err != nil {
288-
return "", err
296+
return "", "", err
289297
}
290298
defer cleanup()
291299
err = Grab(c, storage, snap, url.Path, cache, idest, mode, uid, gid)
292300
if err != nil {
293-
return "", err
301+
return "", "", err
294302
}
295303

296-
err = verifyImportFileHash(p, expectedHash)
297-
if err != nil {
298-
return "", err
299-
}
300-
301-
return p, nil
304+
// return "" as the hash, it is not checked
305+
return p, "", nil
302306
}
303307

304-
return "", errors.Errorf("unsupported url scheme %s", i)
308+
return "", "", errors.Errorf("unsupported url scheme %s", i)
305309
}
306310

307311
func CleanImportsDir(c types.StackerConfig, name string, imports types.Imports, cache *BuildCache) error {
@@ -365,6 +369,7 @@ func Import(c types.StackerConfig, storage types.Storage, name string, imports t
365369
return errors.Wrapf(err, "couldn't read existing directory")
366370
}
367371

372+
importHashes := map[string]string{}
368373
for _, i := range imports {
369374
cache := dir
370375

@@ -387,11 +392,16 @@ func Import(c types.StackerConfig, storage types.Storage, name string, imports t
387392
cache = tmpdir
388393
}
389394

390-
name, err := acquireUrl(c, storage, i.Path, cache, i.Hash, i.Dest, i.Mode, i.Uid, i.Gid, progress)
395+
name, downloadedFileHash, err := acquireUrl(c, storage, i.Path, cache, i.Hash, i.Dest, i.Mode, i.Uid, i.Gid, progress)
391396
if err != nil {
392397
return err
393398
}
394399

400+
// "" is returned for local files, ignore they won't be checked anyway
401+
if downloadedFileHash != "" {
402+
importHashes[i.Path] = downloadedFileHash
403+
}
404+
395405
for i, ext := range existing {
396406
if ext.Name() == path.Base(name) {
397407
existing = append(existing[:i], existing[i+1:]...)
@@ -408,5 +418,10 @@ func Import(c types.StackerConfig, storage types.Storage, name string, imports t
408418
}
409419
}
410420

421+
log.Infof("imported file hashes (after substitutions):")
422+
for path, hash := range importHashes {
423+
log.Infof(" - path: %q\n hash: %q", path, hash)
424+
}
425+
411426
return nil
412427
}

pkg/stacker/network.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,17 +98,21 @@ func Download(cacheDir string, url string, progress bool, expectedHash, remoteHa
9898
if err != nil {
9999
return "", err
100100
}
101-
if expectedHash != "" {
102-
log.Infof("Checking shasum of downloaded file")
103101

104-
downloadHash, err := lib.HashFile(name, false)
105-
if err != nil {
106-
return "", err
107-
}
102+
downloadHash, err := lib.HashFile(name, false)
103+
if err != nil {
104+
return "", err
105+
}
108106

107+
if expectedHash != "" {
108+
log.Infof("Checking shasum of downloaded file")
109109
downloadHash = strings.TrimPrefix(downloadHash, "sha256:")
110110
log.Debugf("Downloaded file hash: %s", downloadHash)
111111

112+
if downloadHash != remoteHash {
113+
log.Warnf("Downloaded file hash %q does not match hash from HTTP header %q", downloadHash, remoteHash)
114+
}
115+
112116
if expectedHash != downloadHash {
113117
os.RemoveAll(name)
114118
return "", errors.Errorf("Downloaded file hash does not match. Expected: %s Actual: %s", expectedHash, downloadHash)

0 commit comments

Comments
 (0)