Correct unmarshal order for SignedManifest
To ensure that we only unmarshal the verified payload into the contained manifest, we first copy the entire incoming buffer into Raw and then unmarshal only the Payload portion of the incoming bytes. If the contents is later verified, the caller can then be sure that the contents of the Manifest fields can be trusted. Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
This commit is contained in:
parent
da206d64cb
commit
26762a54fe
3 changed files with 68 additions and 37 deletions
|
@ -3,7 +3,6 @@ package client
|
|||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
|
@ -14,8 +13,6 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/distribution/uuid"
|
||||
|
||||
"github.com/docker/distribution"
|
||||
"github.com/docker/distribution/context"
|
||||
"github.com/docker/distribution/digest"
|
||||
|
@ -23,6 +20,8 @@ import (
|
|||
"github.com/docker/distribution/manifest/schema1"
|
||||
"github.com/docker/distribution/registry/api/errcode"
|
||||
"github.com/docker/distribution/testutil"
|
||||
"github.com/docker/distribution/uuid"
|
||||
"github.com/docker/libtrust"
|
||||
)
|
||||
|
||||
func testServer(rrm testutil.RequestResponseMap) (string, func()) {
|
||||
|
@ -420,7 +419,7 @@ func TestBlobUploadMonolithic(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func newRandomSchemaV1Manifest(name, tag string, blobCount int) (*schema1.SignedManifest, digest.Digest) {
|
||||
func newRandomSchemaV1Manifest(name, tag string, blobCount int) (*schema1.SignedManifest, digest.Digest, []byte) {
|
||||
blobs := make([]schema1.FSLayer, blobCount)
|
||||
history := make([]schema1.History, blobCount)
|
||||
|
||||
|
@ -431,30 +430,38 @@ func newRandomSchemaV1Manifest(name, tag string, blobCount int) (*schema1.Signed
|
|||
history[i] = schema1.History{V1Compatibility: fmt.Sprintf("{\"Hex\": \"%x\"}", blob)}
|
||||
}
|
||||
|
||||
m := &schema1.SignedManifest{
|
||||
Manifest: schema1.Manifest{
|
||||
Name: name,
|
||||
Tag: tag,
|
||||
Architecture: "x86",
|
||||
FSLayers: blobs,
|
||||
History: history,
|
||||
Versioned: manifest.Versioned{
|
||||
SchemaVersion: 1,
|
||||
},
|
||||
m := schema1.Manifest{
|
||||
Name: name,
|
||||
Tag: tag,
|
||||
Architecture: "x86",
|
||||
FSLayers: blobs,
|
||||
History: history,
|
||||
Versioned: manifest.Versioned{
|
||||
SchemaVersion: 1,
|
||||
},
|
||||
}
|
||||
manifestBytes, err := json.Marshal(m)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
dgst, err := digest.FromBytes(manifestBytes)
|
||||
|
||||
pk, err := libtrust.GenerateECP256PrivateKey()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
m.Raw = manifestBytes
|
||||
sm, err := schema1.Sign(&m, pk)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return m, dgst
|
||||
p, err := sm.Payload()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
dgst, err := digest.FromBytes(p)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return sm, dgst, p
|
||||
}
|
||||
|
||||
func addTestManifestWithEtag(repo, reference string, content []byte, m *testutil.RequestResponseMap, dgst string) {
|
||||
|
@ -551,7 +558,7 @@ func checkEqualManifest(m1, m2 *schema1.SignedManifest) error {
|
|||
func TestManifestFetch(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
repo := "test.example.com/repo"
|
||||
m1, dgst := newRandomSchemaV1Manifest(repo, "latest", 6)
|
||||
m1, dgst, _ := newRandomSchemaV1Manifest(repo, "latest", 6)
|
||||
var m testutil.RequestResponseMap
|
||||
addTestManifest(repo, dgst.String(), m1.Raw, &m)
|
||||
|
||||
|
@ -586,9 +593,9 @@ func TestManifestFetch(t *testing.T) {
|
|||
|
||||
func TestManifestFetchWithEtag(t *testing.T) {
|
||||
repo := "test.example.com/repo/by/tag"
|
||||
m1, d1 := newRandomSchemaV1Manifest(repo, "latest", 6)
|
||||
_, d1, p1 := newRandomSchemaV1Manifest(repo, "latest", 6)
|
||||
var m testutil.RequestResponseMap
|
||||
addTestManifestWithEtag(repo, "latest", m1.Raw, &m, d1.String())
|
||||
addTestManifestWithEtag(repo, "latest", p1, &m, d1.String())
|
||||
|
||||
e, c := testServer(m)
|
||||
defer c()
|
||||
|
@ -611,8 +618,8 @@ func TestManifestFetchWithEtag(t *testing.T) {
|
|||
|
||||
func TestManifestDelete(t *testing.T) {
|
||||
repo := "test.example.com/repo/delete"
|
||||
_, dgst1 := newRandomSchemaV1Manifest(repo, "latest", 6)
|
||||
_, dgst2 := newRandomSchemaV1Manifest(repo, "latest", 6)
|
||||
_, dgst1, _ := newRandomSchemaV1Manifest(repo, "latest", 6)
|
||||
_, dgst2, _ := newRandomSchemaV1Manifest(repo, "latest", 6)
|
||||
var m testutil.RequestResponseMap
|
||||
m = append(m, testutil.RequestResponseMapping{
|
||||
Request: testutil.Request{
|
||||
|
@ -651,7 +658,7 @@ func TestManifestDelete(t *testing.T) {
|
|||
|
||||
func TestManifestPut(t *testing.T) {
|
||||
repo := "test.example.com/repo/delete"
|
||||
m1, dgst := newRandomSchemaV1Manifest(repo, "other", 6)
|
||||
m1, dgst, _ := newRandomSchemaV1Manifest(repo, "other", 6)
|
||||
var m testutil.RequestResponseMap
|
||||
m = append(m, testutil.RequestResponseMapping{
|
||||
Request: testutil.Request{
|
||||
|
@ -744,7 +751,7 @@ func TestManifestTags(t *testing.T) {
|
|||
|
||||
func TestManifestUnauthorized(t *testing.T) {
|
||||
repo := "test.example.com/repo"
|
||||
_, dgst := newRandomSchemaV1Manifest(repo, "latest", 6)
|
||||
_, dgst, _ := newRandomSchemaV1Manifest(repo, "latest", 6)
|
||||
var m testutil.RequestResponseMap
|
||||
|
||||
m = append(m, testutil.RequestResponseMapping{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue