mirror of https://github.com/docker/docs.git
Introduce a KeyStoreManager to abstract management of root and non-root key storage
This structure encapsulates what used to be "rootKeyStore" and "privKeyStore". These are being moved out of NotaryRepository, so that operations like listing keys, importing keys, and exporting keys aren't tied to a NotaryRepository structure. Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
This commit is contained in:
parent
3cc3a0d489
commit
d5c7c40955
|
|
@ -20,6 +20,7 @@ import (
|
|||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/notary/client/changelist"
|
||||
"github.com/docker/notary/keystoremanager"
|
||||
"github.com/docker/notary/trustmanager"
|
||||
"github.com/endophage/gotuf"
|
||||
tufclient "github.com/endophage/gotuf/client"
|
||||
|
|
@ -44,9 +45,7 @@ func (err *ErrRepoNotInitialized) Error() string {
|
|||
// Default paths should end with a '/' so directory creation works correctly
|
||||
const (
|
||||
trustDir string = "/trusted_certificates/"
|
||||
privDir string = "/private/"
|
||||
tufDir string = "/tuf/"
|
||||
rootKeysDir string = privDir + "/root_keys/"
|
||||
rsaKeySize int = 2048 // Used for snapshots and targets keys
|
||||
rsaRootKeySize int = 4096 // Used for new root keys
|
||||
)
|
||||
|
|
@ -75,9 +74,8 @@ type NotaryRepository struct {
|
|||
fileStore store.MetadataStore
|
||||
cryptoService signed.CryptoService
|
||||
tufRepo *tuf.TufRepo
|
||||
privKeyStore *trustmanager.KeyFileStore
|
||||
rootKeyStore *trustmanager.KeyFileStore
|
||||
roundTrip http.RoundTripper
|
||||
KeyStoreManager *keystoremanager.KeyStoreManager
|
||||
}
|
||||
|
||||
// Target represents a simplified version of the data TUF operates on, so external
|
||||
|
|
@ -108,26 +106,25 @@ func NewTarget(targetName string, targetPath string) (*Target, error) {
|
|||
// (usually ~/.docker/trust/).
|
||||
func NewNotaryRepository(baseDir, gun, baseURL string, rt http.RoundTripper) (*NotaryRepository, error) {
|
||||
trustDir := filepath.Join(baseDir, trustDir)
|
||||
rootKeysDir := filepath.Join(baseDir, rootKeysDir)
|
||||
|
||||
privKeyStore, err := trustmanager.NewKeyFileStore(filepath.Join(baseDir, privDir))
|
||||
keyStoreManager, err := keystoremanager.NewKeyStoreManager(baseDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cryptoService := NewCryptoService(gun, privKeyStore, "")
|
||||
cryptoService := NewCryptoService(gun, keyStoreManager.NonRootKeyStore(), "")
|
||||
|
||||
nRepo := &NotaryRepository{
|
||||
gun: gun,
|
||||
baseDir: baseDir,
|
||||
baseURL: baseURL,
|
||||
tufRepoPath: filepath.Join(baseDir, tufDir, gun),
|
||||
cryptoService: cryptoService,
|
||||
privKeyStore: privKeyStore,
|
||||
roundTrip: rt,
|
||||
gun: gun,
|
||||
baseDir: baseDir,
|
||||
baseURL: baseURL,
|
||||
tufRepoPath: filepath.Join(baseDir, tufDir, gun),
|
||||
cryptoService: cryptoService,
|
||||
roundTrip: rt,
|
||||
KeyStoreManager: keyStoreManager,
|
||||
}
|
||||
|
||||
if err := nRepo.loadKeys(trustDir, rootKeysDir); err != nil {
|
||||
if err := nRepo.loadKeys(trustDir); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
@ -166,7 +163,7 @@ func (r *NotaryRepository) Initialize(uCryptoService *UnlockedCryptoService) err
|
|||
// is associated with. This is used to be able to retrieve the root private key
|
||||
// associated with a particular certificate
|
||||
logrus.Debugf("Linking %s to %s.", rootKey.ID(), uCryptoService.ID())
|
||||
err = r.rootKeyStore.Link(uCryptoService.ID(), rootKey.ID())
|
||||
err = r.KeyStoreManager.RootKeyStore().Link(uCryptoService.ID(), rootKey.ID())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -643,12 +640,6 @@ func (r *NotaryRepository) bootstrapClient() (*tufclient.Client, error) {
|
|||
), nil
|
||||
}
|
||||
|
||||
// ListRootKeys returns the IDs for all of the root keys. It ignores symlinks
|
||||
// if any exist.
|
||||
func (r *NotaryRepository) ListRootKeys() []string {
|
||||
return r.rootKeyStore.ListKeys()
|
||||
}
|
||||
|
||||
// GenRootKey generates a new root key protected by a given passphrase
|
||||
// TODO(diogo): show not create keys manually, should use a cryptoservice instead
|
||||
func (r *NotaryRepository) GenRootKey(algorithm, passphrase string) (string, error) {
|
||||
|
|
@ -672,26 +663,26 @@ func (r *NotaryRepository) GenRootKey(algorithm, passphrase string) (string, err
|
|||
}
|
||||
|
||||
// Changing the root
|
||||
r.rootKeyStore.AddEncryptedKey(privKey.ID(), privKey, passphrase)
|
||||
r.KeyStoreManager.RootKeyStore().AddEncryptedKey(privKey.ID(), privKey, passphrase)
|
||||
|
||||
return privKey.ID(), nil
|
||||
}
|
||||
|
||||
// GetRootCryptoService retreives a root key and a cryptoservice to use with it
|
||||
func (r *NotaryRepository) GetRootCryptoService(rootKeyID, passphrase string) (*UnlockedCryptoService, error) {
|
||||
privKey, err := r.rootKeyStore.GetDecryptedKey(rootKeyID, passphrase)
|
||||
privKey, err := r.KeyStoreManager.RootKeyStore().GetDecryptedKey(rootKeyID, passphrase)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get decrypted root key with keyID: %s, %v", rootKeyID, err)
|
||||
}
|
||||
|
||||
cryptoService := NewCryptoService("", r.rootKeyStore, passphrase)
|
||||
cryptoService := NewCryptoService("", r.KeyStoreManager.RootKeyStore(), passphrase)
|
||||
|
||||
return &UnlockedCryptoService{
|
||||
privKey: privKey,
|
||||
cryptoService: cryptoService}, nil
|
||||
}
|
||||
|
||||
func (r *NotaryRepository) loadKeys(trustDir, rootKeysDir string) error {
|
||||
func (r *NotaryRepository) loadKeys(trustDir string) error {
|
||||
// Load all CAs that aren't expired and don't use SHA1
|
||||
caStore, err := trustmanager.NewX509FilteredFileStore(trustDir, func(cert *x509.Certificate) bool {
|
||||
return cert.IsCA && cert.BasicConstraintsValid && cert.SubjectKeyId != nil &&
|
||||
|
|
@ -716,15 +707,8 @@ func (r *NotaryRepository) loadKeys(trustDir, rootKeysDir string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// Load the keystore that will hold all of our encrypted Root Private Keys
|
||||
rootKeyStore, err := trustmanager.NewKeyFileStore(rootKeysDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.caStore = caStore
|
||||
r.certificateStore = certificateStore
|
||||
r.rootKeyStore = rootKeyStore
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ func testInitRepo(t *testing.T, rootType data.KeyAlgorithm) {
|
|||
|
||||
// Look for keys in private. The filenames should match the key IDs
|
||||
// in the private key store.
|
||||
privKeyList := repo.privKeyStore.ListFiles(true)
|
||||
privKeyList := repo.KeyStoreManager.NonRootKeyStore().ListFiles(true)
|
||||
for _, privKeyName := range privKeyList {
|
||||
_, err := os.Stat(privKeyName)
|
||||
assert.NoError(t, err, "missing private key: %s", privKeyName)
|
||||
|
|
@ -309,7 +309,7 @@ func testAddListTarget(t *testing.T, rootType data.KeyAlgorithm) {
|
|||
var tempKey data.PrivateKey
|
||||
json.Unmarshal([]byte(timestampECDSAKeyJSON), &tempKey)
|
||||
|
||||
repo.privKeyStore.AddKey(filepath.Join(gun, tempKey.ID()), &tempKey)
|
||||
repo.KeyStoreManager.NonRootKeyStore().AddKey(filepath.Join(gun, tempKey.ID()), &tempKey)
|
||||
|
||||
mux.HandleFunc("/v2/docker.com/notary/_trust/tuf/root.json", func(w http.ResponseWriter, r *http.Request) {
|
||||
rootJSONFile := filepath.Join(tempBaseDir, "tuf", gun, "metadata", "root.json")
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ func tufInit(cmd *cobra.Command, args []string) {
|
|||
fatalf(err.Error())
|
||||
}
|
||||
|
||||
keysList := nRepo.ListRootKeys()
|
||||
keysList := nRepo.KeyStoreManager.RootKeyStore().ListKeys()
|
||||
var passphrase string
|
||||
var rootKeyID string
|
||||
if len(keysList) < 1 {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
package keystoremanager
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/docker/notary/trustmanager"
|
||||
)
|
||||
|
||||
// KeyStoreManager is an abstraction around the root and non-root key stores
|
||||
type KeyStoreManager struct {
|
||||
rootKeyStore *trustmanager.KeyFileStore
|
||||
nonRootKeyStore *trustmanager.KeyFileStore
|
||||
}
|
||||
|
||||
const (
|
||||
privDir = "private"
|
||||
rootKeysSubdir = "root_keys"
|
||||
)
|
||||
|
||||
// NewKeyStoreManager returns an initialized KeyStoreManager, or an error
|
||||
// if it fails to create the KeyFileStores
|
||||
func NewKeyStoreManager(baseDir string) (*KeyStoreManager, error) {
|
||||
nonRootKeyStore, err := trustmanager.NewKeyFileStore(filepath.Join(baseDir, privDir))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Load the keystore that will hold all of our encrypted Root Private Keys
|
||||
rootKeysPath := filepath.Join(baseDir, privDir, rootKeysSubdir)
|
||||
rootKeyStore, err := trustmanager.NewKeyFileStore(rootKeysPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &KeyStoreManager{
|
||||
rootKeyStore: rootKeyStore,
|
||||
nonRootKeyStore: nonRootKeyStore,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// RootKeyStore returns the root key store being managed by this
|
||||
// KeyStoreManager
|
||||
func (km *KeyStoreManager) RootKeyStore() *trustmanager.KeyFileStore {
|
||||
return km.rootKeyStore
|
||||
}
|
||||
|
||||
// NonRootKeyStore returns the non-root key store being managed by this
|
||||
// KeyStoreManager
|
||||
func (km *KeyStoreManager) NonRootKeyStore() *trustmanager.KeyFileStore {
|
||||
return km.nonRootKeyStore
|
||||
}
|
||||
Loading…
Reference in New Issue