mirror of https://github.com/docker/docs.git
Refactor tests to cover corrupt root/targets/delegations.
Signed-off-by: Ying Li <ying.li@docker.com>
This commit is contained in:
parent
ab97f9e12e
commit
ebac6b158a
|
|
@ -1326,31 +1326,95 @@ func testPublishNoOneHasSnapshotKey(t *testing.T, rootType string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the snapshot metadata is corrupt or the snapshot metadata is unreadable,
|
// If the snapshot metadata is corrupt or the snapshot metadata is unreadable,
|
||||||
// whether the client or server has the snapshot key, we can't publish.
|
// we can't publish for the first time (whether the client or server has the
|
||||||
|
// snapshot key), because there is no existing data for us to download. If the
|
||||||
|
// repo has already been published, it doesn't matter if the metadata is corrupt
|
||||||
|
// because we can just redownload if it is.
|
||||||
func TestPublishSnapshotCorrupt(t *testing.T) {
|
func TestPublishSnapshotCorrupt(t *testing.T) {
|
||||||
testPublishBadMetadataAfterInit(t, data.CanonicalSnapshotRole, true)
|
ts := fullTestServer(t)
|
||||||
testPublishBadMetadataAfterInit(t, data.CanonicalSnapshotRole, false)
|
defer ts.Close()
|
||||||
|
|
||||||
|
// do not publish first - publish should fail
|
||||||
|
repo, _ := initializeRepo(t, data.ECDSAKey, "docker.com/notary1", ts.URL, true)
|
||||||
|
defer os.RemoveAll(repo.baseDir)
|
||||||
|
testPublishBadMetadata(t, data.CanonicalSnapshotRole, repo, false, false)
|
||||||
|
|
||||||
|
repo, _ = initializeRepo(t, data.ECDSAKey, "docker.com/notary2", ts.URL, false)
|
||||||
|
defer os.RemoveAll(repo.baseDir)
|
||||||
|
testPublishBadMetadata(t, data.CanonicalSnapshotRole, repo, false, false)
|
||||||
|
|
||||||
|
// publish first - should succeed
|
||||||
|
repo, _ = initializeRepo(t, data.ECDSAKey, "docker.com/notary3", ts.URL, true)
|
||||||
|
defer os.RemoveAll(repo.baseDir)
|
||||||
|
testPublishBadMetadata(t, data.CanonicalSnapshotRole, repo, true, true)
|
||||||
|
|
||||||
|
repo, _ = initializeRepo(t, data.ECDSAKey, "docker.com/notary4", ts.URL, false)
|
||||||
|
defer os.RemoveAll(repo.baseDir)
|
||||||
|
testPublishBadMetadata(t, data.CanonicalSnapshotRole, repo, true, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the targets metadata is corrupt or the targets metadata is unreadable,
|
// If the targets metadata is corrupt or the targets metadata is unreadable,
|
||||||
// we can't publish. This is even if there is no change to targets.
|
// we can't publish for the first time, because there is no existing data for.
|
||||||
|
// us to download. If the repo has already been published, it doesn't matter
|
||||||
|
// if the metadata is corrupt because we can just redownload if it is.
|
||||||
func TestPublishTargetsCorrupt(t *testing.T) {
|
func TestPublishTargetsCorrupt(t *testing.T) {
|
||||||
testPublishBadMetadataAfterInit(t, data.CanonicalTargetsRole, false)
|
ts := fullTestServer(t)
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
// do not publish first - publish should fail
|
||||||
|
repo, _ := initializeRepo(t, data.ECDSAKey, "docker.com/notary1", ts.URL, false)
|
||||||
|
defer os.RemoveAll(repo.baseDir)
|
||||||
|
testPublishBadMetadata(t, data.CanonicalTargetsRole, repo, false, false)
|
||||||
|
|
||||||
|
// publish first - should succeed
|
||||||
|
repo, _ = initializeRepo(t, data.ECDSAKey, "docker.com/notary2", ts.URL, false)
|
||||||
|
defer os.RemoveAll(repo.baseDir)
|
||||||
|
testPublishBadMetadata(t, data.CanonicalTargetsRole, repo, true, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the root metadata is corrupt or the root metadata is unreadable,
|
// If the root metadata is corrupt or the root metadata is unreadable,
|
||||||
// whether the client or server has the snapshot key, we can't publish. This
|
// we can't publish for the first time or the second time. Root is the most
|
||||||
// is even if there is no change to root.
|
// important and what we used to pin trust, so if it's corrupt, we can't
|
||||||
|
// verify downloaded updates.
|
||||||
func TestPublishRootCorrupt(t *testing.T) {
|
func TestPublishRootCorrupt(t *testing.T) {
|
||||||
testPublishBadMetadataAfterInit(t, data.CanonicalRootRole, false)
|
t.Skip("Test currently fails - not sure what the correct behavior is.")
|
||||||
|
|
||||||
|
ts := fullTestServer(t)
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
// do not publish first - publish should fail
|
||||||
|
repo, _ := initializeRepo(t, data.ECDSAKey, "docker.com/notary1", ts.URL, false)
|
||||||
|
defer os.RemoveAll(repo.baseDir)
|
||||||
|
testPublishBadMetadata(t, data.CanonicalRootRole, repo, false, false)
|
||||||
|
|
||||||
|
// publish first - publish should still succeed if root corrupt
|
||||||
|
repo, _ = initializeRepo(t, data.ECDSAKey, "docker.com/notary2", ts.URL, false)
|
||||||
|
defer os.RemoveAll(repo.baseDir)
|
||||||
|
testPublishBadMetadata(t, data.CanonicalRootRole, repo, true, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertCannotPublishIfMetadataCorrupt(t *testing.T, repo *NotaryRepository, roleName string) {
|
// When publishing snapshot, root, or target, if the repo hasn't been published
|
||||||
|
// before, if the metadata is corrupt, it can't be published. If it has been
|
||||||
|
// published already, then the corrupt metadata can just be re-downloaded, so
|
||||||
|
// publishing is successful.
|
||||||
|
func testPublishBadMetadata(t *testing.T, roleName string, repo *NotaryRepository,
|
||||||
|
publishFirst, succeeds bool) {
|
||||||
|
|
||||||
|
if publishFirst {
|
||||||
|
assert.NoError(t, repo.Publish())
|
||||||
|
}
|
||||||
|
|
||||||
|
addTarget(t, repo, "v1", "../fixtures/intermediate-ca.crt")
|
||||||
|
|
||||||
// readable, but corrupt file
|
// readable, but corrupt file
|
||||||
repo.fileStore.SetMeta(roleName, []byte("this isn't JSON"))
|
repo.fileStore.SetMeta(roleName, []byte("this isn't JSON"))
|
||||||
err := repo.Publish()
|
err := repo.Publish()
|
||||||
assert.Error(t, err)
|
if succeeds {
|
||||||
assert.IsType(t, ®Json.SyntaxError{}, err)
|
assert.NoError(t, err)
|
||||||
|
} else {
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.IsType(t, ®Json.SyntaxError{}, err)
|
||||||
|
}
|
||||||
|
|
||||||
// make an unreadable file by creating a directory instead of a file
|
// make an unreadable file by creating a directory instead of a file
|
||||||
path := fmt.Sprintf("%s.%s",
|
path := fmt.Sprintf("%s.%s",
|
||||||
|
|
@ -1361,22 +1425,12 @@ func assertCannotPublishIfMetadataCorrupt(t *testing.T, repo *NotaryRepository,
|
||||||
defer os.RemoveAll(path)
|
defer os.RemoveAll(path)
|
||||||
|
|
||||||
err = repo.Publish()
|
err = repo.Publish()
|
||||||
assert.Error(t, err)
|
if succeeds {
|
||||||
assert.IsType(t, &os.PathError{}, err)
|
assert.NoError(t, err)
|
||||||
}
|
} else {
|
||||||
|
assert.Error(t, err)
|
||||||
func testPublishBadMetadataAfterInit(
|
assert.IsType(t, &os.PathError{}, err)
|
||||||
t *testing.T, roleName string, serverManagesSnapshot bool) {
|
}
|
||||||
|
|
||||||
ts := fullTestServer(t)
|
|
||||||
defer ts.Close()
|
|
||||||
|
|
||||||
repo, _ := initializeRepo(
|
|
||||||
t, data.ECDSAKey, "docker.com/notary", ts.URL, serverManagesSnapshot)
|
|
||||||
defer os.RemoveAll(repo.baseDir)
|
|
||||||
|
|
||||||
addTarget(t, repo, "v1", "../fixtures/intermediate-ca.crt")
|
|
||||||
assertCannotPublishIfMetadataCorrupt(t, repo, roleName)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type cannotCreateKeys struct {
|
type cannotCreateKeys struct {
|
||||||
|
|
@ -1566,15 +1620,12 @@ func TestPublishTargetsDelgationSuccessLocallyHasRoles(t *testing.T) {
|
||||||
// is present, publish will write to that role only. The targets keys are not
|
// is present, publish will write to that role only. The targets keys are not
|
||||||
// needed.
|
// needed.
|
||||||
func TestPublishTargetsDelgationNoTargetsKeyNeeded(t *testing.T) {
|
func TestPublishTargetsDelgationNoTargetsKeyNeeded(t *testing.T) {
|
||||||
tempBaseDir, err := ioutil.TempDir("", "notary-test-")
|
|
||||||
assert.NoError(t, err, "failed to create a temporary directory: %s", err)
|
|
||||||
defer os.RemoveAll(tempBaseDir)
|
|
||||||
|
|
||||||
gun := "docker.com/notary"
|
|
||||||
ts := fullTestServer(t)
|
ts := fullTestServer(t)
|
||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
|
|
||||||
repo, _ := initializeRepo(t, data.ECDSAKey, tempBaseDir, gun, ts.URL, false)
|
repo, _ := initializeRepo(t, data.ECDSAKey, "docker.com/notary", ts.URL, false)
|
||||||
|
defer os.RemoveAll(repo.baseDir)
|
||||||
|
|
||||||
delgKey, err := repo.CryptoService.Create("targets/a", data.ECDSAKey)
|
delgKey, err := repo.CryptoService.Create("targets/a", data.ECDSAKey)
|
||||||
assert.NoError(t, err, "error creating delegation key")
|
assert.NoError(t, err, "error creating delegation key")
|
||||||
|
|
||||||
|
|
@ -1644,26 +1695,17 @@ func TestPublishTargetsDelgationSuccessNeedsToDownloadRoles(t *testing.T) {
|
||||||
// Ensure that two clients can publish delegations with two different keys and
|
// Ensure that two clients can publish delegations with two different keys and
|
||||||
// the changes will not clobber each other.
|
// the changes will not clobber each other.
|
||||||
func TestPublishTargetsDelgationFromTwoRepos(t *testing.T) {
|
func TestPublishTargetsDelgationFromTwoRepos(t *testing.T) {
|
||||||
var tempDirs [2]string
|
|
||||||
for i := 0; i < 2; i++ {
|
|
||||||
tempBaseDir, err := ioutil.TempDir("", "notary-test-")
|
|
||||||
assert.NoError(t, err, "failed to create a temporary directory: %s", err)
|
|
||||||
defer os.RemoveAll(tempBaseDir)
|
|
||||||
tempDirs[i] = tempBaseDir
|
|
||||||
}
|
|
||||||
|
|
||||||
gun := "docker.com/notary"
|
|
||||||
ts := fullTestServer(t)
|
ts := fullTestServer(t)
|
||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
|
|
||||||
// this happens to be the client that creates the repo, but can also
|
// this happens to be the client that creates the repo, but can also
|
||||||
// write a delegation
|
// write a delegation
|
||||||
repo1, _ := initializeRepo(t, data.ECDSAKey, tempDirs[0], gun, ts.URL, true)
|
repo1, _ := initializeRepo(t, data.ECDSAKey, "docker.com/notary", ts.URL, true)
|
||||||
|
defer os.RemoveAll(repo1.baseDir)
|
||||||
|
|
||||||
// this is the second writable repo
|
// this is the second writable repo
|
||||||
repo2, err := NewNotaryRepository(tempDirs[1], gun, ts.URL,
|
repo2 := newRepoToTestRepo(t, repo1)
|
||||||
http.DefaultTransport, passphraseRetriever)
|
defer os.RemoveAll(repo2.baseDir)
|
||||||
assert.NoError(t, err, "error creating repository: %s", err)
|
|
||||||
|
|
||||||
// create keys for each repo
|
// create keys for each repo
|
||||||
key1, err := repo1.CryptoService.Create("targets/a", data.ECDSAKey)
|
key1, err := repo1.CryptoService.Create("targets/a", data.ECDSAKey)
|
||||||
|
|
@ -1711,14 +1753,6 @@ func TestPublishTargetsDelgationFromTwoRepos(t *testing.T) {
|
||||||
// A client who could publish before can no longer publish once the owner
|
// A client who could publish before can no longer publish once the owner
|
||||||
// removes their delegation key from the delegation role.
|
// removes their delegation key from the delegation role.
|
||||||
func TestPublishRemoveDelgationKeyFromDelegationRole(t *testing.T) {
|
func TestPublishRemoveDelgationKeyFromDelegationRole(t *testing.T) {
|
||||||
var tempDirs [2]string
|
|
||||||
for i := 0; i < 2; i++ {
|
|
||||||
tempBaseDir, err := ioutil.TempDir("", "notary-test-")
|
|
||||||
assert.NoError(t, err, "failed to create a temporary directory: %s", err)
|
|
||||||
defer os.RemoveAll(tempBaseDir)
|
|
||||||
tempDirs[i] = tempBaseDir
|
|
||||||
}
|
|
||||||
|
|
||||||
gun := "docker.com/notary"
|
gun := "docker.com/notary"
|
||||||
ts := fullTestServer(t)
|
ts := fullTestServer(t)
|
||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
|
|
@ -1726,12 +1760,13 @@ func TestPublishRemoveDelgationKeyFromDelegationRole(t *testing.T) {
|
||||||
// this is the original repo - it owns the root/targets keys and creates
|
// this is the original repo - it owns the root/targets keys and creates
|
||||||
// the delegation to which it doesn't have the key (so server snapshot
|
// the delegation to which it doesn't have the key (so server snapshot
|
||||||
// signing would be required)
|
// signing would be required)
|
||||||
ownerRepo, _ := initializeRepo(t, data.ECDSAKey, tempDirs[0], gun, ts.URL, true)
|
ownerRepo, _ := initializeRepo(t, data.ECDSAKey, gun, ts.URL, true)
|
||||||
|
defer os.RemoveAll(ownerRepo.baseDir)
|
||||||
|
|
||||||
// this is a user, or otherwise a repo that only has access to the delegation
|
// this is a user, or otherwise a repo that only has access to the delegation
|
||||||
// key so it can publish targets to the delegated role
|
// key so it can publish targets to the delegated role
|
||||||
delgRepo, err := NewNotaryRepository(tempDirs[1], gun, ts.URL,
|
delgRepo := newRepoToTestRepo(t, ownerRepo)
|
||||||
http.DefaultTransport, passphraseRetriever)
|
defer os.RemoveAll(delgRepo.baseDir)
|
||||||
assert.NoError(t, err, "error creating repository: %s", err)
|
|
||||||
|
|
||||||
// create a key on the delegated repo
|
// create a key on the delegated repo
|
||||||
aKey, err := delgRepo.CryptoService.Create("targets/a", data.ECDSAKey)
|
aKey, err := delgRepo.CryptoService.Create("targets/a", data.ECDSAKey)
|
||||||
|
|
@ -1777,27 +1812,19 @@ func TestPublishRemoveDelgationKeyFromDelegationRole(t *testing.T) {
|
||||||
// A client who could publish before can no longer publish once the owner
|
// A client who could publish before can no longer publish once the owner
|
||||||
// deletes the delegation
|
// deletes the delegation
|
||||||
func TestPublishRemoveDelgation(t *testing.T) {
|
func TestPublishRemoveDelgation(t *testing.T) {
|
||||||
var tempDirs [2]string
|
|
||||||
for i := 0; i < 2; i++ {
|
|
||||||
tempBaseDir, err := ioutil.TempDir("", "notary-test-")
|
|
||||||
assert.NoError(t, err, "failed to create a temporary directory: %s", err)
|
|
||||||
defer os.RemoveAll(tempBaseDir)
|
|
||||||
tempDirs[i] = tempBaseDir
|
|
||||||
}
|
|
||||||
|
|
||||||
gun := "docker.com/notary"
|
|
||||||
ts := fullTestServer(t)
|
ts := fullTestServer(t)
|
||||||
defer ts.Close()
|
defer ts.Close()
|
||||||
|
|
||||||
// this is the original repo - it owns the root/targets keys and creates
|
// this is the original repo - it owns the root/targets keys and creates
|
||||||
// the delegation to which it doesn't have the key (so server snapshot
|
// the delegation to which it doesn't have the key (so server snapshot
|
||||||
// signing would be required)
|
// signing would be required)
|
||||||
ownerRepo, _ := initializeRepo(t, data.ECDSAKey, tempDirs[0], gun, ts.URL, true)
|
ownerRepo, _ := initializeRepo(t, data.ECDSAKey, "docker.com/notary", ts.URL, true)
|
||||||
|
defer os.RemoveAll(ownerRepo.baseDir)
|
||||||
|
|
||||||
// this is a user, or otherwise a repo that only has access to the delegation
|
// this is a user, or otherwise a repo that only has access to the delegation
|
||||||
// key so it can publish targets to the delegated role
|
// key so it can publish targets to the delegated role
|
||||||
delgRepo, err := NewNotaryRepository(tempDirs[1], gun, ts.URL,
|
delgRepo := newRepoToTestRepo(t, ownerRepo)
|
||||||
http.DefaultTransport, passphraseRetriever)
|
defer os.RemoveAll(delgRepo.baseDir)
|
||||||
assert.NoError(t, err, "error creating repository: %s", err)
|
|
||||||
|
|
||||||
// create a key on the delegated repo
|
// create a key on the delegated repo
|
||||||
aKey, err := delgRepo.CryptoService.Create("targets/a", data.ECDSAKey)
|
aKey, err := delgRepo.CryptoService.Create("targets/a", data.ECDSAKey)
|
||||||
|
|
@ -1822,6 +1849,31 @@ func TestPublishRemoveDelgation(t *testing.T) {
|
||||||
assert.Error(t, delgRepo.Publish())
|
assert.Error(t, delgRepo.Publish())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the delegation data is corrupt or unreadable, it doesn't matter because
|
||||||
|
// all the delegation information is just re-downloaded. When bootstrapping
|
||||||
|
// the repository from disk, we just don't load the data from disk because
|
||||||
|
// there should not be anything there yet.
|
||||||
|
func TestPublishSucceedsDespiteDelegationCorrupt(t *testing.T) {
|
||||||
|
ts := fullTestServer(t)
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
repo, _ := initializeRepo(t, data.ECDSAKey, "docker.com/notary", ts.URL, false)
|
||||||
|
defer os.RemoveAll(repo.baseDir)
|
||||||
|
|
||||||
|
delgKey, err := repo.CryptoService.Create("targets/a", data.ECDSAKey)
|
||||||
|
assert.NoError(t, err, "error creating delegation key")
|
||||||
|
|
||||||
|
assert.NoError(t,
|
||||||
|
repo.AddDelegation("targets/a", 1, []data.PublicKey{delgKey}, []string{""}),
|
||||||
|
"error creating delegation")
|
||||||
|
|
||||||
|
testPublishBadMetadata(t, "targets/a", repo, false, true)
|
||||||
|
|
||||||
|
// publish again, now that it has already been published, and again there
|
||||||
|
// is no error.
|
||||||
|
testPublishBadMetadata(t, "targets/a", repo, true, true)
|
||||||
|
}
|
||||||
|
|
||||||
// Rotate invalid roles, or attempt to delegate target signing to the server
|
// Rotate invalid roles, or attempt to delegate target signing to the server
|
||||||
func TestRotateKeyInvalidRole(t *testing.T) {
|
func TestRotateKeyInvalidRole(t *testing.T) {
|
||||||
ts, _, _ := simpleTestServer(t)
|
ts, _, _ := simpleTestServer(t)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue