Add test for, and fix bug with, publishing a bare repo not sending the targets file.

It should always be published the first time, like the root.json.

Signed-off-by: Ying Li <ying.li@docker.com>
This commit is contained in:
Ying Li 2015-12-18 13:39:19 -08:00
parent c12958af36
commit a1cbe5d43c
2 changed files with 63 additions and 16 deletions

View File

@ -522,7 +522,7 @@ func (r *NotaryRepository) GetChangelist() (changelist.Changelist, error) {
// Publish pushes the local changes in signed material to the remote notary-server
// Conceptually it performs an operation similar to a `git rebase`
func (r *NotaryRepository) Publish() error {
var updateRoot bool
var initialPublish bool
// attempt to initialize the repo from the remote store
c, err := r.bootstrapClient()
if err != nil {
@ -538,10 +538,11 @@ func (r *NotaryRepository) Publish() error {
return err
}
// We had local data but the server doesn't know about the repo yet,
// ensure we will push the initial root file. The root may not
// be marked as Dirty, since there may not be any changes that
// update it, so use a different boolean.
updateRoot = true
// ensure we will push the initial root and targets file. Either or
// both of the root and targets may not be marked as Dirty, since
// there may not be any changes that update them, so use a
// different boolean.
initialPublish = true
} else {
// The remote store returned an error other than 404. We're
// unable to determine if the repo has been initialized or not.
@ -576,7 +577,7 @@ func (r *NotaryRepository) Publish() error {
updatedFiles := make(map[string][]byte)
// check if our root file is nearing expiry. Resign if it is.
if nearExpiry(r.tufRepo.Root) || r.tufRepo.Root.Dirty || updateRoot {
if nearExpiry(r.tufRepo.Root) || r.tufRepo.Root.Dirty || initialPublish {
rootJSON, err := serializeCanonicalRole(r.tufRepo, data.CanonicalRootRole)
if err != nil {
return err
@ -586,7 +587,7 @@ func (r *NotaryRepository) Publish() error {
// iterate through all the targets files - if they are dirty, sign and update
for roleName, roleObj := range r.tufRepo.Targets {
if roleObj.Dirty {
if roleObj.Dirty || (roleName == data.CanonicalTargetsRole && initialPublish) {
targetsJSON, err := serializeCanonicalRole(r.tufRepo, roleName)
if err != nil {
return err

View File

@ -1140,28 +1140,74 @@ func testGetChangelist(t *testing.T, rootType string) {
assert.Equal(t, "latest", latestChange.Path())
}
// Create a repo, instantiate a notary server, and publish the repo to the
// server, signing all the non-timestamp metadata.
// Create a repo, instantiate a notary server, and publish the bare repo to the
// server, signing all the non-timestamp metadata. Root, targets, and snapshots
// (if locally signing) should be sent.
func TestPublishBareRepo(t *testing.T) {
testPublishNoData(t, data.ECDSAKey, true)
testPublishNoData(t, data.ECDSAKey, false)
if !testing.Short() {
testPublishNoData(t, data.RSAKey, true)
testPublishNoData(t, data.RSAKey, false)
}
}
func testPublishNoData(t *testing.T, rootType string, serverManagesSnapshot bool) {
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)
defer ts.Close()
repo1, _ := initializeRepo(t, rootType, tempDirs[0], gun, ts.URL,
serverManagesSnapshot)
assert.NoError(t, repo1.Publish())
// use another repo to check metadata
repo2, err := NewNotaryRepository(tempDirs[1], gun, ts.URL,
http.DefaultTransport, passphraseRetriever)
assert.NoError(t, err, "error creating repository: %s", err)
targets, err := repo2.ListTargets()
assert.NoError(t, err)
assert.Empty(t, targets)
for role := range data.ValidRoles {
// we don't cache timstamp metadata
if role != data.CanonicalTimestampRole {
assertRepoHasExpectedMetadata(t, repo2, role, true)
}
}
}
// Create a repo, instantiate a notary server, and publish the repo with
// some targets to the server, signing all the non-timestamp metadata.
// We test this with both an RSA and ECDSA root key
func TestPublishClientHasSnapshotKey(t *testing.T) {
testPublish(t, data.ECDSAKey, false)
testPublishWithData(t, data.ECDSAKey, false)
if !testing.Short() {
testPublish(t, data.RSAKey, false)
testPublishWithData(t, data.RSAKey, false)
}
}
// Create a repo, instantiate a notary server (designating the server as the
// snapshot signer) , and publish the repo to the server, signing the root and
// targets metadata only. The server should sign just fine.
// snapshot signer) , and publish the repo with some targets to the server,
// signing the root and targets metadata only. The server should sign just fine.
// We test this with both an RSA and ECDSA root key
func TestPublishAfterInitServerHasSnapshotKey(t *testing.T) {
testPublish(t, data.ECDSAKey, true)
testPublishWithData(t, data.ECDSAKey, true)
if !testing.Short() {
testPublish(t, data.RSAKey, true)
testPublishWithData(t, data.RSAKey, true)
}
}
func testPublish(t *testing.T, rootType string, serverManagesSnapshot bool) {
func testPublishWithData(t *testing.T, rootType string, serverManagesSnapshot bool) {
// Temporary directory where test files will be created
tempBaseDir, err := ioutil.TempDir("/tmp", "notary-test-")
defer os.RemoveAll(tempBaseDir)