cleaning up cache vs filestore

Signed-off-by: David Lawrence <david.lawrence@docker.com> (github: endophage)
This commit is contained in:
David Lawrence 2015-07-18 22:50:44 -07:00
parent 9b604d0a6c
commit 20b60d9cc2
3 changed files with 213 additions and 40 deletions

View File

@ -0,0 +1,190 @@
package client
import (
"testing"
"github.com/Sirupsen/logrus"
tuf "github.com/endophage/gotuf"
"github.com/stretchr/testify/assert"
"github.com/endophage/gotuf/data"
"github.com/endophage/gotuf/keys"
"github.com/endophage/gotuf/signed"
"github.com/endophage/gotuf/store"
)
func TestRotation(t *testing.T) {
kdb := keys.NewDB()
signer := signed.NewEd25519()
repo := tuf.NewTufRepo(kdb, signer)
remote := store.NewMemoryStore(nil, nil)
cache := store.NewMemoryStore(nil, nil)
// Generate initial root key and role and add to key DB
rootKey, err := signer.Create("root", data.ED25519Key)
assert.NoError(t, err, "Error creating root key")
rootRole, err := data.NewRole("root", 1, []string{rootKey.ID()}, nil, nil)
assert.NoError(t, err, "Error creating root role")
kdb.AddKey(rootKey)
err = kdb.AddRole(rootRole)
assert.NoError(t, err, "Error adding root role to db")
// Generate new key and role. These will appear in the root.json
// but will not be added to the keyDB.
replacementKey, err := signer.Create("root", data.ED25519Key)
assert.NoError(t, err, "Error creating replacement root key")
replacementRole, err := data.NewRole("root", 1, []string{replacementKey.ID()}, nil, nil)
assert.NoError(t, err, "Error creating replacement root role")
// Generate a new root with the replacement key and role
testRoot, err := data.NewRoot(
map[string]data.PublicKey{replacementKey.ID(): replacementKey},
map[string]*data.RootRole{"root": &replacementRole.RootRole},
false,
)
assert.NoError(t, err, "Failed to create new root")
// Sign testRoot with both old and new keys
signedRoot, err := testRoot.ToSigned()
err = signed.Sign(signer, signedRoot, rootKey, replacementKey)
assert.NoError(t, err, "Failed to sign root")
var origKeySig bool
var replKeySig bool
for _, sig := range signedRoot.Signatures {
if sig.KeyID == rootKey.ID() {
origKeySig = true
} else if sig.KeyID == replacementKey.ID() {
replKeySig = true
}
}
assert.True(t, origKeySig, "Original root key signature not present")
assert.True(t, replKeySig, "Replacement root key signature not present")
client := NewClient(repo, remote, kdb, cache)
err = client.verifyRoot("root", signedRoot, 0)
assert.NoError(t, err, "Failed to verify key rotated root")
}
func TestRotationNewSigMissing(t *testing.T) {
logrus.SetLevel(logrus.DebugLevel)
kdb := keys.NewDB()
signer := signed.NewEd25519()
repo := tuf.NewTufRepo(kdb, signer)
remote := store.NewMemoryStore(nil, nil)
cache := store.NewMemoryStore(nil, nil)
// Generate initial root key and role and add to key DB
rootKey, err := signer.Create("root", data.ED25519Key)
assert.NoError(t, err, "Error creating root key")
rootRole, err := data.NewRole("root", 1, []string{rootKey.ID()}, nil, nil)
assert.NoError(t, err, "Error creating root role")
kdb.AddKey(rootKey)
err = kdb.AddRole(rootRole)
assert.NoError(t, err, "Error adding root role to db")
// Generate new key and role. These will appear in the root.json
// but will not be added to the keyDB.
replacementKey, err := signer.Create("root", data.ED25519Key)
assert.NoError(t, err, "Error creating replacement root key")
replacementRole, err := data.NewRole("root", 1, []string{replacementKey.ID()}, nil, nil)
assert.NoError(t, err, "Error creating replacement root role")
assert.NotEqual(t, rootKey.ID(), replacementKey.ID(), "Key IDs are the same")
// Generate a new root with the replacement key and role
testRoot, err := data.NewRoot(
map[string]data.PublicKey{replacementKey.ID(): replacementKey},
map[string]*data.RootRole{"root": &replacementRole.RootRole},
false,
)
assert.NoError(t, err, "Failed to create new root")
_, ok := testRoot.Signed.Keys[rootKey.ID()]
assert.False(t, ok, "Old root key appeared in test root")
// Sign testRoot with both old and new keys
signedRoot, err := testRoot.ToSigned()
err = signed.Sign(signer, signedRoot, rootKey)
assert.NoError(t, err, "Failed to sign root")
var origKeySig bool
var replKeySig bool
for _, sig := range signedRoot.Signatures {
if sig.KeyID == rootKey.ID() {
origKeySig = true
} else if sig.KeyID == replacementKey.ID() {
replKeySig = true
}
}
assert.True(t, origKeySig, "Original root key signature not present")
assert.False(t, replKeySig, "Replacement root key signature was present and shouldn't be")
client := NewClient(repo, remote, kdb, cache)
err = client.verifyRoot("root", signedRoot, 0)
assert.Error(t, err, "Should have errored on verify as replacement signature was missing.")
}
func TestRotationOldSigMissing(t *testing.T) {
logrus.SetLevel(logrus.DebugLevel)
kdb := keys.NewDB()
signer := signed.NewEd25519()
repo := tuf.NewTufRepo(kdb, signer)
remote := store.NewMemoryStore(nil, nil)
cache := store.NewMemoryStore(nil, nil)
// Generate initial root key and role and add to key DB
rootKey, err := signer.Create("root", data.ED25519Key)
assert.NoError(t, err, "Error creating root key")
rootRole, err := data.NewRole("root", 1, []string{rootKey.ID()}, nil, nil)
assert.NoError(t, err, "Error creating root role")
kdb.AddKey(rootKey)
err = kdb.AddRole(rootRole)
assert.NoError(t, err, "Error adding root role to db")
// Generate new key and role. These will appear in the root.json
// but will not be added to the keyDB.
replacementKey, err := signer.Create("root", data.ED25519Key)
assert.NoError(t, err, "Error creating replacement root key")
replacementRole, err := data.NewRole("root", 1, []string{replacementKey.ID()}, nil, nil)
assert.NoError(t, err, "Error creating replacement root role")
assert.NotEqual(t, rootKey.ID(), replacementKey.ID(), "Key IDs are the same")
// Generate a new root with the replacement key and role
testRoot, err := data.NewRoot(
map[string]data.PublicKey{replacementKey.ID(): replacementKey},
map[string]*data.RootRole{"root": &replacementRole.RootRole},
false,
)
assert.NoError(t, err, "Failed to create new root")
_, ok := testRoot.Signed.Keys[rootKey.ID()]
assert.False(t, ok, "Old root key appeared in test root")
// Sign testRoot with both old and new keys
signedRoot, err := testRoot.ToSigned()
err = signed.Sign(signer, signedRoot, replacementKey)
assert.NoError(t, err, "Failed to sign root")
var origKeySig bool
var replKeySig bool
for _, sig := range signedRoot.Signatures {
if sig.KeyID == rootKey.ID() {
origKeySig = true
} else if sig.KeyID == replacementKey.ID() {
replKeySig = true
}
}
assert.False(t, origKeySig, "Original root key signature was present and shouldn't be")
assert.True(t, replKeySig, "Replacement root key signature was not present")
client := NewClient(repo, remote, kdb, cache)
err = client.verifyRoot("root", signedRoot, 0)
assert.Error(t, err, "Should have errored on verify as replacement signature was missing.")
}

