Add key import and export commands

This adds four commands:

- notary keys export: export all keys, or keys for a particular GUN
  (with -g)
- notary keys export-root: export root key by ID
- notary keys import: import a zip file of keys
- notary keys import-root: import a single root key

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
This commit is contained in:
Aaron Lehmann 2015-07-28 11:12:32 -07:00
parent 17a0373eb3
commit 558f52530b
1 changed files with 174 additions and 2 deletions

View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"archive/zip"
"crypto/x509" "crypto/x509"
"fmt" "fmt"
"math" "math"
@ -10,6 +11,7 @@ import (
"time" "time"
"github.com/docker/notary/keystoremanager" "github.com/docker/notary/keystoremanager"
"github.com/docker/notary/pkg/passphrase"
"github.com/docker/notary/trustmanager" "github.com/docker/notary/trustmanager"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -18,12 +20,18 @@ import (
func init() { func init() {
cmdKeys.AddCommand(cmdKeysRemoveRootKey) cmdKeys.AddCommand(cmdKeysRemoveRootKey)
cmdKeys.AddCommand(cmdKeysGenerateRootKey) cmdKeys.AddCommand(cmdKeysGenerateRootKey)
cmdKeysExport.Flags().StringVarP(&keysExportGUN, "gun", "g", "", "Globally unique name to export keys for. A new password will be set for all the keys. Output format is a zip archive.")
cmdKeys.AddCommand(cmdKeysExport)
cmdKeys.AddCommand(cmdKeysExportRoot)
cmdKeys.AddCommand(cmdKeysImport)
cmdKeys.AddCommand(cmdKeysImportRoot)
} }
var cmdKeys = &cobra.Command{ var cmdKeys = &cobra.Command{
Use: "keys", Use: "keys",
Short: "Operates on root keys.", Short: "Operates on keys.",
Long: "operations on private root keys.", Long: "operations on private keys.",
Run: keysList, Run: keysList,
} }
@ -41,6 +49,36 @@ var cmdKeysGenerateRootKey = &cobra.Command{
Run: keysGenerateRootKey, Run: keysGenerateRootKey,
} }
var keysExportGUN string
var cmdKeysExport = &cobra.Command{
Use: "export [ filename ]",
Short: "Exports keys to a ZIP file.",
Long: "exports a collection of keys. The keys are reencrypted with a new passphrase. The output is a ZIP file.",
Run: keysExport,
}
var cmdKeysExportRoot = &cobra.Command{
Use: "export-root [ keyID ] [ filename ]",
Short: "Exports given root key to a file.",
Long: "exports a root key, without reencrypting. The output is a PEM file.",
Run: keysExportRoot,
}
var cmdKeysImport = &cobra.Command{
Use: "import [ filename ]",
Short: "Imports keys from a ZIP file.",
Long: "imports one or more keys from a ZIP file.",
Run: keysImport,
}
var cmdKeysImportRoot = &cobra.Command{
Use: "import-root [ keyID ] [ filename ]",
Short: "Imports root key.",
Long: "imports a root key from a PEM file.",
Run: keysImportRoot,
}
// keysRemoveRootKey deletes a root private key based on ID // keysRemoveRootKey deletes a root private key based on ID
func keysRemoveRootKey(cmd *cobra.Command, args []string) { func keysRemoveRootKey(cmd *cobra.Command, args []string) {
if len(args) < 1 { if len(args) < 1 {
@ -141,6 +179,140 @@ func keysGenerateRootKey(cmd *cobra.Command, args []string) {
fmt.Printf("Generated new %s key with keyID: %s\n", algorithm, keyID) fmt.Printf("Generated new %s key with keyID: %s\n", algorithm, keyID)
} }
// keysExport exports a collection of keys to a ZIP file
func keysExport(cmd *cobra.Command, args []string) {
if len(args) < 1 {
cmd.Usage()
fatalf("must specify output filename for export")
}
exportFilename := args[0]
parseConfig()
keyStoreManager, err := keystoremanager.NewKeyStoreManager(trustDir, retriever)
if err != nil {
fatalf("failed to create a new truststore manager with directory: %s", trustDir)
}
exportFile, err := os.Create(exportFilename)
if err != nil {
fatalf("error creating output file: %v", err)
}
// Must use a different passphrase retriever to avoid caching the
// unlocking passphrase and reusing that.
exportRetriever := passphrase.PromptRetriever()
if keysExportGUN != "" {
err = keyStoreManager.ExportKeysByGUN(exportFile, keysExportGUN, exportRetriever)
} else {
err = keyStoreManager.ExportAllKeys(exportFile, exportRetriever)
}
exportFile.Close()
if err != nil {
fatalf("error exporting keys: %v", err)
os.Remove(exportFilename)
}
}
// keysExportRoot exports a root key by ID to a PEM file
func keysExportRoot(cmd *cobra.Command, args []string) {
if len(args) < 2 {
cmd.Usage()
fatalf("must specify key ID and output filename for export")
}
keyID := args[0]
exportFilename := args[1]
if len(keyID) != 64 {
fatalf("please specify a valid root key ID")
}
parseConfig()
keyStoreManager, err := keystoremanager.NewKeyStoreManager(trustDir, retriever)
if err != nil {
fatalf("failed to create a new truststore manager with directory: %s", trustDir)
}
exportFile, err := os.Create(exportFilename)
if err != nil {
fatalf("error creating output file: %v", err)
}
err = keyStoreManager.ExportRootKey(exportFile, keyID)
exportFile.Close()
if err != nil {
fatalf("error exporting root key: %v", err)
os.Remove(exportFilename)
}
}
// keysImport imports keys from a ZIP file
func keysImport(cmd *cobra.Command, args []string) {
if len(args) < 1 {
cmd.Usage()
fatalf("must specify input filename for import")
}
importFilename := args[0]
parseConfig()
keyStoreManager, err := keystoremanager.NewKeyStoreManager(trustDir, retriever)
if err != nil {
fatalf("failed to create a new truststore manager with directory: %s", trustDir)
}
zipReader, err := zip.OpenReader(importFilename)
if err != nil {
fatalf("opening file for import: %v", err)
}
defer zipReader.Close()
err = keyStoreManager.ImportKeysZip(zipReader.Reader)
if err != nil {
fatalf("error importing keys: %v", err)
}
}
// keysImportRoot imports a root key from a PEM file
func keysImportRoot(cmd *cobra.Command, args []string) {
if len(args) < 2 {
cmd.Usage()
fatalf("must specify key ID and input filename for import")
}
keyID := args[0]
importFilename := args[1]
if len(keyID) != 64 {
fatalf("please specify a valid root key ID")
}
parseConfig()
keyStoreManager, err := keystoremanager.NewKeyStoreManager(trustDir, retriever)
if err != nil {
fatalf("failed to create a new truststore manager with directory: %s", trustDir)
}
importFile, err := os.Open(importFilename)
if err != nil {
fatalf("opening file for import: %v", err)
}
defer importFile.Close()
err = keyStoreManager.ImportRootKey(importFile, keyID)
if err != nil {
fatalf("error importing root key: %v", err)
}
}
func printCert(cert *x509.Certificate) { func printCert(cert *x509.Certificate) {
timeDifference := cert.NotAfter.Sub(time.Now()) timeDifference := cert.NotAfter.Sub(time.Now())
certID, err := trustmanager.FingerprintCert(cert) certID, err := trustmanager.FingerprintCert(cert)