mirror of https://github.com/docker/docs.git
Add ExportRootKey and ImportRootKey functions
Also add a unit test Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
This commit is contained in:
parent
20633e3e12
commit
479333ca7b
|
@ -16,6 +16,36 @@ import (
|
||||||
"github.com/endophage/gotuf/data"
|
"github.com/endophage/gotuf/data"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ExportRootKey exports the specified root key to an io.Writer in PEM format.
|
||||||
|
// The key's existing encryption is preserved.
|
||||||
|
func (km *KeyStoreManager) ExportRootKey(dest io.Writer, keyID string) error {
|
||||||
|
pemBytes, err := km.rootKeyStore.Get(keyID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = dest.Write(pemBytes)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImportRootKey imports a root in PEM format key from an io.Reader
|
||||||
|
// The key's existing encryption is preserved. The keyID parameter is
|
||||||
|
// necessary because otherwise we'd need the passphrase to decrypt the key
|
||||||
|
// in order to compute the ID.
|
||||||
|
func (km *KeyStoreManager) ImportRootKey(source io.Reader, keyID string) error {
|
||||||
|
pemBytes, err := ioutil.ReadAll(source)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = km.rootKeyStore.Add(keyID, pemBytes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func moveKeysWithNewPassphrase(oldKeyStore, newKeyStore *trustmanager.KeyFileStore, outputPassphrase string) error {
|
func moveKeysWithNewPassphrase(oldKeyStore, newKeyStore *trustmanager.KeyFileStore, outputPassphrase string) error {
|
||||||
// List all files but no symlinks
|
// List all files but no symlinks
|
||||||
for _, f := range oldKeyStore.ListFiles(false) {
|
for _, f := range oldKeyStore.ListFiles(false) {
|
||||||
|
|
|
@ -69,7 +69,7 @@ func TestImportExportZip(t *testing.T) {
|
||||||
tempZipFile.Close()
|
tempZipFile.Close()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
// Check the contents of the zip file
|
// Reopen the zip file for importing
|
||||||
zipReader, err := zip.OpenReader(tempZipFilePath)
|
zipReader, err := zip.OpenReader(tempZipFilePath)
|
||||||
assert.NoError(t, err, "could not open zip file")
|
assert.NoError(t, err, "could not open zip file")
|
||||||
|
|
||||||
|
@ -173,3 +173,70 @@ func TestImportExportZip(t *testing.T) {
|
||||||
_, err = os.Stat(filepath.Join(tempBaseDir2, "private", "root_keys", rootKeyFilename))
|
_, err = os.Stat(filepath.Join(tempBaseDir2, "private", "root_keys", rootKeyFilename))
|
||||||
assert.NoError(t, err, "missing root key")
|
assert.NoError(t, err, "missing root key")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestImportExportRootKey(t *testing.T) {
|
||||||
|
gun := "docker.com/notary"
|
||||||
|
oldPassphrase := "oldPassphrase"
|
||||||
|
|
||||||
|
// Temporary directory where test files will be created
|
||||||
|
tempBaseDir, err := ioutil.TempDir("", "notary-test-")
|
||||||
|
defer os.RemoveAll(tempBaseDir)
|
||||||
|
|
||||||
|
assert.NoError(t, err, "failed to create a temporary directory: %s", err)
|
||||||
|
|
||||||
|
ts, _ := createTestServer(t)
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
repo, err := client.NewNotaryRepository(tempBaseDir, gun, ts.URL, http.DefaultTransport)
|
||||||
|
assert.NoError(t, err, "error creating repo: %s", err)
|
||||||
|
|
||||||
|
rootKeyID, err := repo.KeyStoreManager.GenRootKey(data.ECDSAKey.String(), oldPassphrase)
|
||||||
|
assert.NoError(t, err, "error generating root key: %s", err)
|
||||||
|
|
||||||
|
rootCryptoService, err := repo.KeyStoreManager.GetRootCryptoService(rootKeyID, oldPassphrase)
|
||||||
|
assert.NoError(t, err, "error retrieving root key: %s", err)
|
||||||
|
|
||||||
|
err = repo.Initialize(rootCryptoService)
|
||||||
|
assert.NoError(t, err, "error creating repository: %s", err)
|
||||||
|
|
||||||
|
tempKeyFile, err := ioutil.TempFile("", "notary-test-export-")
|
||||||
|
tempKeyFilePath := tempKeyFile.Name()
|
||||||
|
defer os.Remove(tempKeyFilePath)
|
||||||
|
|
||||||
|
err = repo.KeyStoreManager.ExportRootKey(tempKeyFile, rootKeyID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
tempKeyFile.Close()
|
||||||
|
|
||||||
|
// Create new repo to test import
|
||||||
|
tempBaseDir2, err := ioutil.TempDir("", "notary-test-")
|
||||||
|
defer os.RemoveAll(tempBaseDir2)
|
||||||
|
|
||||||
|
assert.NoError(t, err, "failed to create a temporary directory: %s", err)
|
||||||
|
|
||||||
|
repo2, err := client.NewNotaryRepository(tempBaseDir2, gun, ts.URL, http.DefaultTransport)
|
||||||
|
assert.NoError(t, err, "error creating repo: %s", err)
|
||||||
|
|
||||||
|
rootKeyID2, err := repo2.KeyStoreManager.GenRootKey(data.ECDSAKey.String(), "oldPassphrase")
|
||||||
|
assert.NoError(t, err, "error generating root key: %s", err)
|
||||||
|
|
||||||
|
rootCryptoService2, err := repo2.KeyStoreManager.GetRootCryptoService(rootKeyID2, "oldPassphrase")
|
||||||
|
assert.NoError(t, err, "error retrieving root key: %s", err)
|
||||||
|
|
||||||
|
err = repo2.Initialize(rootCryptoService2)
|
||||||
|
assert.NoError(t, err, "error creating repository: %s", err)
|
||||||
|
|
||||||
|
// Check the contents of the zip file
|
||||||
|
keyReader, err := os.Open(tempKeyFilePath)
|
||||||
|
assert.NoError(t, err, "could not open key file")
|
||||||
|
|
||||||
|
err = repo2.KeyStoreManager.ImportRootKey(keyReader, rootKeyID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
keyReader.Close()
|
||||||
|
|
||||||
|
// Look for repo's root key in repo2
|
||||||
|
// There should be a file named after the key ID of the root key we
|
||||||
|
// imported.
|
||||||
|
rootKeyFilename := rootKeyID + ".key"
|
||||||
|
_, err = os.Stat(filepath.Join(tempBaseDir2, "private", "root_keys", rootKeyFilename))
|
||||||
|
assert.NoError(t, err, "missing root key")
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue