Skip to content

Commit

Permalink
Use keyinfo instead of strings, bring back tests, and add migration to
Browse files Browse the repository at this point in the history
drop mysql table

Signed-off-by: Riyaz Faizullabhoy <riyaz.faizullabhoy@docker.com>
  • Loading branch information
riyazdf committed Aug 1, 2016
1 parent e9169f2 commit e5bbe16
Show file tree
Hide file tree
Showing 9 changed files with 152 additions and 192 deletions.
4 changes: 2 additions & 2 deletions cmd/notary-signer/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func passphraseRetriever(keyName, alias string, createNew bool, attempts int) (p
}

type markActive func(string) error
type pendingKeyFunc func(string, string) (data.PublicKey, error)
type pendingKeyFunc func(trustmanager.KeyInfo) (data.PublicKey, error)

// Reads the configuration file for storage setup, and sets up the cryptoservice
// mapping
Expand All @@ -112,7 +112,7 @@ func setUpCryptoservices(configuration *viper.Viper, allowedBackends []string, d

var keyStore trustmanager.KeyStore
var markFunc = func(string) error { return nil }
var pendingKeyFunc = func(string, string) (data.PublicKey, error) { return nil, fmt.Errorf("no pending key") }
var pendingKeyFunc = func(trustmanager.KeyInfo) (data.PublicKey, error) { return nil, fmt.Errorf("no pending key") }
switch backend {
case notary.MemoryBackend:
keyStore = trustmanager.NewKeyMemoryStore(
Expand Down
3 changes: 2 additions & 1 deletion cmd/notary-signer/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,12 @@ func TestSetupCryptoServicesDBStoreSuccess(t *testing.T) {
func TestSetupCryptoServicesMemoryStore(t *testing.T) {
config := configure(fmt.Sprintf(`{"storage": {"backend": "%s"}}`,
notary.MemoryBackend))
cryptoServices, markFunc, _, err := setUpCryptoservices(config,
cryptoServices, markFunc, pendingKeyFunc, err := setUpCryptoservices(config,
[]string{notary.SQLiteBackend, notary.MemoryBackend}, false)
require.NoError(t, err)
require.Len(t, cryptoServices, 2)
require.NotNil(t, markFunc)
require.NotNil(t, pendingKeyFunc)

edService, ok := cryptoServices[data.ED25519Key]
require.True(t, ok)
Expand Down
1 change: 1 addition & 0 deletions migrations/server/mysql/0004_drop_timestamp_key.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE `timestamp_keys`;
319 changes: 138 additions & 181 deletions server/handlers/validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -670,187 +670,144 @@ func TestValidateSnapshotMissingNoSnapshotKey(t *testing.T) {
require.IsType(t, validation.ErrBadHierarchy{}, err)
}

// TODO(riyazdf): Need to update these tests with the new behavior
//func TestValidateSnapshotGenerateNoPrev(t *testing.T) {
// gun := "docker.com/notary"
// repo, cs, err := testutils.EmptyRepo(gun)
// require.NoError(t, err)
// store := storage.NewMemStorage()
// snapRole, err := repo.GetBaseRole(data.CanonicalSnapshotRole)
// require.NoError(t, err)
//
// for _, k := range snapRole.Keys {
// err := store.SetKey(gun, data.CanonicalSnapshotRole, k.Algorithm(), k.Public())
// require.NoError(t, err)
// }
//
// r, tg, sn, ts, err := testutils.Sign(repo)
// require.NoError(t, err)
// root, targets, _, _, err := getUpdates(r, tg, sn, ts)
// require.NoError(t, err)
//
// updates := []storage.MetaUpdate{root, targets}
//
// serverCrypto := testutils.CopyKeys(t, cs, data.CanonicalTimestampRole, data.CanonicalSnapshotRole)
// _, err = validateUpdate(serverCrypto, gun, updates, store)
// require.NoError(t, err)
//}
//
//func TestValidateSnapshotGenerateWithPrev(t *testing.T) {
// gun := "docker.com/notary"
// repo, cs, err := testutils.EmptyRepo(gun)
// require.NoError(t, err)
// store := storage.NewMemStorage()
// snapRole, err := repo.GetBaseRole(data.CanonicalSnapshotRole)
// require.NoError(t, err)
//
// for _, k := range snapRole.Keys {
// err := store.SetKey(gun, data.CanonicalSnapshotRole, k.Algorithm(), k.Public())
// require.NoError(t, err)
// }
//
// r, tg, sn, ts, err := testutils.Sign(repo)
// require.NoError(t, err)
// root, targets, snapshot, _, err := getUpdates(r, tg, sn, ts)
// require.NoError(t, err)
//
// updates := []storage.MetaUpdate{root, targets}
//
// // set the current snapshot in the store manually so we find it when generating
// // the next version
// store.UpdateCurrent(gun, snapshot)
//
// prev, err := data.SnapshotFromSigned(sn)
// require.NoError(t, err)
//
// serverCrypto := testutils.CopyKeys(t, cs, data.CanonicalTimestampRole, data.CanonicalSnapshotRole)
// updates, err = validateUpdate(serverCrypto, gun, updates, store)
// require.NoError(t, err)
//
// for _, u := range updates {
// if u.Role == data.CanonicalSnapshotRole {
// curr := &data.SignedSnapshot{}
// err = json.Unmarshal(u.Data, curr)
// require.NoError(t, err)
// require.Equal(t, prev.Signed.Version+1, curr.Signed.Version)
// require.Equal(t, u.Version, curr.Signed.Version)
// }
// }
//}

//func TestValidateSnapshotGeneratePrevCorrupt(t *testing.T) {
// gun := "docker.com/notary"
// repo, cs, err := testutils.EmptyRepo(gun)
// require.NoError(t, err)
// store := storage.NewMemStorage()
// snapRole, err := repo.GetBaseRole(data.CanonicalSnapshotRole)
// require.NoError(t, err)
//
// for _, k := range snapRole.Keys {
// err := store.SetKey(gun, data.CanonicalSnapshotRole, k.Algorithm(), k.Public())
// require.NoError(t, err)
// }
//
// r, tg, sn, ts, err := testutils.Sign(repo)
// require.NoError(t, err)
// root, targets, snapshot, _, err := getUpdates(r, tg, sn, ts)
// require.NoError(t, err)
//
// updates := []storage.MetaUpdate{root, targets}
//
// // corrupt the JSON structure of prev snapshot
// snapshot.Data = snapshot.Data[1:]
// // set the current snapshot in the store manually so we find it when generating
// // the next version
// store.UpdateCurrent(gun, snapshot)
//
// serverCrypto := testutils.CopyKeys(t, cs, data.CanonicalTimestampRole, data.CanonicalSnapshotRole)
// _, err = validateUpdate(serverCrypto, gun, updates, store)
// require.Error(t, err)
// require.IsType(t, &json.SyntaxError{}, err)
//}
//
//// Store is broken when getting the current snapshot
//func TestValidateSnapshotGenerateStoreGetCurrentSnapshotBroken(t *testing.T) {
// gun := "docker.com/notary"
// repo, cs, err := testutils.EmptyRepo(gun)
// require.NoError(t, err)
// store := getFailStore{
// MetaStore: storage.NewMemStorage(),
// errsToReturn: map[string]error{data.CanonicalSnapshotRole: data.ErrNoSuchRole{}},
// }
// snapRole, err := repo.GetBaseRole(data.CanonicalSnapshotRole)
// require.NoError(t, err)
//
// for _, k := range snapRole.Keys {
// err := store.SetKey(gun, data.CanonicalSnapshotRole, k.Algorithm(), k.Public())
// require.NoError(t, err)
// }
//
// r, tg, sn, ts, err := testutils.Sign(repo)
// require.NoError(t, err)
// root, targets, _, _, err := getUpdates(r, tg, sn, ts)
// require.NoError(t, err)
//
// updates := []storage.MetaUpdate{root, targets}
//
// serverCrypto := testutils.CopyKeys(t, cs, data.CanonicalTimestampRole, data.CanonicalSnapshotRole)
// _, err = validateUpdate(serverCrypto, gun, updates, store)
// require.Error(t, err)
// require.IsType(t, data.ErrNoSuchRole{}, err)
//}
//
//func TestValidateSnapshotGenerateNoTargets(t *testing.T) {
// gun := "docker.com/notary"
// repo, cs, err := testutils.EmptyRepo(gun)
// require.NoError(t, err)
// store := storage.NewMemStorage()
// snapRole, err := repo.GetBaseRole(data.CanonicalSnapshotRole)
// require.NoError(t, err)
//
// for _, k := range snapRole.Keys {
// err := store.SetKey(gun, data.CanonicalSnapshotRole, k.Algorithm(), k.Public())
// require.NoError(t, err)
// }
//
// r, tg, sn, ts, err := testutils.Sign(repo)
// require.NoError(t, err)
// root, _, _, _, err := getUpdates(r, tg, sn, ts)
// require.NoError(t, err)
//
// updates := []storage.MetaUpdate{root}
//
// serverCrypto := testutils.CopyKeys(t, cs, data.CanonicalTimestampRole, data.CanonicalSnapshotRole)
// _, err = validateUpdate(serverCrypto, gun, updates, store)
// require.Error(t, err)
//}
//
//func TestValidateSnapshotGenerate(t *testing.T) {
// gun := "docker.com/notary"
// repo, cs, err := testutils.EmptyRepo(gun)
// require.NoError(t, err)
// store := storage.NewMemStorage()
// snapRole, err := repo.GetBaseRole(data.CanonicalSnapshotRole)
// require.NoError(t, err)
//
// for _, k := range snapRole.Keys {
// err := store.SetKey(gun, data.CanonicalSnapshotRole, k.Algorithm(), k.Public())
// require.NoError(t, err)
// }
//
// r, tg, sn, ts, err := testutils.Sign(repo)
// require.NoError(t, err)
// root, targets, _, _, err := getUpdates(r, tg, sn, ts)
// require.NoError(t, err)
//
// updates := []storage.MetaUpdate{targets}
//
// store.UpdateCurrent(gun, root)
//
// serverCrypto := testutils.CopyKeys(t, cs, data.CanonicalTimestampRole, data.CanonicalSnapshotRole)
// _, err = validateUpdate(serverCrypto, gun, updates, store)
// require.NoError(t, err)
//}
func TestValidateSnapshotGenerateNoPrev(t *testing.T) {
gun := "docker.com/notary"
repo, cs, err := testutils.EmptyRepo(gun)
require.NoError(t, err)
store := storage.NewMemStorage()

r, tg, sn, ts, err := testutils.Sign(repo)
require.NoError(t, err)
root, targets, _, _, err := getUpdates(r, tg, sn, ts)
require.NoError(t, err)

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

serverCrypto := testutils.CopyKeys(t, cs, data.CanonicalTimestampRole, data.CanonicalSnapshotRole)
_, err = validateUpdate(serverCrypto, gun, updates, store)
require.NoError(t, err)
}

func TestValidateSnapshotGenerateWithPrev(t *testing.T) {
gun := "docker.com/notary"
repo, cs, err := testutils.EmptyRepo(gun)
require.NoError(t, err)
store := storage.NewMemStorage()

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

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

// set the current snapshot in the store manually so we find it when generating
// the next version
store.UpdateCurrent(gun, snapshot)

prev, err := data.SnapshotFromSigned(sn)
require.NoError(t, err)

serverCrypto := testutils.CopyKeys(t, cs, data.CanonicalTimestampRole, data.CanonicalSnapshotRole)
updates, err = validateUpdate(serverCrypto, gun, updates, store)
require.NoError(t, err)

for _, u := range updates {
if u.Role == data.CanonicalSnapshotRole {
curr := &data.SignedSnapshot{}
err = json.Unmarshal(u.Data, curr)
require.NoError(t, err)
require.Equal(t, prev.Signed.Version+1, curr.Signed.Version)
require.Equal(t, u.Version, curr.Signed.Version)
}
}
}

func TestValidateSnapshotGeneratePrevCorrupt(t *testing.T) {
gun := "docker.com/notary"
repo, cs, err := testutils.EmptyRepo(gun)
require.NoError(t, err)
store := storage.NewMemStorage()

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

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

// corrupt the JSON structure of prev snapshot
snapshot.Data = snapshot.Data[1:]
// set the current snapshot in the store manually so we find it when generating
// the next version
store.UpdateCurrent(gun, snapshot)

serverCrypto := testutils.CopyKeys(t, cs, data.CanonicalTimestampRole, data.CanonicalSnapshotRole)
_, err = validateUpdate(serverCrypto, gun, updates, store)
require.Error(t, err)
require.IsType(t, &json.SyntaxError{}, err)
}

// Store is broken when getting the current snapshot
func TestValidateSnapshotGenerateStoreGetCurrentSnapshotBroken(t *testing.T) {
gun := "docker.com/notary"
repo, cs, err := testutils.EmptyRepo(gun)
require.NoError(t, err)
store := getFailStore{
MetaStore: storage.NewMemStorage(),
errsToReturn: map[string]error{data.CanonicalSnapshotRole: data.ErrNoSuchRole{}},
}

r, tg, sn, ts, err := testutils.Sign(repo)
require.NoError(t, err)
root, targets, _, _, err := getUpdates(r, tg, sn, ts)
require.NoError(t, err)

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

serverCrypto := testutils.CopyKeys(t, cs, data.CanonicalTimestampRole, data.CanonicalSnapshotRole)
_, err = validateUpdate(serverCrypto, gun, updates, store)
require.Error(t, err)
require.IsType(t, data.ErrNoSuchRole{}, err)
}

func TestValidateSnapshotGenerateNoTargets(t *testing.T) {
gun := "docker.com/notary"
repo, cs, err := testutils.EmptyRepo(gun)
require.NoError(t, err)
store := storage.NewMemStorage()

r, tg, sn, ts, err := testutils.Sign(repo)
require.NoError(t, err)
root, _, _, _, err := getUpdates(r, tg, sn, ts)
require.NoError(t, err)

updates := []storage.MetaUpdate{root}

serverCrypto := testutils.CopyKeys(t, cs, data.CanonicalTimestampRole, data.CanonicalSnapshotRole)
_, err = validateUpdate(serverCrypto, gun, updates, store)
require.Error(t, err)
}

func TestValidateSnapshotGenerate(t *testing.T) {
gun := "docker.com/notary"
repo, cs, err := testutils.EmptyRepo(gun)
require.NoError(t, err)
store := storage.NewMemStorage()

r, tg, sn, ts, err := testutils.Sign(repo)
require.NoError(t, err)
root, targets, _, _, err := getUpdates(r, tg, sn, ts)
require.NoError(t, err)

updates := []storage.MetaUpdate{targets}

store.UpdateCurrent(gun, root)

serverCrypto := testutils.CopyKeys(t, cs, data.CanonicalTimestampRole, data.CanonicalSnapshotRole)
_, err = validateUpdate(serverCrypto, gun, updates, store)
require.NoError(t, err)
}

// If there is no timestamp key in the store, validation fails. This could
// happen if pushing an existing repository from one server to another that
Expand Down
4 changes: 2 additions & 2 deletions signer/api/rpc_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
type KeyManagementServer struct {
CryptoServices signer.CryptoServiceIndex
HealthChecker func() map[string]string
PendingKeyFunc func(string, string) (data.PublicKey, error)
PendingKeyFunc func(trustmanager.KeyInfo) (data.PublicKey, error)
}

//SignerServer implements the SignerServer grpc interface
Expand All @@ -45,7 +45,7 @@ func (s *KeyManagementServer) CreateKey(ctx context.Context, req *pb.CreateKeyRe
var tufKey data.PublicKey
var err error

if tufKey, err = s.PendingKeyFunc(req.Gun, req.Role); err == nil {
if tufKey, err = s.PendingKeyFunc(trustmanager.KeyInfo{Gun: req.Gun, Role: req.Role}); err == nil {
logger.Debugf("CreateKey: found pending key for role %s GUN %s that will be used", req.Role, req.Gun)
} else {
tufKey, err = service.Create(req.Role, req.Gun, req.Algorithm)
Expand Down
4 changes: 2 additions & 2 deletions signer/keydbstore/rethink_keydbstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,9 +265,9 @@ func (rdb RethinkDBKeyStore) MarkActive(keyID string) error {
}

// GetPendingKey gets the public key component of a key that was created but never used for signing a given gun and role
func (rdb RethinkDBKeyStore) GetPendingKey(gun, role string) (data.PublicKey, error) {
func (rdb RethinkDBKeyStore) GetPendingKey(keyInfo trustmanager.KeyInfo) (data.PublicKey, error) {
dbPrivateKey := RDBPrivateKey{}
res, err := gorethink.DB(rdb.dbName).Table(dbPrivateKey.TableName()).Filter(gorethink.Row.Field("gun").Eq(gun)).Filter(gorethink.Row.Field("role").Eq(role)).Filter(gorethink.Row.Field("last_used").Eq(time.Time{})).Run(rdb.sess)
res, err := gorethink.DB(rdb.dbName).Table(dbPrivateKey.TableName()).Filter(gorethink.Row.Field("gun").Eq(keyInfo.Gun)).Filter(gorethink.Row.Field("role").Eq(keyInfo.Role)).Filter(gorethink.Row.Field("last_used").Eq(time.Time{})).Run(rdb.sess)
if err != nil {
return nil, err
}
Expand Down
Loading

0 comments on commit e5bbe16

Please sign in to comment.