Add (skopeo manifest-digest)

A plain sha256sum and the like is insufficient because we need to strip
signatures from v2s1 manifests; so, add a subcommand.

This can be used together with (skopeo inspect --raw) to download a
manifest from a source untrusted to modify it under us; we download a
manifest once using (skopeo inspect --raw), compute a digest using
(skopeo manifest-digest), and then do all future operations using a
digest reference.
This commit is contained in:
Miloslav Trmač 2016-08-16 18:06:33 +02:00
parent e4315e82b0
commit c236b29c75
5 changed files with 88 additions and 0 deletions

View File

@ -0,0 +1,11 @@
{
"schemaVersion": 1,
"name": "mitr/buxybox",
"tag": "latest",
"architecture": "amd64",
"fsLayers": [
],
"history": [
],
"signatures": 1
}

View File

@ -61,6 +61,7 @@ func createApp() *cli.App {
inspectCmd,
layersCmd,
deleteCmd,
manifestDigestCmd,
standaloneSignCmd,
standaloneVerifyCmd,
}

35
cmd/skopeo/manifest.go Normal file
View File

@ -0,0 +1,35 @@
package main
import (
"errors"
"fmt"
"io/ioutil"
"github.com/containers/image/manifest"
"github.com/urfave/cli"
)
func manifestDigest(context *cli.Context) error {
if len(context.Args()) != 1 {
return errors.New("Usage: skopeo manifest-digest manifest")
}
manifestPath := context.Args()[0]
man, err := ioutil.ReadFile(manifestPath)
if err != nil {
return fmt.Errorf("Error reading manifest from %s: %v", manifestPath, err)
}
digest, err := manifest.Digest(man)
if err != nil {
return fmt.Errorf("Error computing digest: %v", err)
}
fmt.Fprintf(context.App.Writer, "%s\n", digest)
return nil
}
var manifestDigestCmd = cli.Command{
Name: "manifest-digest",
Usage: "Compute a manifest digest of a file",
ArgsUsage: "MANIFEST",
Action: manifestDigest,
}

View File

@ -0,0 +1,31 @@
package main
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestManifestDigest(t *testing.T) {
// Invalid command-line arguments
for _, args := range [][]string{
{},
{"a1", "a2"},
} {
out, err := runSkopeo(append([]string{"manifest-digest"}, args...)...)
assertTestFailed(t, out, err, "Usage")
}
// Error reading manifest
out, err := runSkopeo("manifest-digest", "/this/doesnt/exist")
assertTestFailed(t, out, err, "/this/doesnt/exist")
// Error computing manifest
out, err = runSkopeo("manifest-digest", "fixtures/v2s1-invalid-signatures.manifest.json")
assertTestFailed(t, out, err, "computing digest")
// Success
out, err = runSkopeo("manifest-digest", "fixtures/image.manifest.json")
assert.NoError(t, err)
assert.Equal(t, fixturesTestImageManifestDigest+"\n", out)
}

View File

@ -91,6 +91,11 @@ Get image layers of _image-name_
_image-name_ name of the image to retrieve layers
## skopeo manifest-digest
**skopeo manifest-digest** _manifest-file_
Compute a manifest digest of _manifest-file_ and write it to standard output.
## skopeo standalone-sign
**skopeo standalone-sign** _manifest docker-reference key-fingerprint_ **--output**|**-o** _signature_
@ -184,6 +189,11 @@ $ ls layers-500650331/
manifest.json
a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4.tar
```
## skopeo manifest-digest
```sh
$ skopeo manifest-digest manifest.json
sha256:a59906e33509d14c036c8678d687bd4eec81ed7c4b8ce907b888c607f6a1e0e6
```
## skopeo standalone-sign
```sh
$ skopeo standalone-sign busybox-manifest.json registry.example.com/example/busybox 1D8230F6CDB6A06716E414C1DB72F2188BB46CC8 --output busybox.signature