1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Merge pull request #20164 from tonistiigi/verify-tarsteam-on-creation

Verify layer tarstream
This commit is contained in:
Tibor Vass 2016-02-09 21:07:41 -05:00
commit c4756a0c36
4 changed files with 126 additions and 14 deletions

View file

@ -6,6 +6,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
"github.com/docker/distribution/digest"
@ -56,7 +57,7 @@ func newTestGraphDriver(t *testing.T) (graphdriver.Driver, func()) {
}
}
func newTestStore(t *testing.T) (Store, func()) {
func newTestStore(t *testing.T) (Store, string, func()) {
td, err := ioutil.TempDir("", "layerstore-")
if err != nil {
t.Fatal(err)
@ -72,7 +73,7 @@ func newTestStore(t *testing.T) (Store, func()) {
t.Fatal(err)
}
return ls, func() {
return ls, td, func() {
graphcleanup()
os.RemoveAll(td)
}
@ -265,7 +266,7 @@ func assertLayerEqual(t *testing.T, l1, l2 Layer) {
}
func TestMountAndRegister(t *testing.T) {
ls, cleanup := newTestStore(t)
ls, _, cleanup := newTestStore(t)
defer cleanup()
li := initWithFiles(newTestFile("testfile.txt", []byte("some test data"), 0644))
@ -306,7 +307,7 @@ func TestMountAndRegister(t *testing.T) {
}
func TestLayerRelease(t *testing.T) {
ls, cleanup := newTestStore(t)
ls, _, cleanup := newTestStore(t)
defer cleanup()
layer1, err := createLayer(ls, "", initWithFiles(newTestFile("layer1.txt", []byte("layer 1 file"), 0644)))
@ -351,7 +352,7 @@ func TestLayerRelease(t *testing.T) {
}
func TestStoreRestore(t *testing.T) {
ls, cleanup := newTestStore(t)
ls, _, cleanup := newTestStore(t)
defer cleanup()
layer1, err := createLayer(ls, "", initWithFiles(newTestFile("layer1.txt", []byte("layer 1 file"), 0644)))
@ -472,7 +473,7 @@ func TestStoreRestore(t *testing.T) {
}
func TestTarStreamStability(t *testing.T) {
ls, cleanup := newTestStore(t)
ls, _, cleanup := newTestStore(t)
defer cleanup()
files1 := []FileApplier{
@ -668,7 +669,7 @@ func assertActivityCount(t *testing.T, l RWLayer, expected int) {
}
func TestRegisterExistingLayer(t *testing.T) {
ls, cleanup := newTestStore(t)
ls, _, cleanup := newTestStore(t)
defer cleanup()
baseFiles := []FileApplier{
@ -713,7 +714,7 @@ func graphDiffSize(ls Store, l Layer) (int64, error) {
}
func TestLayerSize(t *testing.T) {
ls, cleanup := newTestStore(t)
ls, _, cleanup := newTestStore(t)
defer cleanup()
content1 := []byte("Base contents")
@ -765,3 +766,69 @@ func TestLayerSize(t *testing.T) {
t.Fatalf("Unexpected size %d, expected %d", layer2Size, expected)
}
}
func TestTarStreamVerification(t *testing.T) {
ls, tmpdir, cleanup := newTestStore(t)
defer cleanup()
files1 := []FileApplier{
newTestFile("/foo", []byte("abc"), 0644),
newTestFile("/bar", []byte("def"), 0644),
}
files2 := []FileApplier{
newTestFile("/foo", []byte("abc"), 0644),
newTestFile("/bar", []byte("def"), 0600), // different perm
}
tar1, err := tarFromFiles(files1...)
if err != nil {
t.Fatal(err)
}
tar2, err := tarFromFiles(files2...)
if err != nil {
t.Fatal(err)
}
layer1, err := ls.Register(bytes.NewReader(tar1), "")
if err != nil {
t.Fatal(err)
}
layer2, err := ls.Register(bytes.NewReader(tar2), "")
if err != nil {
t.Fatal(err)
}
id1 := digest.Digest(layer1.ChainID())
id2 := digest.Digest(layer2.ChainID())
// Replace tar data files
src, err := os.Open(filepath.Join(tmpdir, id1.Algorithm().String(), id1.Hex(), "tar-split.json.gz"))
if err != nil {
t.Fatal(err)
}
dst, err := os.Create(filepath.Join(tmpdir, id2.Algorithm().String(), id2.Hex(), "tar-split.json.gz"))
if err != nil {
t.Fatal(err)
}
if _, err := io.Copy(dst, src); err != nil {
t.Fatal(err)
}
src.Close()
dst.Close()
ts, err := layer2.TarStream()
if err != nil {
t.Fatal(err)
}
_, err = io.Copy(ioutil.Discard, ts)
if err == nil {
t.Fatal("expected data verification to fail")
}
if !strings.Contains(err.Error(), "could not verify layer data") {
t.Fatalf("wrong error returned from tarstream: %q", err)
}
}

View file

@ -268,7 +268,7 @@ func TestLayerMigrationNoTarsplit(t *testing.T) {
}
func TestMountMigration(t *testing.T) {
ls, cleanup := newTestStore(t)
ls, _, cleanup := newTestStore(t)
defer cleanup()
baseFiles := []FileApplier{

View file

@ -11,7 +11,7 @@ import (
)
func TestMountInit(t *testing.T) {
ls, cleanup := newTestStore(t)
ls, _, cleanup := newTestStore(t)
defer cleanup()
basefile := newTestFile("testfile.txt", []byte("base data!"), 0644)
@ -63,7 +63,7 @@ func TestMountInit(t *testing.T) {
}
func TestMountSize(t *testing.T) {
ls, cleanup := newTestStore(t)
ls, _, cleanup := newTestStore(t)
defer cleanup()
content1 := []byte("Base contents")
@ -105,7 +105,7 @@ func TestMountSize(t *testing.T) {
}
func TestMountChanges(t *testing.T) {
ls, cleanup := newTestStore(t)
ls, _, cleanup := newTestStore(t)
defer cleanup()
basefiles := []FileApplier{

View file

@ -1,6 +1,11 @@
package layer
import "io"
import (
"fmt"
"io"
"github.com/docker/distribution/digest"
)
type roLayer struct {
chainID ChainID
@ -29,7 +34,11 @@ func (rl *roLayer) TarStream() (io.ReadCloser, error) {
pw.Close()
}
}()
return pr, nil
rc, err := newVerifiedReadCloser(pr, digest.Digest(rl.diffID))
if err != nil {
return nil, err
}
return rc, nil
}
func (rl *roLayer) ChainID() ChainID {
@ -117,3 +126,39 @@ func storeLayer(tx MetadataTransaction, layer *roLayer) error {
return nil
}
func newVerifiedReadCloser(rc io.ReadCloser, dgst digest.Digest) (io.ReadCloser, error) {
verifier, err := digest.NewDigestVerifier(dgst)
if err != nil {
return nil, err
}
return &verifiedReadCloser{
rc: rc,
dgst: dgst,
verifier: verifier,
}, nil
}
type verifiedReadCloser struct {
rc io.ReadCloser
dgst digest.Digest
verifier digest.Verifier
}
func (vrc *verifiedReadCloser) Read(p []byte) (n int, err error) {
n, err = vrc.rc.Read(p)
if n > 0 {
if n, err := vrc.verifier.Write(p[:n]); err != nil {
return n, err
}
}
if err == io.EOF {
if !vrc.verifier.Verified() {
err = fmt.Errorf("could not verify layer data for: %s. This may be because internal files in the layer store were modified. Re-pulling or rebuilding this image may resolve the issue", vrc.dgst)
}
}
return
}
func (vrc *verifiedReadCloser) Close() error {
return vrc.rc.Close()
}