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 }