diff --git a/CHANGELOG.md b/CHANGELOG.md index f5e531782..fc5933edc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Changelog -## [v0.4.3](https://github.com/docker/notary/releases/tag/v0.4.3) 11/15/2016 +## [v0.4.3](https://github.com/docker/notary/releases/tag/v0.4.3) 1/3/2017 + Fix build tags for static notary client binaries in linux [#1039](https://github.com/docker/notary/pull/1039) ++ Fix key import for exported delegation keys [#1067](https://github.com/docker/notary/pull/1067) ## [v0.4.2](https://github.com/docker/notary/releases/tag/v0.4.2) 9/30/2016 + Bump the cross compiler to golang 1.7.1, since [1.6.3 builds binaries that could have non-deterministic bugs in OS X Sierra](https://groups.google.com/forum/#!msg/golang-dev/Jho5sBHZgAg/cq6d97S1AwAJ) [#984](https://github.com/docker/notary/pull/984) diff --git a/cmd/notary/integration_test.go b/cmd/notary/integration_test.go index 1cb199e44..ded718fab 100644 --- a/cmd/notary/integration_test.go +++ b/cmd/notary/integration_test.go @@ -2562,3 +2562,43 @@ func TestExportImportFlow(t *testing.T) { require.Contains(t, targString, "gun: gun") require.True(t, strings.Contains(snapString, "role: snapshot") || strings.Contains(snapString, "role: target")) } + +// Tests import/export keys with delegations, which don't require a gun +func TestDelegationKeyImportExport(t *testing.T) { + // -- setup -- + setUp(t) + + tempDir := tempDirWithConfig(t, "{}") + defer os.RemoveAll(tempDir) + + tempExportedDir := tempDirWithConfig(t, "{}") + defer os.RemoveAll(tempDir) + + tempImportingDir := tempDirWithConfig(t, "{}") + defer os.RemoveAll(tempDir) + + // Setup key in a file for import + keyFile, err := ioutil.TempFile("", "pemfile") + require.NoError(t, err) + defer os.Remove(keyFile.Name()) + privKey, err := utils.GenerateRSAKey(rand.Reader, 2048) + require.NoError(t, err) + pemBytes, err := utils.EncryptPrivateKey(privKey, "", "", "") + require.NoError(t, err) + nBytes, err := keyFile.Write(pemBytes) + require.NoError(t, err) + keyFile.Close() + require.Equal(t, len(pemBytes), nBytes) + + // import the key + _, err = runCommand(t, tempDir, "key", "import", keyFile.Name(), "-r", "user") + require.NoError(t, err) + + // export the key + _, err = runCommand(t, tempDir, "key", "export", "-o", filepath.Join(tempExportedDir, "exported")) + require.NoError(t, err) + + // re-import the key from the exported store to a new tempDir + _, err = runCommand(t, tempImportingDir, "key", "import", filepath.Join(tempExportedDir, "exported")) + require.NoError(t, err) +} diff --git a/utils/keys.go b/utils/keys.go index 1da3d95a7..48663cf7e 100644 --- a/utils/keys.go +++ b/utils/keys.go @@ -4,15 +4,16 @@ import ( "encoding/pem" "errors" "fmt" - "github.com/Sirupsen/logrus" - "github.com/docker/notary" - tufdata "github.com/docker/notary/tuf/data" - "github.com/docker/notary/tuf/utils" "io" "io/ioutil" "path/filepath" "sort" "strings" + + "github.com/Sirupsen/logrus" + "github.com/docker/notary" + tufdata "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/utils" ) // Exporter is a simple interface for the two functions we need from the Storage interface @@ -110,8 +111,8 @@ func ImportKeys(from io.Reader, to []Importer, fallbackRole string, fallbackGun if rawPath := block.Headers["path"]; rawPath != "" { pathWOFileName := strings.TrimSuffix(rawPath, filepath.Base(rawPath)) if strings.HasPrefix(pathWOFileName, notary.NonRootKeysSubdir) { - gunName := strings.TrimPrefix(pathWOFileName, notary.NonRootKeysSubdir) - gunName = gunName[1:(len(gunName) - 1)] // remove the slashes + // remove the notary keystore-specific segment of the path, and any potential leading or trailing slashes + gunName := strings.Trim(strings.TrimPrefix(pathWOFileName, notary.NonRootKeysSubdir), "/") if gunName != "" { block.Headers["gun"] = gunName } diff --git a/utils/keys_test.go b/utils/keys_test.go index bd122d032..da7b3bde5 100644 --- a/utils/keys_test.go +++ b/utils/keys_test.go @@ -5,14 +5,15 @@ import ( "crypto/rand" "encoding/pem" "errors" - "github.com/docker/notary" - "github.com/docker/notary/tuf/data" - "github.com/docker/notary/tuf/utils" - "github.com/stretchr/testify/require" "io/ioutil" "os" "path/filepath" "testing" + + "github.com/docker/notary" + "github.com/docker/notary/tuf/data" + "github.com/docker/notary/tuf/utils" + "github.com/stretchr/testify/require" ) const cannedPassphrase = "passphrase" @@ -363,8 +364,8 @@ func TestBlockHeaderPrecedenceGunFromPath(t *testing.T) { require.Equal(t, key, filepath.Join(notary.NonRootKeysSubdir, "anothergun", "12ba0e0a8e05e177bc2c3489bdb6d28836879469f078e68a4812fc8a2d521497")) final, rest := pem.Decode(s.data[key]) require.Len(t, rest, 0) - require.Equal(t, final.Headers["role"], "snapshot") - require.Equal(t, final.Headers["gun"], "anothergun") + require.Equal(t, "snapshot", final.Headers["role"]) + require.Equal(t, "anothergun", final.Headers["gun"]) } }