mirror of https://github.com/docker/docs.git
cleaning up cache vs filestore
Signed-off-by: David Lawrence <david.lawrence@docker.com> (github: endophage)
This commit is contained in:
parent
9b604d0a6c
commit
20b60d9cc2
190
Godeps/_workspace/src/github.com/endophage/gotuf/client/client_test.go
generated
vendored
Normal file
190
Godeps/_workspace/src/github.com/endophage/gotuf/client/client_test.go
generated
vendored
Normal 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.")
|
||||||
|
|
||||||
|
}
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue