Merge pull request #1156 from RichardScothern/manifest-verification
Manifest Verification
This commit is contained in:
commit
362ae9cc41
5 changed files with 76 additions and 12 deletions
|
@ -11,7 +11,7 @@ import (
|
||||||
|
|
||||||
type testEnv struct {
|
type testEnv struct {
|
||||||
name, tag string
|
name, tag string
|
||||||
manifest *Manifest
|
invalidSigned *SignedManifest
|
||||||
signed *SignedManifest
|
signed *SignedManifest
|
||||||
pk libtrust.PrivateKey
|
pk libtrust.PrivateKey
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ func TestManifestUnmarshaling(t *testing.T) {
|
||||||
if !reflect.DeepEqual(&signed, env.signed) {
|
if !reflect.DeepEqual(&signed, env.signed) {
|
||||||
t.Fatalf("manifests are different after unmarshaling: %v != %v", signed, env.signed)
|
t.Fatalf("manifests are different after unmarshaling: %v != %v", signed, env.signed)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestManifestVerification(t *testing.T) {
|
func TestManifestVerification(t *testing.T) {
|
||||||
|
@ -69,6 +70,12 @@ func TestManifestVerification(t *testing.T) {
|
||||||
if !found {
|
if !found {
|
||||||
t.Fatalf("expected public key, %v, not found in verified keys: %v", publicKey, publicKeys)
|
t.Fatalf("expected public key, %v, not found in verified keys: %v", publicKey, publicKeys)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that an invalid manifest fails verification
|
||||||
|
_, err = Verify(env.invalidSigned)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Invalid manifest should not pass Verify()")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func genEnv(t *testing.T) *testEnv {
|
func genEnv(t *testing.T) *testEnv {
|
||||||
|
@ -79,7 +86,7 @@ func genEnv(t *testing.T) *testEnv {
|
||||||
|
|
||||||
name, tag := "foo/bar", "test"
|
name, tag := "foo/bar", "test"
|
||||||
|
|
||||||
m := Manifest{
|
invalid := Manifest{
|
||||||
Versioned: SchemaVersion,
|
Versioned: SchemaVersion,
|
||||||
Name: name,
|
Name: name,
|
||||||
Tag: tag,
|
Tag: tag,
|
||||||
|
@ -93,7 +100,28 @@ func genEnv(t *testing.T) *testEnv {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
sm, err := Sign(&m, pk)
|
valid := Manifest{
|
||||||
|
Versioned: SchemaVersion,
|
||||||
|
Name: name,
|
||||||
|
Tag: tag,
|
||||||
|
FSLayers: []FSLayer{
|
||||||
|
{
|
||||||
|
BlobSum: "asdf",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
History: []History{
|
||||||
|
{
|
||||||
|
V1Compatibility: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
sm, err := Sign(&valid, pk)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error signing manifest: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
invalidSigned, err := Sign(&invalid, pk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error signing manifest: %v", err)
|
t.Fatalf("error signing manifest: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -101,7 +129,7 @@ func genEnv(t *testing.T) *testEnv {
|
||||||
return &testEnv{
|
return &testEnv{
|
||||||
name: name,
|
name: name,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
manifest: &m,
|
invalidSigned: invalidSigned,
|
||||||
signed: sm,
|
signed: sm,
|
||||||
pk: pk,
|
pk: pk,
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,6 +131,9 @@ func checkExerciseRepository(t *testing.T, repository distribution.Repository) {
|
||||||
m.FSLayers = append(m.FSLayers, schema1.FSLayer{
|
m.FSLayers = append(m.FSLayers, schema1.FSLayer{
|
||||||
BlobSum: dgst,
|
BlobSum: dgst,
|
||||||
})
|
})
|
||||||
|
m.History = append(m.History, schema1.History{
|
||||||
|
V1Compatibility: "",
|
||||||
|
})
|
||||||
|
|
||||||
// Then fetch the blobs
|
// Then fetch the blobs
|
||||||
if rc, err := blobs.Open(ctx, dgst); err != nil {
|
if rc, err := blobs.Open(ctx, dgst); err != nil {
|
||||||
|
|
|
@ -804,6 +804,14 @@ func testManifestAPI(t *testing.T, env *testEnv, args manifestArgs) (*testEnv, m
|
||||||
BlobSum: "qwer",
|
BlobSum: "qwer",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
History: []schema1.History{
|
||||||
|
{
|
||||||
|
V1Compatibility: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
V1Compatibility: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
resp = putManifest(t, "putting unsigned manifest", manifestURL, unsignedManifest)
|
resp = putManifest(t, "putting unsigned manifest", manifestURL, unsignedManifest)
|
||||||
|
@ -999,6 +1007,19 @@ func testManifestAPI(t *testing.T, env *testEnv, args manifestArgs) (*testEnv, m
|
||||||
t.Fatalf("tag not as expected: %q != %q", tagsResponse.Tags[0], tag)
|
t.Fatalf("tag not as expected: %q != %q", tagsResponse.Tags[0], tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Attempt to put a manifest with mismatching FSLayer and History array cardinalities
|
||||||
|
|
||||||
|
unsignedManifest.History = append(unsignedManifest.History, schema1.History{
|
||||||
|
V1Compatibility: "",
|
||||||
|
})
|
||||||
|
invalidSigned, err := schema1.Sign(unsignedManifest, env.pk)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error signing manifest")
|
||||||
|
}
|
||||||
|
|
||||||
|
resp = putManifest(t, "putting invalid signed manifest", manifestDigestURL, invalidSigned)
|
||||||
|
checkResponse(t, "putting invalid signed manifest", resp, http.StatusBadRequest)
|
||||||
|
|
||||||
return env, args
|
return env, args
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1432,8 +1453,10 @@ func createRepository(env *testEnv, t *testing.T, imageName string, tag string)
|
||||||
{
|
{
|
||||||
BlobSum: "asdf",
|
BlobSum: "asdf",
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
History: []schema1.History{
|
||||||
{
|
{
|
||||||
BlobSum: "qwer",
|
V1Compatibility: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1499,6 +1522,7 @@ func TestRegistryAsCacheMutationAPIs(t *testing.T) {
|
||||||
Name: imageName,
|
Name: imageName,
|
||||||
Tag: tag,
|
Tag: tag,
|
||||||
FSLayers: []schema1.FSLayer{},
|
FSLayers: []schema1.FSLayer{},
|
||||||
|
History: []schema1.History{},
|
||||||
}
|
}
|
||||||
|
|
||||||
sm, err := schema1.Sign(m, env.pk)
|
sm, err := schema1.Sign(m, env.pk)
|
||||||
|
|
|
@ -110,6 +110,11 @@ func (ms *manifestStore) verifyManifest(ctx context.Context, mnfst *schema1.Sign
|
||||||
errs = append(errs, fmt.Errorf("repository name does not match manifest name"))
|
errs = append(errs, fmt.Errorf("repository name does not match manifest name"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(mnfst.History) != len(mnfst.FSLayers) {
|
||||||
|
errs = append(errs, fmt.Errorf("mismatched history and fslayer cardinality %d != %d",
|
||||||
|
len(mnfst.History), len(mnfst.FSLayers)))
|
||||||
|
}
|
||||||
|
|
||||||
if _, err := schema1.Verify(mnfst); err != nil {
|
if _, err := schema1.Verify(mnfst); err != nil {
|
||||||
switch err {
|
switch err {
|
||||||
case libtrust.ErrMissingSignatureKey, libtrust.ErrInvalidJSONContent, libtrust.ErrMissingSignatureKey:
|
case libtrust.ErrMissingSignatureKey, libtrust.ErrInvalidJSONContent, libtrust.ErrMissingSignatureKey:
|
||||||
|
|
|
@ -98,6 +98,10 @@ func TestManifestStorage(t *testing.T) {
|
||||||
m.FSLayers = append(m.FSLayers, schema1.FSLayer{
|
m.FSLayers = append(m.FSLayers, schema1.FSLayer{
|
||||||
BlobSum: dgst,
|
BlobSum: dgst,
|
||||||
})
|
})
|
||||||
|
m.History = append(m.History, schema1.History{
|
||||||
|
V1Compatibility: "",
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pk, err := libtrust.GenerateECP256PrivateKey()
|
pk, err := libtrust.GenerateECP256PrivateKey()
|
||||||
|
|
Loading…
Add table
Reference in a new issue