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