View File

@ -103,6 +103,17 @@ func NewNotaryRepository(baseDir, gun, baseURL string, rt http.RoundTripper) (*N
KeyStoreManager: keyStoreManager, KeyStoreManager: keyStoreManager,
} }
fileStore, err := store.NewFilesystemStore(
nRepo.tufRepoPath,
"metadata",
"json",
"",
)
if err != nil {
return nil, err
}
nRepo.fileStore = fileStore
return nRepo, nil return nRepo, nil
} }
@ -210,16 +221,6 @@ func (r *NotaryRepository) Initialize(uCryptoService *cryptoservice.UnlockedCryp
r.tufRepo = tuf.NewTufRepo(kdb, r.cryptoService) r.tufRepo = tuf.NewTufRepo(kdb, r.cryptoService)
r.fileStore, err = store.NewFilesystemStore(
r.tufRepoPath,
"metadata",
"json",
"",
)
if err != nil {
return err
}
if err := r.tufRepo.InitRepo(false); err != nil { if err := r.tufRepo.InitRepo(false); err != nil {
return err return err
} }
@ -421,21 +422,11 @@ func (r *NotaryRepository) Publish(getPass passwordRetriever) error {
} }
func (r *NotaryRepository) bootstrapRepo() error { func (r *NotaryRepository) bootstrapRepo() error {
fileStore, err := store.NewFilesystemStore(
r.tufRepoPath,
"metadata",
"json",
"",
)
if err != nil {
return err
}
kdb := keys.NewDB() kdb := keys.NewDB()
tufRepo := tuf.NewTufRepo(kdb, r.cryptoService) tufRepo := tuf.NewTufRepo(kdb, r.cryptoService)
logrus.Debugf("Loading trusted collection.") logrus.Debugf("Loading trusted collection.")
rootJSON, err := fileStore.GetMeta("root", 0) rootJSON, err := r.fileStore.GetMeta("root", 0)
if err != nil { if err != nil {
return err return err
} }
@ -445,7 +436,7 @@ func (r *NotaryRepository) bootstrapRepo() error {
return err return err
} }
tufRepo.SetRoot(root) tufRepo.SetRoot(root)
targetsJSON, err := fileStore.GetMeta("targets", 0) targetsJSON, err := r.fileStore.GetMeta("targets", 0)
if err != nil { if err != nil {
return err return err
} }
@ -455,7 +446,7 @@ func (r *NotaryRepository) bootstrapRepo() error {
return err return err
} }
tufRepo.SetTargets("targets", targets) tufRepo.SetTargets("targets", targets)
snapshotJSON, err := fileStore.GetMeta("snapshot", 0) snapshotJSON, err := r.fileStore.GetMeta("snapshot", 0)
if err != nil { if err != nil {
return err return err
} }
@ -467,7 +458,6 @@ func (r *NotaryRepository) bootstrapRepo() error {
tufRepo.SetSnapshot(snapshot) tufRepo.SetSnapshot(snapshot)
r.tufRepo = tufRepo r.tufRepo = tufRepo
r.fileStore = fileStore
return nil return nil
} }
@ -506,19 +496,7 @@ func (r *NotaryRepository) snapshot() error {
} }
func (r *NotaryRepository) bootstrapClient() (*tufclient.Client, error) { func (r *NotaryRepository) bootstrapClient() (*tufclient.Client, error) {
var cache store.MetadataStore
cache, err := store.NewFilesystemStore(
filepath.Join(r.tufRepoPath, "cache"),
"metadata",
"json",
"",
)
if err != nil {
cache = store.NewMemoryStore(nil, nil)
}
var rootJSON []byte var rootJSON []byte
err = nil
remote, err := getRemoteStore(r.baseURL, r.gun, r.roundTrip) remote, err := getRemoteStore(r.baseURL, r.gun, r.roundTrip)
if err == nil { if err == nil {
// if remote store successfully set up, try and get root from remote // if remote store successfully set up, try and get root from remote
@ -528,7 +506,12 @@ func (r *NotaryRepository) bootstrapClient() (*tufclient.Client, error) {
// if remote store couldn't be setup, or we failed to get a root from it // if remote store couldn't be setup, or we failed to get a root from it
// load the root from cache (offline operation) // load the root from cache (offline operation)
if err != nil { if err != nil {
rootJSON, err = cache.GetMeta("root", maxSize) if err, ok := err.(*store.ErrMetaNotFound); ok {
// if the error was MetaNotFound then we successfully contacted
// the store and it doesn't know about the repo.
return nil, err
}
rootJSON, err = r.fileStore.GetMeta("root", maxSize)
if err != nil { if err != nil {
// if cache didn't return a root, we cannot proceed // if cache didn't return a root, we cannot proceed
return nil, &store.ErrMetaNotFound{} return nil, &store.ErrMetaNotFound{}
@ -557,6 +540,6 @@ func (r *NotaryRepository) bootstrapClient() (*tufclient.Client, error) {
r.tufRepo, r.tufRepo,
remote, remote,
kdb, kdb,
cache, r.fileStore,
), nil ), nil
} }

View File

@ -64,10 +64,10 @@ func (st *MemStorage) GetCurrent(gun, role string) (data []byte, err error) {
st.lock.Lock() st.lock.Lock()
defer st.lock.Unlock() defer st.lock.Unlock()
space, ok := st.tufMeta[id] space, ok := st.tufMeta[id]
if !ok { if !ok || len(space) == 0 {
return nil, &ErrNotFound{} return nil, &ErrNotFound{}
} }
return space[len(st.tufMeta[id])-1].data, nil return space[len(space)-1].data, nil
} }
// Delete delets all the metadata for a given GUN // Delete delets all the metadata for a given GUN