Пример #1
0
func writeRepo(t *testing.T, dir string, repo *Repo) {
	err := os.MkdirAll(dir, 0755)
	assert.NoError(t, err)
	signedRoot, err := repo.SignRoot(data.DefaultExpires("root"))
	assert.NoError(t, err)
	rootJSON, _ := json.Marshal(signedRoot)
	ioutil.WriteFile(dir+"/root.json", rootJSON, 0755)

	for r := range repo.Targets {
		signedTargets, err := repo.SignTargets(r, data.DefaultExpires("targets"))
		assert.NoError(t, err)
		targetsJSON, _ := json.Marshal(signedTargets)
		p := path.Join(dir, r+".json")
		parentDir := filepath.Dir(p)
		os.MkdirAll(parentDir, 0755)
		ioutil.WriteFile(p, targetsJSON, 0755)
	}

	signedSnapshot, err := repo.SignSnapshot(data.DefaultExpires("snapshot"))
	assert.NoError(t, err)
	snapshotJSON, _ := json.Marshal(signedSnapshot)
	ioutil.WriteFile(dir+"/snapshot.json", snapshotJSON, 0755)

	signedTimestamp, err := repo.SignTimestamp(data.DefaultExpires("timestamp"))
	assert.NoError(t, err)
	timestampJSON, _ := json.Marshal(signedTimestamp)
	ioutil.WriteFile(dir+"/timestamp.json", timestampJSON, 0755)
}
Пример #2
0
func TestDownloadSnapshotHappy(t *testing.T) {
	repo, _, err := testutils.EmptyRepo("docker.com/notary")
	assert.NoError(t, err)
	localStorage := store.NewMemoryStore(nil)
	remoteStorage := store.NewMemoryStore(nil)
	client := NewClient(repo, remoteStorage, localStorage)

	// create and "upload" sample snapshot and timestamp
	signedOrig, err := repo.SignSnapshot(data.DefaultExpires("snapshot"))
	assert.NoError(t, err)
	orig, err := json.Marshal(signedOrig)
	assert.NoError(t, err)
	err = remoteStorage.SetMeta("snapshot", orig)
	assert.NoError(t, err)

	signedOrig, err = repo.SignTimestamp(data.DefaultExpires("timestamp"))
	assert.NoError(t, err)
	orig, err = json.Marshal(signedOrig)
	assert.NoError(t, err)
	err = remoteStorage.SetMeta("timestamp", orig)
	assert.NoError(t, err)

	err = client.downloadSnapshot()
	assert.NoError(t, err)
}
Пример #3
0
func TestGetTimestampNewSnapshot(t *testing.T) {
	store := storage.NewMemStorage()
	crypto := signed.NewEd25519()

	snapshot := &data.SignedSnapshot{
		Signed: data.Snapshot{
			Expires: data.DefaultExpires(data.CanonicalSnapshotRole),
		},
	}
	snapshot.Signed.Version = 0
	snapJSON, _ := json.Marshal(snapshot)

	store.UpdateCurrent("gun", storage.MetaUpdate{Role: "snapshot", Version: 0, Data: snapJSON})
	// create a key to be used by GetTimestamp
	_, err := GetOrCreateTimestampKey("gun", store, crypto, data.ED25519Key)
	assert.Nil(t, err, "GetKey errored")

	ts1, err := GetOrCreateTimestamp("gun", store, crypto)
	assert.Nil(t, err, "GetTimestamp errored")

	snapshot = &data.SignedSnapshot{
		Signed: data.Snapshot{
			Expires: data.DefaultExpires(data.CanonicalSnapshotRole),
		},
	}
	snapshot.Signed.Version = 1
	snapJSON, _ = json.Marshal(snapshot)

	store.UpdateCurrent("gun", storage.MetaUpdate{Role: "snapshot", Version: 1, Data: snapJSON})

	ts2, err := GetOrCreateTimestamp("gun", store, crypto)
	assert.NoError(t, err, "GetTimestamp errored")

	assert.NotEqual(t, ts1, ts2, "Timestamp was not regenerated when snapshot changed")
}
Пример #4
0
func TestValidateTargetsRoleNotInParent(t *testing.T) {
	baseRepo, cs, err := testutils.EmptyRepo("docker.com/notary")
	assert.NoError(t, err)
	store := storage.NewMemStorage()

	level1Key, err := cs.Create("targets/level1", data.ED25519Key)
	assert.NoError(t, err)
	r, err := data.NewRole("targets/level1", 1, []string{level1Key.ID()}, []string{""})

	baseRepo.Targets[data.CanonicalTargetsRole].Signed.Delegations.Roles = []*data.Role{r}
	baseRepo.Targets[data.CanonicalTargetsRole].Signed.Delegations.Keys = data.Keys{
		level1Key.ID(): level1Key,
	}

	baseRepo.InitTargets("targets/level1")

	del, err := baseRepo.SignTargets("targets/level1", data.DefaultExpires(data.CanonicalTargetsRole))
	assert.NoError(t, err)
	delJSON, err := json.Marshal(del)
	assert.NoError(t, err)

	delUpdate := storage.MetaUpdate{
		Role:    "targets/level1",
		Version: 1,
		Data:    delJSON,
	}

	// set back to empty so stored targets doesn't have reference to level1
	baseRepo.Targets[data.CanonicalTargetsRole].Signed.Delegations.Roles = nil
	baseRepo.Targets[data.CanonicalTargetsRole].Signed.Delegations.Keys = nil
	targets, err := baseRepo.SignTargets(data.CanonicalTargetsRole, data.DefaultExpires(data.CanonicalTargetsRole))

	tgtsJSON, err := json.Marshal(targets)
	assert.NoError(t, err)
	update := storage.MetaUpdate{
		Role:    data.CanonicalTargetsRole,
		Version: 1,
		Data:    tgtsJSON,
	}
	store.UpdateCurrent("gun", update)

	roles := map[string]storage.MetaUpdate{
		"targets/level1":          delUpdate,
		data.CanonicalTargetsRole: update,
	}

	valRepo := tuf.NewRepo(nil)
	valRepo.SetRoot(baseRepo.Root)

	// because we sort the roles, the list of returned updates
	// will contain shallower roles first, in this case "targets",
	// and then "targets/level1"
	updates, err := loadAndValidateTargets("gun", valRepo, roles, store)
	assert.NoError(t, err)
	assert.Len(t, updates, 1)
	assert.Equal(t, data.CanonicalTargetsRole, updates[0].Role)
	assert.Equal(t, tgtsJSON, updates[0].Data)
}
Пример #5
0
func TestValidateTargetsParentInUpdate(t *testing.T) {
	_, baseRepo, cs, err := testutils.EmptyRepo("docker.com/notary")
	assert.NoError(t, err)
	store := storage.NewMemStorage()

	k, err := cs.Create("targets/level1", data.ED25519Key)
	assert.NoError(t, err)
	r, err := data.NewRole("targets/level1", 1, []string{k.ID()}, []string{""}, nil)
	assert.NoError(t, err)

	baseRepo.UpdateDelegations(r, []data.PublicKey{k})

	// no targets file is created for the new delegations, so force one
	baseRepo.InitTargets("targets/level1")

	targets, err := baseRepo.SignTargets("targets", data.DefaultExpires(data.CanonicalTargetsRole))

	tgtsJSON, err := json.Marshal(targets)
	assert.NoError(t, err)
	update := storage.MetaUpdate{
		Role:    data.CanonicalTargetsRole,
		Version: 1,
		Data:    tgtsJSON,
	}
	store.UpdateCurrent("gun", update)

	del, err := baseRepo.SignTargets("targets/level1", data.DefaultExpires(data.CanonicalTargetsRole))
	assert.NoError(t, err)
	delJSON, err := json.Marshal(del)
	assert.NoError(t, err)

	delUpdate := storage.MetaUpdate{
		Role:    "targets/level1",
		Version: 1,
		Data:    delJSON,
	}

	roles := map[string]storage.MetaUpdate{
		"targets/level1": delUpdate,
		"targets":        update,
	}

	kdb := keys.NewDB()
	valRepo := tuf.NewRepo(kdb, nil)
	valRepo.SetRoot(baseRepo.Root)

	// because we sort the roles, the list of returned updates
	// will contain shallower roles first, in this case "targets",
	// and then "targets/level1"
	updates, err := loadAndValidateTargets("gun", valRepo, roles, kdb, store)
	assert.NoError(t, err)
	assert.Len(t, updates, 2)
	assert.Equal(t, "targets", updates[0].Role)
	assert.Equal(t, tgtsJSON, updates[0].Data)
	assert.Equal(t, "targets/level1", updates[1].Role)
	assert.Equal(t, delJSON, updates[1].Data)
}
Пример #6
0
func TestSignRootOldKeyCertMissing(t *testing.T) {
	gun := "docker/test-sign-root"
	referenceTime := time.Now()

	cs := cryptoservice.NewCryptoService(trustmanager.NewKeyMemoryStore(
		passphrase.ConstantRetriever("password")))

	rootPublicKey, err := cs.Create(data.CanonicalRootRole, gun, data.ECDSAKey)
	require.NoError(t, err)
	rootPrivateKey, _, err := cs.GetPrivateKey(rootPublicKey.ID())
	require.NoError(t, err)
	oldRootCert, err := cryptoservice.GenerateCertificate(rootPrivateKey, gun, referenceTime.AddDate(-9, 0, 0),
		referenceTime.AddDate(1, 0, 0))
	require.NoError(t, err)
	oldRootCertKey := trustmanager.CertToKey(oldRootCert)

	repo := initRepoWithRoot(t, cs, oldRootCertKey)

	// Create a first signature, using the old key.
	signedRoot, err := repo.SignRoot(data.DefaultExpires(data.CanonicalRootRole))
	require.NoError(t, err)
	verifySignatureList(t, signedRoot, oldRootCertKey)
	err = verifyRootSignatureAgainstKey(t, signedRoot, oldRootCertKey)
	require.NoError(t, err)

	// Create a new certificate
	newRootCert, err := cryptoservice.GenerateCertificate(rootPrivateKey, gun, referenceTime, referenceTime.AddDate(10, 0, 0))
	require.NoError(t, err)
	newRootCertKey := trustmanager.CertToKey(newRootCert)
	require.NotEqual(t, oldRootCertKey.ID(), newRootCertKey.ID())

	// Only trust the new certificate
	err = repo.ReplaceBaseKeys(data.CanonicalRootRole, newRootCertKey)
	require.NoError(t, err)
	updatedRootRole, err := repo.GetBaseRole(data.CanonicalRootRole)
	require.NoError(t, err)
	updatedRootKeyIDs := updatedRootRole.ListKeyIDs()
	require.Equal(t, 1, len(updatedRootKeyIDs))
	require.Equal(t, newRootCertKey.ID(), updatedRootKeyIDs[0])

	// Now forget all about the old certificate: drop it from the Root carried keys
	delete(repo.Root.Signed.Keys, oldRootCertKey.ID())
	repo2 := NewRepo(cs)
	repo2.Root = repo.Root
	repo2.originalRootRole = updatedRootRole

	// Create a second signature
	signedRoot, err = repo2.SignRoot(data.DefaultExpires(data.CanonicalRootRole))
	require.NoError(t, err)
	verifySignatureList(t, signedRoot, newRootCertKey) // Without oldRootCertKey

	// Verify that the signature can be verified when trusting the new certificate
	err = verifyRootSignatureAgainstKey(t, signedRoot, newRootCertKey)
	require.NoError(t, err)
	err = verifyRootSignatureAgainstKey(t, signedRoot, oldRootCertKey)
	require.Error(t, err)
}
Пример #7
0
func TestDBGetChecksum(t *testing.T) {
	tempBaseDir, err := ioutil.TempDir("", "notary-test-")
	_, store := SetUpSQLite(t, tempBaseDir)
	defer os.RemoveAll(tempBaseDir)

	ts := data.SignedTimestamp{
		Signatures: make([]data.Signature, 0),
		Signed: data.Timestamp{
			SignedCommon: data.SignedCommon{
				Type:    data.TUFTypes[data.CanonicalTimestampRole],
				Version: 1,
				Expires: data.DefaultExpires(data.CanonicalTimestampRole),
			},
		},
	}
	j, err := json.Marshal(&ts)
	require.NoError(t, err)
	update := MetaUpdate{
		Role:    data.CanonicalTimestampRole,
		Version: 1,
		Data:    j,
	}
	checksumBytes := sha256.Sum256(j)
	checksum := hex.EncodeToString(checksumBytes[:])

	store.UpdateCurrent("gun", update)

	// create and add a newer timestamp. We're going to try and get the one
	// created above by checksum
	ts = data.SignedTimestamp{
		Signatures: make([]data.Signature, 0),
		Signed: data.Timestamp{
			SignedCommon: data.SignedCommon{
				Type:    data.TUFTypes[data.CanonicalTimestampRole],
				Version: 2,
				Expires: data.DefaultExpires(data.CanonicalTimestampRole),
			},
		},
	}
	newJ, err := json.Marshal(&ts)
	require.NoError(t, err)
	update = MetaUpdate{
		Role:    data.CanonicalTimestampRole,
		Version: 2,
		Data:    newJ,
	}

	store.UpdateCurrent("gun", update)

	cDate, data, err := store.GetChecksum("gun", data.CanonicalTimestampRole, checksum)
	require.NoError(t, err)
	require.EqualValues(t, j, data)
	// the creation date was sometime wthin the last minute
	require.True(t, cDate.After(time.Now().Add(-1*time.Minute)))
	require.True(t, cDate.Before(time.Now().Add(5*time.Second)))
}
Пример #8
0
func TestValidateTargetsRoleNotInParent(t *testing.T) {
	kdb, baseRepo, cs := testutils.EmptyRepo()
	store := storage.NewMemStorage()

	k, err := cs.Create("targets/level1", data.ED25519Key)
	assert.NoError(t, err)
	r, err := data.NewRole("targets/level1", 1, []string{k.ID()}, []string{""}, nil)
	assert.NoError(t, err)

	kdb.AddKey(k)
	err = kdb.AddRole(r)
	assert.NoError(t, err)

	baseRepo.InitTargets("targets/level1")

	targets, err := baseRepo.SignTargets("targets", data.DefaultExpires(data.CanonicalTargetsRole))

	tgtsJSON, err := json.MarshalCanonical(targets)
	assert.NoError(t, err)
	update := storage.MetaUpdate{
		Role:    data.CanonicalTargetsRole,
		Version: 1,
		Data:    tgtsJSON,
	}
	store.UpdateCurrent("gun", update)

	del, err := baseRepo.SignTargets("targets/level1", data.DefaultExpires(data.CanonicalTargetsRole))
	assert.NoError(t, err)
	delJSON, err := json.MarshalCanonical(del)
	assert.NoError(t, err)

	delUpdate := storage.MetaUpdate{
		Role:    "targets/level1",
		Version: 1,
		Data:    delJSON,
	}

	roles := map[string]storage.MetaUpdate{
		"targets/level1": delUpdate,
		"targets":        update,
	}

	kdb = keys.NewDB()
	valRepo := tuf.NewRepo(kdb, nil)
	valRepo.SetRoot(baseRepo.Root)

	// because we sort the roles, the list of returned updates
	// will contain shallower roles first, in this case "targets",
	// and then "targets/level1"
	updates, err := loadAndValidateTargets("gun", valRepo, roles, kdb, store)
	assert.NoError(t, err)
	assert.Len(t, updates, 1)
	assert.Equal(t, "targets", updates[0].Role)
	assert.Equal(t, tgtsJSON, updates[0].Data)
}
Пример #9
0
// reads data from the repository in order to fake data being served via
// the ServeMux.
func fakeServerData(t *testing.T, repo *NotaryRepository, mux *http.ServeMux) {
	tempKey, err := data.UnmarshalPrivateKey([]byte(timestampECDSAKeyJSON))
	assert.NoError(t, err)

	savedTUFRepo := repo.tufRepo // in case this is overwritten

	fileStore, err := trustmanager.NewKeyFileStore(repo.baseDir, passphraseRetriever)
	assert.NoError(t, err)
	fileStore.AddKey(
		filepath.Join(filepath.FromSlash(repo.gun), tempKey.ID()),
		"nonroot", tempKey)

	rootJSONFile := filepath.Join(repo.baseDir, "tuf",
		filepath.FromSlash(repo.gun), "metadata", "root.json")
	rootFileBytes, err := ioutil.ReadFile(rootJSONFile)

	signedTargets, err := savedTUFRepo.SignTargets(
		"targets", data.DefaultExpires("targets"))
	assert.NoError(t, err)

	signedSnapshot, err := savedTUFRepo.SignSnapshot(
		data.DefaultExpires("snapshot"))
	assert.NoError(t, err)

	signedTimestamp, err := savedTUFRepo.SignTimestamp(
		data.DefaultExpires("timestamp"))
	assert.NoError(t, err)

	mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/root.json",
		func(w http.ResponseWriter, r *http.Request) {
			assert.NoError(t, err)
			fmt.Fprint(w, string(rootFileBytes))
		})

	mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/timestamp.json",
		func(w http.ResponseWriter, r *http.Request) {
			timestampJSON, _ := json.Marshal(signedTimestamp)
			fmt.Fprint(w, string(timestampJSON))
		})

	mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/snapshot.json",
		func(w http.ResponseWriter, r *http.Request) {
			snapshotJSON, _ := json.Marshal(signedSnapshot)
			fmt.Fprint(w, string(snapshotJSON))
		})

	mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/targets.json",
		func(w http.ResponseWriter, r *http.Request) {
			targetsJSON, _ := json.Marshal(signedTargets)
			fmt.Fprint(w, string(targetsJSON))
		})
}
Пример #10
0
func TestDBGetChecksum(t *testing.T) {
	tempBaseDir, err := ioutil.TempDir("", "notary-test-")
	_, store := SetUpSQLite(t, tempBaseDir)
	defer os.RemoveAll(tempBaseDir)

	ts := data.SignedTimestamp{
		Signatures: make([]data.Signature, 0),
		Signed: data.Timestamp{
			Type:    data.TUFTypes["timestamp"],
			Version: 1,
			Expires: data.DefaultExpires("timestamp"),
		},
	}
	j, err := json.Marshal(&ts)
	require.NoError(t, err)
	update := MetaUpdate{
		Role:    data.CanonicalTimestampRole,
		Version: 1,
		Data:    j,
	}
	checksumBytes := sha256.Sum256(j)
	checksum := hex.EncodeToString(checksumBytes[:])

	store.UpdateCurrent("gun", update)

	// create and add a newer timestamp. We're going to try and get the one
	// created above by checksum
	ts = data.SignedTimestamp{
		Signatures: make([]data.Signature, 0),
		Signed: data.Timestamp{
			Type:    data.TUFTypes["timestamp"],
			Version: 2,
			Expires: data.DefaultExpires("timestamp"),
		},
	}
	newJ, err := json.Marshal(&ts)
	require.NoError(t, err)
	update = MetaUpdate{
		Role:    data.CanonicalTimestampRole,
		Version: 2,
		Data:    newJ,
	}

	store.UpdateCurrent("gun", update)

	data, err := store.GetChecksum("gun", data.CanonicalTimestampRole, checksum)
	require.NoError(t, err)
	require.EqualValues(t, j, data)
}
Пример #11
0
func TestDuplicateSigs(t *testing.T) {
	cs := NewEd25519()
	k, err := cs.Create("root", data.ED25519Key)
	assert.NoError(t, err)
	r, err := data.NewRole(
		"root",
		2,
		[]string{k.ID()},
		nil,
		nil,
	)
	assert.NoError(t, err)
	db := keys.NewDB()
	assert.NoError(t, err)
	db.AddKey(k)
	err = db.AddRole(r)
	assert.NoError(t, err)
	meta := &data.SignedCommon{Type: "Root", Version: 1, Expires: data.DefaultExpires("root")}

	b, err := json.MarshalCanonical(meta)
	assert.NoError(t, err)
	s := &data.Signed{Signed: b}
	Sign(cs, s, k)
	s.Signatures = append(s.Signatures, s.Signatures[0])
	err = Verify(s, "root", 1, db)
	assert.IsType(t, ErrRoleThreshold{}, err)
}
Пример #12
0
func TestGetSnapshotCurrValid(t *testing.T) {
	store := storage.NewMemStorage()
	crypto := signed.NewEd25519()

	_, err := GetOrCreateSnapshotKey("gun", store, crypto, data.ED25519Key)

	newData := []byte{2}
	currMeta, err := data.NewFileMeta(bytes.NewReader(newData), "sha256")
	assert.NoError(t, err)

	snapshot := &data.SignedSnapshot{
		Signed: data.Snapshot{
			Expires: data.DefaultExpires(data.CanonicalSnapshotRole),
			Meta: data.Files{
				data.CanonicalRootRole: currMeta,
			},
		},
	}
	snapJSON, _ := json.Marshal(snapshot)

	// test when db is missing the role data
	store.UpdateCurrent("gun", storage.MetaUpdate{Role: "snapshot", Version: 0, Data: snapJSON})
	_, err = GetOrCreateSnapshot("gun", store, crypto)
	assert.NoError(t, err)

	// test when db has the role data
	store.UpdateCurrent("gun", storage.MetaUpdate{Role: "root", Version: 0, Data: newData})
	_, err = GetOrCreateSnapshot("gun", store, crypto)
	assert.NoError(t, err)

	// test when db role data is expired
	store.UpdateCurrent("gun", storage.MetaUpdate{Role: "root", Version: 1, Data: []byte{3}})
	_, err = GetOrCreateSnapshot("gun", store, crypto)
	assert.NoError(t, err)
}
Пример #13
0
// If there is no previous snapshot or the previous snapshot is corrupt, then
// even if everything else is in place, getting the snapshot fails
func TestGetSnapshotNoPreviousSnapshot(t *testing.T) {
	repo, crypto, err := testutils.EmptyRepo("gun")
	require.NoError(t, err)

	sgnd, err := repo.SignRoot(data.DefaultExpires(data.CanonicalRootRole))
	require.NoError(t, err)
	rootJSON, err := json.Marshal(sgnd)
	require.NoError(t, err)

	for _, snapshotJSON := range [][]byte{nil, []byte("invalid JSON")} {
		store := storage.NewMemStorage()

		// so we know it's not a failure in getting root
		require.NoError(t,
			store.UpdateCurrent("gun", storage.MetaUpdate{Role: data.CanonicalRootRole, Version: 0, Data: rootJSON}))

		if snapshotJSON != nil {
			require.NoError(t,
				store.UpdateCurrent("gun",
					storage.MetaUpdate{Role: data.CanonicalSnapshotRole, Version: 0, Data: snapshotJSON}))
		}

		hashBytes := sha256.Sum256(snapshotJSON)
		hashHex := hex.EncodeToString(hashBytes[:])

		_, _, err = GetOrCreateSnapshot("gun", hashHex, store, crypto)
		require.Error(t, err, "GetSnapshot should have failed")
		if snapshotJSON == nil {
			require.IsType(t, storage.ErrNotFound{}, err)
		} else {
			require.IsType(t, &json.SyntaxError{}, err)
		}
	}
}
Пример #14
0
func TestDownloadTargetChecksumMismatch(t *testing.T) {
	repo, _, err := testutils.EmptyRepo("docker.com/notary")
	assert.NoError(t, err)
	localStorage := store.NewMemoryStore(nil)
	remoteStorage := testutils.NewCorruptingMemoryStore(nil)
	client := NewClient(repo, remoteStorage, localStorage)

	// create and "upload" sample targets
	signedOrig, err := repo.SignTargets("targets", data.DefaultExpires("targets"))
	assert.NoError(t, err)
	orig, err := json.Marshal(signedOrig)
	assert.NoError(t, err)
	origSha256 := sha256.Sum256(orig)
	err = remoteStorage.SetMeta("targets", orig)
	assert.NoError(t, err)

	// create local snapshot with targets file
	snap := data.SignedSnapshot{
		Signed: data.Snapshot{
			Meta: data.Files{
				"targets": data.FileMeta{
					Length: int64(len(orig)),
					Hashes: data.Hashes{
						"sha256": origSha256[:],
					},
				},
			},
		},
	}

	repo.Snapshot = &snap

	err = client.downloadTargets("targets")
	assert.IsType(t, ErrChecksumMismatch{}, err)
}
Пример #15
0
func TestCreateSnapshotNoKeyInCrypto(t *testing.T) {
	store := storage.NewMemStorage()
	repo, _, err := testutils.EmptyRepo("gun")
	require.NoError(t, err)

	sgnd, err := repo.SignRoot(data.DefaultExpires(data.CanonicalRootRole))
	require.NoError(t, err)
	rootJSON, err := json.Marshal(sgnd)
	require.NoError(t, err)

	// create an expired snapshot
	sgnd, err = repo.SignSnapshot(time.Now().AddDate(-1, -1, -1))
	require.True(t, repo.Snapshot.Signed.Expires.Before(time.Now()))
	require.NoError(t, err)
	snapshotJSON, err := json.Marshal(sgnd)
	require.NoError(t, err)

	// set all the metadata so we know the failure to sign is just because of the key
	require.NoError(t, store.UpdateCurrent("gun",
		storage.MetaUpdate{Role: data.CanonicalRootRole, Version: 0, Data: rootJSON}))
	require.NoError(t, store.UpdateCurrent("gun",
		storage.MetaUpdate{Role: data.CanonicalSnapshotRole, Version: 0, Data: snapshotJSON}))

	hashBytes := sha256.Sum256(snapshotJSON)
	hashHex := hex.EncodeToString(hashBytes[:])

	// pass it a new cryptoservice without the key
	_, _, err = GetOrCreateSnapshot("gun", hashHex, store, signed.NewEd25519())
	require.Error(t, err)
	require.IsType(t, signed.ErrInsufficientSignatures{}, err)
}
Пример #16
0
func TestUnknownKeyBelowThreshold(t *testing.T) {
	cs := NewEd25519()
	k, err := cs.Create("root", "", data.ED25519Key)
	require.NoError(t, err)
	unknown, err := cs.Create("root", "", data.ED25519Key)
	require.NoError(t, err)
	roleWithKeys := data.BaseRole{Name: "root", Keys: data.Keys{k.ID(): k}, Threshold: 2}

	meta := &data.SignedCommon{Type: "Root", Version: 1, Expires: data.DefaultExpires("root")}

	b, err := json.MarshalCanonical(meta)
	require.NoError(t, err)
	s := &data.Signed{Signed: (*json.RawMessage)(&b)}
	require.NoError(t, Sign(cs, s, []data.PublicKey{k, unknown}, 2, nil))
	s.Signatures = append(s.Signatures)
	err = VerifySignatures(s, roleWithKeys)
	require.IsType(t, ErrRoleThreshold{}, err)
	require.Len(t, s.Signatures, 2)
	for _, signature := range s.Signatures {
		if signature.KeyID == k.ID() {
			require.True(t, signature.IsValid)
		} else {
			require.False(t, signature.IsValid)
		}
	}
}
Пример #17
0
// Creates metadata in the following manner:
// - the snapshot has bad checksums for itself and for timestamp, to show that those aren't checked
// - snapshot has valid checksums for root, targets, and targets/other
// - snapshot doesn't have a checksum for targets/other/other, but targets/other/other is a valid
//   delegation role in targets/other and there is metadata for targets/other/other that is correctly
//   signed
func setupSnapshotChecksumming(t *testing.T, gun string) map[string][]byte {
	repo, _, err := testutils.EmptyRepo(gun, "targets/other", "targets/other/other")
	require.NoError(t, err)

	// add invalid checkums for all the other roles to timestamp too, and show that
	// cached items aren't checksummed against this
	fakeChecksum, err := data.NewFileMeta(bytes.NewBuffer([]byte("fake")), notary.SHA256, notary.SHA512)
	require.NoError(t, err)
	// fake the snapshot and timestamp checksums
	repo.Snapshot.Signed.Meta[data.CanonicalSnapshotRole] = fakeChecksum
	repo.Snapshot.Signed.Meta[data.CanonicalTimestampRole] = fakeChecksum

	meta, err := testutils.SignAndSerialize(repo)
	require.NoError(t, err)
	// ensure that the fake metadata for other roles wasn't destroyed by signing
	require.Len(t, repo.Snapshot.Signed.Meta, 5)

	// create delegation metadata that should not be in snapshot, but has a valid role and signature
	_, err = repo.InitTargets("targets/other/other")
	require.NoError(t, err)
	s, err := repo.SignTargets("targets/other/other", data.DefaultExpires(data.CanonicalTargetsRole))
	require.NoError(t, err)
	meta["targets/other/other"], err = json.Marshal(s)
	require.NoError(t, err)

	return meta
}
Пример #18
0
func TestMoreThanEnoughSigs(t *testing.T) {
	cs := NewEd25519()
	k1, err := cs.Create("root", data.ED25519Key)
	assert.NoError(t, err)
	k2, err := cs.Create("root", data.ED25519Key)
	assert.NoError(t, err)
	r, err := data.NewRole(
		"root",
		1,
		[]string{k1.ID(), k2.ID()},
		nil,
		nil,
	)
	assert.NoError(t, err)
	db := keys.NewDB()
	assert.NoError(t, err)
	db.AddKey(k1)
	db.AddKey(k2)
	err = db.AddRole(r)
	assert.NoError(t, err)
	meta := &data.SignedCommon{Type: "Root", Version: 1, Expires: data.DefaultExpires("root")}

	b, err := json.MarshalCanonical(meta)
	assert.NoError(t, err)
	s := &data.Signed{Signed: b}
	Sign(cs, s, k1, k2)
	assert.Equal(t, 2, len(s.Signatures))
	err = Verify(s, "root", 1, db)
	assert.NoError(t, err)
}
Пример #19
0
func (r *NotaryRepository) saveMetadata() error {
	logrus.Debugf("Saving changes to Trusted Collection.")

	signedRoot, err := r.tufRepo.SignRoot(data.DefaultExpires("root"))
	if err != nil {
		return err
	}
	rootJSON, err := json.Marshal(signedRoot)
	if err != nil {
		return err
	}

	targetsToSave := make(map[string][]byte)
	for t := range r.tufRepo.Targets {
		signedTargets, err := r.tufRepo.SignTargets(t, data.DefaultExpires("targets"))
		if err != nil {
			return err
		}
		targetsJSON, err := json.Marshal(signedTargets)
		if err != nil {
			return err
		}
		targetsToSave[t] = targetsJSON
	}

	signedSnapshot, err := r.tufRepo.SignSnapshot(data.DefaultExpires("snapshot"))
	if err != nil {
		return err
	}
	snapshotJSON, err := json.Marshal(signedSnapshot)
	if err != nil {
		return err
	}

	err = r.fileStore.SetMeta("root", rootJSON)
	if err != nil {
		return err
	}

	for role, blob := range targetsToSave {
		parentDir := filepath.Dir(role)
		os.MkdirAll(parentDir, 0755)
		r.fileStore.SetMeta(role, blob)
	}

	return r.fileStore.SetMeta("snapshot", snapshotJSON)
}
Пример #20
0
func TestValidateRootRotation(t *testing.T) {
	repo, crypto, err := testutils.EmptyRepo("docker.com/notary")
	assert.NoError(t, err)
	store := storage.NewMemStorage()

	r, tg, sn, ts, err := testutils.Sign(repo)
	assert.NoError(t, err)
	root, targets, snapshot, timestamp, err := getUpdates(r, tg, sn, ts)
	assert.NoError(t, err)

	store.UpdateCurrent("testGUN", root)

	oldRootRole := repo.Root.Signed.Roles["root"]
	oldRootKey := repo.Root.Signed.Keys[oldRootRole.KeyIDs[0]]

	rootKey, err := crypto.Create("root", data.ED25519Key)
	assert.NoError(t, err)
	rootRole, err := data.NewRole("root", 1, []string{rootKey.ID()}, nil)
	assert.NoError(t, err)

	delete(repo.Root.Signed.Keys, oldRootRole.KeyIDs[0])

	repo.Root.Signed.Roles["root"] = &rootRole.RootRole
	repo.Root.Signed.Keys[rootKey.ID()] = rootKey

	r, err = repo.SignRoot(data.DefaultExpires(data.CanonicalRootRole))
	assert.NoError(t, err)
	err = signed.Sign(crypto, r, rootKey, oldRootKey)
	assert.NoError(t, err)

	rt, err := data.RootFromSigned(r)
	assert.NoError(t, err)
	repo.SetRoot(rt)

	sn, err = repo.SignSnapshot(data.DefaultExpires(data.CanonicalSnapshotRole))
	assert.NoError(t, err)
	root, targets, snapshot, timestamp, err = getUpdates(r, tg, sn, ts)
	assert.NoError(t, err)

	updates := []storage.MetaUpdate{root, targets, snapshot, timestamp}

	copyTimestampKey(t, repo, store, "testGUN")
	_, err = validateUpdate(crypto, "testGUN", updates, store)
	assert.NoError(t, err)
}
Пример #21
0
// Sign signs all top level roles in a repo in the appropriate order
func Sign(repo *tuf.Repo) (root, targets, snapshot, timestamp *data.Signed, err error) {
	root, err = repo.SignRoot(data.DefaultExpires("root"))
	if err != nil {
		return nil, nil, nil, nil, err
	}
	targets, err = repo.SignTargets("targets", data.DefaultExpires("targets"))
	if err != nil {
		return nil, nil, nil, nil, err
	}
	snapshot, err = repo.SignSnapshot(data.DefaultExpires("snapshot"))
	if err != nil {
		return nil, nil, nil, nil, err
	}
	timestamp, err = repo.SignTimestamp(data.DefaultExpires("timestamp"))
	if err != nil {
		return nil, nil, nil, nil, err
	}
	return
}
Пример #22
0
func TestDownloadTargetsHappy(t *testing.T) {
	kdb, repo, _ := testutils.EmptyRepo()
	localStorage := store.NewMemoryStore(nil, nil)
	remoteStorage := store.NewMemoryStore(nil, nil)
	client := NewClient(repo, remoteStorage, kdb, localStorage)

	signedOrig, err := repo.SignTargets("targets", data.DefaultExpires("targets"))
	assert.NoError(t, err)
	orig, err := json.Marshal(signedOrig)
	assert.NoError(t, err)
	err = remoteStorage.SetMeta("targets", orig)
	assert.NoError(t, err)

	// call repo.SignSnapshot to update the targets role in the snapshot
	repo.SignSnapshot(data.DefaultExpires("snapshot"))

	err = client.downloadTargets("targets")
	assert.NoError(t, err)
}
Пример #23
0
// Sign signs all top level roles in a repo in the appropriate order
func Sign(repo *tuf.Repo) (root, targets, snapshot, timestamp *data.Signed, err error) {
	root, err = repo.SignRoot(data.DefaultExpires("root"))
	if _, ok := err.(data.ErrInvalidRole); err != nil && !ok {
		return nil, nil, nil, nil, err
	}
	targets, err = repo.SignTargets("targets", data.DefaultExpires("targets"))
	if _, ok := err.(data.ErrInvalidRole); err != nil && !ok {
		return nil, nil, nil, nil, err
	}
	snapshot, err = repo.SignSnapshot(data.DefaultExpires("snapshot"))
	if _, ok := err.(data.ErrInvalidRole); err != nil && !ok {
		return nil, nil, nil, nil, err
	}
	timestamp, err = repo.SignTimestamp(data.DefaultExpires("timestamp"))
	if _, ok := err.(data.ErrInvalidRole); err != nil && !ok {
		return nil, nil, nil, nil, err
	}
	return
}
Пример #24
0
func TestUpdateDownloadRootHappy(t *testing.T) {
	kdb, repo, _ := testutils.EmptyRepo()
	localStorage := store.NewMemoryStore(nil, nil)
	remoteStorage := store.NewMemoryStore(nil, nil)
	client := NewClient(repo, remoteStorage, kdb, localStorage)

	// create and "upload" sample root, snapshot, and timestamp
	signedOrig, err := repo.SignRoot(data.DefaultExpires("root"))
	assert.NoError(t, err)
	orig, err := json.Marshal(signedOrig)
	assert.NoError(t, err)
	err = remoteStorage.SetMeta("root", orig)
	assert.NoError(t, err)

	// sign snapshot to make root meta in snapshot get updated
	signedOrig, err = repo.SignSnapshot(data.DefaultExpires("snapshot"))

	err = client.downloadRoot()
	assert.NoError(t, err)
}
Пример #25
0
// signs and serializes the metadata for a canonical role in a tuf repo to JSON
func serializeCanonicalRole(tufRepo *tuf.Repo, role string) (out []byte, err error) {
	var s *data.Signed
	switch {
	case role == data.CanonicalRootRole:
		s, err = tufRepo.SignRoot(data.DefaultExpires(role))
	case role == data.CanonicalSnapshotRole:
		s, err = tufRepo.SignSnapshot(data.DefaultExpires(role))
	case tufRepo.Targets[role] != nil:
		s, err = tufRepo.SignTargets(
			role, data.DefaultExpires(data.CanonicalTargetsRole))
	default:
		err = fmt.Errorf("%s not supported role to sign on the client", role)
	}

	if err != nil {
		return
	}

	return json.Marshal(s)
}
Пример #26
0
// TestDownloadTargetsLarge: Check that we can download very large targets metadata files,
// which may be caused by adding a large number of targets.
// This test is slow, so it will not run in short mode.
func TestDownloadTargetsLarge(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode")
	}

	repo, _, err := testutils.EmptyRepo("docker.com/notary")
	assert.NoError(t, err)
	localStorage := store.NewMemoryStore(nil)
	remoteStorage := store.NewMemoryStore(nil)
	client := NewClient(repo, remoteStorage, localStorage)

	hash := sha256.Sum256([]byte{})
	f := data.FileMeta{
		Length: 1,
		Hashes: map[string][]byte{
			"sha256": hash[:],
		},
	}
	// Add a ton of target files to the targets role to make this targets metadata huge
	// 75,000 targets results in > 5MB (~6.5MB on recent runs)
	for i := 0; i < 75000; i++ {
		_, err = repo.AddTargets(data.CanonicalTargetsRole, data.Files{strconv.Itoa(i): f})
		assert.NoError(t, err)
	}

	signedOrig, err := repo.SignTargets("targets", data.DefaultExpires("targets"))
	assert.NoError(t, err)
	orig, err := json.Marshal(signedOrig)
	assert.NoError(t, err)
	err = remoteStorage.SetMeta("targets", orig)
	assert.NoError(t, err)

	// call repo.SignSnapshot to update the targets role in the snapshot
	repo.SignSnapshot(data.DefaultExpires("snapshot"))

	// Clear the cache to force an online download
	client.cache.RemoveAll()

	err = client.downloadTargets("targets")
	assert.NoError(t, err)
}
Пример #27
0
func TestVerifyExpiry(t *testing.T) {
	tufType := data.TUFTypes[data.CanonicalRootRole]
	notExpired := data.DefaultExpires(data.CanonicalRootRole)
	expired := time.Now().Add(-1 * notary.Year)

	require.NoError(t, VerifyExpiry(
		&data.SignedCommon{Type: tufType, Version: 1, Expires: notExpired}, data.CanonicalRootRole))
	err := VerifyExpiry(
		&data.SignedCommon{Type: tufType, Version: 1, Expires: expired}, data.CanonicalRootRole)
	require.Error(t, err)
	require.IsType(t, ErrExpired{}, err)
}
Пример #28
0
// TestDownloadSnapshotLarge: Check that we can download very large snapshot metadata files,
// which may be caused by adding a large number of delegations.
// This test is slow, so it will not run in short mode.
func TestDownloadSnapshotLarge(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode")
	}
	repo, _, err := testutils.EmptyRepo("docker.com/notary")
	assert.NoError(t, err)
	localStorage := store.NewMemoryStore(nil)
	remoteStorage := store.NewMemoryStore(nil)
	client := NewClient(repo, remoteStorage, localStorage)

	// Add a ton of empty delegation roles to targets to make snapshot data huge
	// This can also be done by adding legitimate delegations but it will be much slower
	// 75,000 delegation roles results in > 5MB (~7.3MB on recent runs)
	for i := 0; i < 75000; i++ {
		newRole := &data.SignedTargets{}
		repo.Targets[fmt.Sprintf("targets/%d", i)] = newRole
	}

	// create and "upload" sample snapshot and timestamp
	signedOrig, err := repo.SignSnapshot(data.DefaultExpires("snapshot"))
	assert.NoError(t, err)
	orig, err := json.Marshal(signedOrig)
	assert.NoError(t, err)
	err = remoteStorage.SetMeta("snapshot", orig)
	assert.NoError(t, err)

	signedOrig, err = repo.SignTimestamp(data.DefaultExpires("timestamp"))
	assert.NoError(t, err)
	orig, err = json.Marshal(signedOrig)
	assert.NoError(t, err)
	err = remoteStorage.SetMeta("timestamp", orig)
	assert.NoError(t, err)

	// Clear the cache to force an online download
	client.cache.RemoveAll()

	err = client.downloadSnapshot()
	assert.NoError(t, err)
}
Пример #29
0
func TestValidateTargetsLoadParent(t *testing.T) {
	_, baseRepo, cs, err := testutils.EmptyRepo("docker.com/notary")
	assert.NoError(t, err)
	store := storage.NewMemStorage()

	k, err := cs.Create("targets/level1", data.ED25519Key)
	assert.NoError(t, err)
	r, err := data.NewRole("targets/level1", 1, []string{k.ID()}, []string{""}, nil)
	assert.NoError(t, err)

	err = baseRepo.UpdateDelegations(r, []data.PublicKey{k})
	assert.NoError(t, err)

	// no targets file is created for the new delegations, so force one
	baseRepo.InitTargets("targets/level1")

	// we're not going to validate things loaded from storage, so no need
	// to sign the base targets, just Marshal it and set it into storage
	tgtsJSON, err := json.Marshal(baseRepo.Targets["targets"])
	assert.NoError(t, err)
	update := storage.MetaUpdate{
		Role:    data.CanonicalTargetsRole,
		Version: 1,
		Data:    tgtsJSON,
	}
	store.UpdateCurrent("gun", update)

	// generate the update object we're doing to use to call loadAndValidateTargets
	del, err := baseRepo.SignTargets("targets/level1", data.DefaultExpires(data.CanonicalTargetsRole))
	assert.NoError(t, err)
	delJSON, err := json.Marshal(del)
	assert.NoError(t, err)

	delUpdate := storage.MetaUpdate{
		Role:    "targets/level1",
		Version: 1,
		Data:    delJSON,
	}

	roles := map[string]storage.MetaUpdate{"targets/level1": delUpdate}

	kdb := keys.NewDB()
	valRepo := tuf.NewRepo(kdb, nil)
	valRepo.SetRoot(baseRepo.Root)

	updates, err := loadAndValidateTargets("gun", valRepo, roles, kdb, store)
	assert.NoError(t, err)
	assert.Len(t, updates, 1)
	assert.Equal(t, "targets/level1", updates[0].Role)
	assert.Equal(t, delJSON, updates[0].Data)
}
Пример #30
0
func TestDownloadSnapshotBadChecksum(t *testing.T) {
	kdb, repo, _ := testutils.EmptyRepo()
	localStorage := store.NewMemoryStore(nil, nil)
	remoteStorage := store.NewMemoryStore(nil, nil)
	client := NewClient(repo, remoteStorage, kdb, localStorage)

	// sign timestamp to ensure it has a checksum for snapshot
	_, err := repo.SignTimestamp(data.DefaultExpires("timestamp"))
	assert.NoError(t, err)

	// create and "upload" sample snapshot and timestamp
	signedOrig, err := repo.SignSnapshot(data.DefaultExpires("snapshot"))
	assert.NoError(t, err)
	orig, err := json.Marshal(signedOrig)
	assert.NoError(t, err)
	err = remoteStorage.SetMeta("snapshot", orig)
	assert.NoError(t, err)

	// by not signing timestamp again we ensure it has the wrong checksum

	err = client.downloadSnapshot()
	assert.IsType(t, ErrChecksumMismatch{}, err)
}