From 14fb80d6c3e3dcc80db00816cab173acd70b6ab1 Mon Sep 17 00:00:00 2001 From: Stephen J Day Date: Wed, 28 Jan 2015 14:54:09 -0800 Subject: [PATCH] Add payload and signatures method to SignedManifest To provide easier access to digestible content, the paylaod has been made accessible on the signed manifest type. This hides the specifics of the interaction with libtrust with the caveat that signatures may be parsed twice. We'll have to have a future look at the interface for manifest as we may be making problematic architectural decisions. We'll visit this after the initial release. Signed-off-by: Stephen J Day --- manifest/manifest.go | 26 ++++++++++++++++++++++++++ storage/manifeststore.go | 5 +++++ storage/revisionstore.go | 9 ++------- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/manifest/manifest.go b/manifest/manifest.go index ad3ecd00..8ea4d14d 100644 --- a/manifest/manifest.go +++ b/manifest/manifest.go @@ -4,6 +4,7 @@ import ( "encoding/json" "github.com/docker/distribution/digest" + "github.com/docker/libtrust" ) // Versioned provides a struct with just the manifest schemaVersion. Incoming @@ -62,6 +63,31 @@ func (sm *SignedManifest) UnmarshalJSON(b []byte) error { return nil } +// Payload returns the raw, signed content of the signed manifest. The +// contents can be used to calculate the content identifier. +func (sm *SignedManifest) Payload() ([]byte, error) { + jsig, err := libtrust.ParsePrettySignature(sm.Raw, "signatures") + if err != nil { + return nil, err + } + + // Resolve the payload in the manifest. + return jsig.Payload() +} + +// Signatures returns the signatures as provided by +// (*libtrust.JSONSignature).Signatures. The byte slices are opaque jws +// signatures. +func (sm *SignedManifest) Signatures() ([][]byte, error) { + jsig, err := libtrust.ParsePrettySignature(sm.Raw, "signatures") + if err != nil { + return nil, err + } + + // Resolve the payload in the manifest. + return jsig.Signatures() +} + // MarshalJSON returns the contents of raw. If Raw is nil, marshals the inner // contents. Applications requiring a marshaled signed manifest should simply // use Raw directly, since the the content produced by json.Marshal will be diff --git a/storage/manifeststore.go b/storage/manifeststore.go index bc28f3b8..f84a0208 100644 --- a/storage/manifeststore.go +++ b/storage/manifeststore.go @@ -94,6 +94,11 @@ func (ms *manifestStore) Get(tag string) (*manifest.SignedManifest, error) { } func (ms *manifestStore) Put(tag string, manifest *manifest.SignedManifest) error { + // TODO(stevvooe): Add check here to see if the revision is already + // present in the repository. If it is, we should merge the signatures, do + // a shallow verify (or a full one, doesn't matter) and return an error + // indicating what happened. + // Verify the manifest. if err := ms.verifyManifest(tag, manifest); err != nil { return err diff --git a/storage/revisionstore.go b/storage/revisionstore.go index a88ca8c7..b3ecd711 100644 --- a/storage/revisionstore.go +++ b/storage/revisionstore.go @@ -79,13 +79,8 @@ func (rs *revisionStore) get(revision digest.Digest) (*manifest.SignedManifest, // put stores the manifest in the repository, if not already present. Any // updated signatures will be stored, as well. func (rs *revisionStore) put(sm *manifest.SignedManifest) (digest.Digest, error) { - jsig, err := libtrust.ParsePrettySignature(sm.Raw, "signatures") - if err != nil { - return "", err - } - // Resolve the payload in the manifest. - payload, err := jsig.Payload() + payload, err := sm.Payload() if err != nil { return "", err } @@ -103,7 +98,7 @@ func (rs *revisionStore) put(sm *manifest.SignedManifest) (digest.Digest, error) } // Grab each json signature and store them. - signatures, err := jsig.Signatures() + signatures, err := sm.Signatures() if err != nil { return "", err }