mirror of https://github.com/docker/docs.git
				
				
				
			backup to a KeyFileStore and take out key remove
Signed-off-by: David Lawrence <david.lawrence@docker.com> (github: endophage)
This commit is contained in:
		
							parent
							
								
									542c4a6d32
								
							
						
					
					
						commit
						91e8b9bcdb
					
				|  | @ -24,14 +24,13 @@ func NewNotaryRepository(baseDir, gun, baseURL string, rt http.RoundTripper, | |||
| 	retriever passphrase.Retriever) (*NotaryRepository, error) { | ||||
| 
 | ||||
| 	keysPath := filepath.Join(baseDir, notary.PrivDir) | ||||
| 	backupPath := filepath.Join(baseDir, notary.BackupDir) | ||||
| 	fileKeyStore, err := trustmanager.NewKeyFileStore(keysPath, retriever) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("failed to create private key store in directory: %s", keysPath) | ||||
| 	} | ||||
| 
 | ||||
| 	keyStoreManager, err := keystoremanager.NewKeyStoreManager(baseDir, fileKeyStore) | ||||
| 	yubiKeyStore, _ := api.NewYubiKeyStore(backupPath, retriever) | ||||
| 	yubiKeyStore, _ := api.NewYubiKeyStore(fileKeyStore, retriever) | ||||
| 	var cryptoService signed.CryptoService | ||||
| 	if yubiKeyStore == nil { | ||||
| 		cryptoService = cryptoservice.NewCryptoService(gun, keyStoreManager.KeyStore) | ||||
|  |  | |||
|  | @ -22,10 +22,6 @@ import ( | |||
| 
 | ||||
| func init() { | ||||
| 	cmdKey.AddCommand(cmdKeyList) | ||||
| 	cmdKey.AddCommand(cmdKeyRemoveKey) | ||||
| 	cmdKeyRemoveKey.Flags().StringVarP(&keyRemoveGUN, "gun", "g", "", "Globally unique name to remove keys for") | ||||
| 	cmdKeyRemoveKey.Flags().BoolVarP(&keyRemoveRoot, "root", "r", false, "Remove root keys") | ||||
| 	cmdKeyRemoveKey.Flags().BoolVarP(&keyRemoveYes, "yes", "y", false, "Answer yes to the removal question (no confirmation)") | ||||
| 	cmdKey.AddCommand(cmdKeyGenerateRootKey) | ||||
| 
 | ||||
| 	cmdKeyExport.Flags().StringVarP(&keysExportGUN, "gun", "g", "", "Globally unique name to export keys for") | ||||
|  | @ -57,17 +53,6 @@ var cmdRotateKey = &cobra.Command{ | |||
| 	Run:   keysRotate, | ||||
| } | ||||
| 
 | ||||
| var keyRemoveGUN string | ||||
| var keyRemoveRoot bool | ||||
| var keyRemoveYes bool | ||||
| 
 | ||||
| var cmdKeyRemoveKey = &cobra.Command{ | ||||
| 	Use:   "remove [ keyID ]", | ||||
| 	Short: "Removes the key with the given keyID.", | ||||
| 	Long:  "remove the key with the given keyID from the local host.", | ||||
| 	Run:   keysRemoveKey, | ||||
| } | ||||
| 
 | ||||
| var cmdKeyGenerateRootKey = &cobra.Command{ | ||||
| 	Use:   "generate [ algorithm ]", | ||||
| 	Short: "Generates a new root key with a given algorithm.", | ||||
|  | @ -107,67 +92,6 @@ var cmdKeyImportRoot = &cobra.Command{ | |||
| 	Run:   keysImportRoot, | ||||
| } | ||||
| 
 | ||||
| // keysRemoveKey deletes a private key based on ID
 | ||||
| func keysRemoveKey(cmd *cobra.Command, args []string) { | ||||
| 	if len(args) < 1 { | ||||
| 		cmd.Usage() | ||||
| 		fatalf("must specify the key ID of the key to remove") | ||||
| 	} | ||||
| 
 | ||||
| 	parseConfig() | ||||
| 
 | ||||
| 	keysPath := filepath.Join(trustDir, notary.PrivDir) | ||||
| 	backupPath := filepath.Join(trustDir, notary.BackupDir) | ||||
| 	fileKeyStore, err := trustmanager.NewKeyFileStore(keysPath, retriever) | ||||
| 	if err != nil { | ||||
| 		fatalf("failed to create private key store in directory: %s", keysPath) | ||||
| 	} | ||||
| 	yubiStore, _ := api.NewYubiKeyStore(backupPath, retriever) | ||||
| 	var cs signed.CryptoService | ||||
| 	if yubiStore == nil { | ||||
| 		cs = cryptoservice.NewCryptoService("", fileKeyStore) | ||||
| 	} else { | ||||
| 		cs = cryptoservice.NewCryptoService("", yubiStore, fileKeyStore) | ||||
| 	} | ||||
| 
 | ||||
| 	keyID := args[0] | ||||
| 
 | ||||
| 	// This is an invalid ID
 | ||||
| 	if len(keyID) != idSize { | ||||
| 		fatalf("invalid key ID provided: %s", keyID) | ||||
| 	} | ||||
| 
 | ||||
| 	keyMap := cs.ListAllKeys() | ||||
| 	var key string | ||||
| 	for k := range keyMap { | ||||
| 		if filepath.Base(k) == keyID { | ||||
| 			key = k | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if key == "" { | ||||
| 		fatalf("key with key ID: %s not found\n", keyID) | ||||
| 	} | ||||
| 
 | ||||
| 	// List the key about to be removed
 | ||||
| 	fmt.Println("Are you sure you want to remove the following key?") | ||||
| 	fmt.Printf("%s\n(yes/no)\n", keyID) | ||||
| 
 | ||||
| 	// Ask for confirmation before removing the key, unless -y is passed
 | ||||
| 	if !keyRemoveYes { | ||||
| 		confirmed := askConfirm() | ||||
| 		if !confirmed { | ||||
| 			fatalf("aborting action.") | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Attempt to remove the key
 | ||||
| 	err = cs.RemoveKey(key) | ||||
| 	if err != nil { | ||||
| 		fatalf("failed to remove key with key ID: %s, %v", keyID, err) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func keysList(cmd *cobra.Command, args []string) { | ||||
| 	if len(args) > 0 { | ||||
| 		cmd.Usage() | ||||
|  | @ -177,12 +101,11 @@ func keysList(cmd *cobra.Command, args []string) { | |||
| 	parseConfig() | ||||
| 
 | ||||
| 	keysPath := filepath.Join(trustDir, notary.PrivDir) | ||||
| 	backupPath := filepath.Join(trustDir, notary.BackupDir) | ||||
| 	fileKeyStore, err := trustmanager.NewKeyFileStore(keysPath, retriever) | ||||
| 	if err != nil { | ||||
| 		fatalf("failed to create private key store in directory: %s", keysPath) | ||||
| 	} | ||||
| 	yubiStore, _ := api.NewYubiKeyStore(backupPath, retriever) | ||||
| 	yubiStore, _ := api.NewYubiKeyStore(fileKeyStore, retriever) | ||||
| 	var cs signed.CryptoService | ||||
| 	if yubiStore == nil { | ||||
| 		cs = cryptoservice.NewCryptoService("", fileKeyStore) | ||||
|  | @ -239,12 +162,11 @@ func keysGenerateRootKey(cmd *cobra.Command, args []string) { | |||
| 	parseConfig() | ||||
| 
 | ||||
| 	keysPath := filepath.Join(trustDir, notary.PrivDir) | ||||
| 	backupPath := filepath.Join(trustDir, notary.BackupDir) | ||||
| 	fileKeyStore, err := trustmanager.NewKeyFileStore(keysPath, retriever) | ||||
| 	if err != nil { | ||||
| 		fatalf("failed to create private key store in directory: %s", keysPath) | ||||
| 	} | ||||
| 	yubiStore, err := api.NewYubiKeyStore(backupPath, retriever) | ||||
| 	yubiStore, err := api.NewYubiKeyStore(fileKeyStore, retriever) | ||||
| 	var cs signed.CryptoService | ||||
| 	if err != nil { | ||||
| 		cmd.Printf("No Yubikey detected, importing to local filesystem.") | ||||
|  | @ -386,12 +308,11 @@ func keysImportRoot(cmd *cobra.Command, args []string) { | |||
| 	parseConfig() | ||||
| 
 | ||||
| 	keysPath := filepath.Join(trustDir, notary.PrivDir) | ||||
| 	backupPath := filepath.Join(trustDir, notary.BackupDir) | ||||
| 	fileKeyStore, err := trustmanager.NewKeyFileStore(keysPath, retriever) | ||||
| 	if err != nil { | ||||
| 		fatalf("failed to create private key store in directory: %s", keysPath) | ||||
| 	} | ||||
| 	yubiStore, err := api.NewYubiKeyStore(backupPath, retriever) | ||||
| 	yubiStore, err := api.NewYubiKeyStore(fileKeyStore, retriever) | ||||
| 	var cs signed.CryptoService | ||||
| 	if err != nil { | ||||
| 		cmd.Printf("No Yubikey detected, importing to local filesystem.") | ||||
|  |  | |||
|  | @ -12,13 +12,9 @@ import ( | |||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| 	"math/big" | ||||
| 	"os" | ||||
| 	"path" | ||||
| 
 | ||||
| 	"github.com/Sirupsen/logrus" | ||||
| 	"github.com/docker/notary" | ||||
| 	"github.com/docker/notary/passphrase" | ||||
| 	"github.com/docker/notary/trustmanager" | ||||
| 	"github.com/docker/notary/tuf/data" | ||||
|  | @ -35,11 +31,11 @@ const ( | |||
| var YUBIKEY_ROOT_KEY_ID = []byte{2} | ||||
| 
 | ||||
| type ErrBackupFailed struct { | ||||
| 	path string | ||||
| 	err string | ||||
| } | ||||
| 
 | ||||
| func (err ErrBackupFailed) Error() string { | ||||
| 	return fmt.Sprintf("Failed to backup private key to: %s", err.path) | ||||
| 	return fmt.Sprintf("Failed to backup private key to: %s", err.err) | ||||
| } | ||||
| 
 | ||||
| type yubiSlot struct { | ||||
|  | @ -108,7 +104,15 @@ func (y *YubiPrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts | |||
| } | ||||
| 
 | ||||
| // addECDSAKey adds a key to the yubikey
 | ||||
| func addECDSAKey(ctx *pkcs11.Ctx, session pkcs11.SessionHandle, privKey data.PrivateKey, pkcs11KeyID []byte, passRetriever passphrase.Retriever, role, backupPath string) error { | ||||
| func addECDSAKey( | ||||
| 	ctx *pkcs11.Ctx, | ||||
| 	session pkcs11.SessionHandle, | ||||
| 	privKey data.PrivateKey, | ||||
| 	pkcs11KeyID []byte, | ||||
| 	passRetriever passphrase.Retriever, | ||||
| 	role string, | ||||
| 	backupStore trustmanager.KeyStore, | ||||
| ) error { | ||||
| 	logrus.Debugf("Got into add key with key: %s\n", privKey.ID()) | ||||
| 
 | ||||
| 	// TODO(diogo): Figure out CKU_SO with yubikey
 | ||||
|  | @ -165,14 +169,9 @@ func addECDSAKey(ctx *pkcs11.Ctx, session pkcs11.SessionHandle, privKey data.Pri | |||
| 		return fmt.Errorf("error importing: %v", err) | ||||
| 	} | ||||
| 
 | ||||
| 	backupTo := path.Join(backupPath, privKey.ID()) | ||||
| 	err = ioutil.WriteFile( | ||||
| 		backupTo, | ||||
| 		privKey.Private(), | ||||
| 		notary.PrivKeyPerms, | ||||
| 	) | ||||
| 	err = backupStore.AddKey(privKey.ID(), role, privKey) | ||||
| 	if err != nil { | ||||
| 		return ErrBackupFailed{path: backupTo} | ||||
| 		return ErrBackupFailed{err: err.Error()} | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
|  | @ -484,21 +483,17 @@ func getNextEmptySlot(ctx *pkcs11.Ctx, session pkcs11.SessionHandle) ([]byte, er | |||
| type YubiKeyStore struct { | ||||
| 	passRetriever passphrase.Retriever | ||||
| 	keys          map[string]yubiSlot | ||||
| 	backupPath    string | ||||
| 	backupStore   trustmanager.KeyStore | ||||
| } | ||||
| 
 | ||||
| func NewYubiKeyStore(backupPath string, passphraseRetriever passphrase.Retriever) (*YubiKeyStore, error) { | ||||
| 	err := os.MkdirAll(backupPath, notary.PrivKeyPerms) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| func NewYubiKeyStore(backupStore trustmanager.KeyStore, passphraseRetriever passphrase.Retriever) (*YubiKeyStore, error) { | ||||
| 	s := &YubiKeyStore{ | ||||
| 		passRetriever: passphraseRetriever, | ||||
| 		keys:          make(map[string]yubiSlot), | ||||
| 		backupPath:    backupPath, | ||||
| 		backupStore:   backupStore, | ||||
| 	} | ||||
| 	s.ListKeys() // populate keys field
 | ||||
| 	return s, err | ||||
| 	return s, nil | ||||
| } | ||||
| 
 | ||||
| func (s *YubiKeyStore) ListKeys() map[string]string { | ||||
|  | @ -542,7 +537,7 @@ func (s *YubiKeyStore) AddKey(keyID, role string, privKey data.PrivateKey) error | |||
| 		return err | ||||
| 	} | ||||
| 	logrus.Debugf("Using yubikey slot %v", slot) | ||||
| 	err = addECDSAKey(ctx, session, privKey, slot, s.passRetriever, role, s.backupPath) | ||||
| 	err = addECDSAKey(ctx, session, privKey, slot, s.passRetriever, role, s.backupStore) | ||||
| 	if err == nil { | ||||
| 		s.keys[privKey.ID()] = yubiSlot{ | ||||
| 			role:   role, | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue