mirror of https://github.com/docker/docs.git
				
				
				
			Merge pull request #31 from docker/non-pkcs11
Ensure that tests pass and binaries build without the pkcs11 build tag. Signed-off-by: David Lawrence <david.lawrence@docker.com> Signed-off-by: Diogo Mónica <diogo.monica@gmail.com> (github: endophage)
This commit is contained in:
		
						commit
						580303c219
					
				|  | @ -7,14 +7,9 @@ import ( | |||
| 	"sort" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/docker/notary" | ||||
| 	notaryclient "github.com/docker/notary/client" | ||||
| 	"github.com/docker/notary/cryptoservice" | ||||
| 	"github.com/docker/notary/signer/api" | ||||
| 	"github.com/docker/notary/trustmanager" | ||||
| 
 | ||||
| 	"github.com/docker/notary/tuf/data" | ||||
| 	"github.com/docker/notary/tuf/signed" | ||||
| 	"github.com/spf13/cobra" | ||||
| ) | ||||
| 
 | ||||
|  | @ -98,18 +93,7 @@ func keysList(cmd *cobra.Command, args []string) { | |||
| 
 | ||||
| 	parseConfig() | ||||
| 
 | ||||
| 	keysPath := filepath.Join(trustDir, notary.PrivDir) | ||||
| 	fileKeyStore, err := trustmanager.NewKeyFileStore(keysPath, retriever) | ||||
| 	if err != nil { | ||||
| 		fatalf("Failed to create private key store in directory: %s", keysPath) | ||||
| 	} | ||||
| 	yubiStore, _ := api.NewYubiKeyStore(fileKeyStore, retriever) | ||||
| 	var cs signed.CryptoService | ||||
| 	if yubiStore == nil { | ||||
| 		cs = cryptoservice.NewCryptoService("", fileKeyStore) | ||||
| 	} else { | ||||
| 		cs = cryptoservice.NewCryptoService("", yubiStore, fileKeyStore) | ||||
| 	} | ||||
| 	cs := getCryptoService(cmd, trustDir, retriever, true) | ||||
| 
 | ||||
| 	// Get a map of all the keys/roles
 | ||||
| 	keysMap := cs.ListAllKeys() | ||||
|  | @ -159,19 +143,7 @@ func keysGenerateRootKey(cmd *cobra.Command, args []string) { | |||
| 
 | ||||
| 	parseConfig() | ||||
| 
 | ||||
| 	keysPath := filepath.Join(trustDir, notary.PrivDir) | ||||
| 	fileKeyStore, err := trustmanager.NewKeyFileStore(keysPath, retriever) | ||||
| 	if err != nil { | ||||
| 		fatalf("Failed to create private key store in directory: %s", keysPath) | ||||
| 	} | ||||
| 	yubiStore, err := api.NewYubiKeyStore(fileKeyStore, retriever) | ||||
| 	var cs signed.CryptoService | ||||
| 	if err != nil { | ||||
| 		cmd.Printf("No Yubikey detected, importing to local filesystem.") | ||||
| 		cs = cryptoservice.NewCryptoService("", fileKeyStore) | ||||
| 	} else { | ||||
| 		cs = cryptoservice.NewCryptoService("", yubiStore, fileKeyStore) | ||||
| 	} | ||||
| 	cs := getCryptoService(cmd, trustDir, retriever, true) | ||||
| 
 | ||||
| 	pubKey, err := cs.Create(data.CanonicalRootRole, algorithm) | ||||
| 	if err != nil { | ||||
|  | @ -192,12 +164,7 @@ func keysExport(cmd *cobra.Command, args []string) { | |||
| 
 | ||||
| 	parseConfig() | ||||
| 
 | ||||
| 	keysPath := filepath.Join(trustDir, notary.PrivDir) | ||||
| 	fileKeyStore, err := trustmanager.NewKeyFileStore(keysPath, retriever) | ||||
| 	if err != nil { | ||||
| 		fatalf("Failed to create private key store in directory: %s", keysPath) | ||||
| 	} | ||||
| 	cs := cryptoservice.NewCryptoService("", fileKeyStore) | ||||
| 	cs := getCryptoService(cmd, trustDir, retriever, false) | ||||
| 
 | ||||
| 	exportFile, err := os.Create(exportFilename) | ||||
| 	if err != nil { | ||||
|  | @ -237,12 +204,7 @@ func keysExportRoot(cmd *cobra.Command, args []string) { | |||
| 
 | ||||
| 	parseConfig() | ||||
| 
 | ||||
| 	keysPath := filepath.Join(trustDir, notary.PrivDir) | ||||
| 	fileKeyStore, err := trustmanager.NewKeyFileStore(keysPath, retriever) | ||||
| 	if err != nil { | ||||
| 		fatalf("Failed to create private key store in directory: %s", keysPath) | ||||
| 	} | ||||
| 	cs := cryptoservice.NewCryptoService("", fileKeyStore) | ||||
| 	cs := getCryptoService(cmd, trustDir, retriever, false) | ||||
| 
 | ||||
| 	exportFile, err := os.Create(exportFilename) | ||||
| 	if err != nil { | ||||
|  | @ -274,12 +236,7 @@ func keysImport(cmd *cobra.Command, args []string) { | |||
| 
 | ||||
| 	parseConfig() | ||||
| 
 | ||||
| 	keysPath := filepath.Join(trustDir, notary.PrivDir) | ||||
| 	fileKeyStore, err := trustmanager.NewKeyFileStore(keysPath, retriever) | ||||
| 	if err != nil { | ||||
| 		fatalf("Failed to create private key store in directory: %s", keysPath) | ||||
| 	} | ||||
| 	cs := cryptoservice.NewCryptoService("", fileKeyStore) | ||||
| 	cs := getCryptoService(cmd, trustDir, retriever, false) | ||||
| 
 | ||||
| 	zipReader, err := zip.OpenReader(importFilename) | ||||
| 	if err != nil { | ||||
|  | @ -305,19 +262,7 @@ func keysImportRoot(cmd *cobra.Command, args []string) { | |||
| 
 | ||||
| 	parseConfig() | ||||
| 
 | ||||
| 	keysPath := filepath.Join(trustDir, notary.PrivDir) | ||||
| 	fileKeyStore, err := trustmanager.NewKeyFileStore(keysPath, retriever) | ||||
| 	if err != nil { | ||||
| 		fatalf("Failed to create private key store in directory: %s", keysPath) | ||||
| 	} | ||||
| 	yubiStore, err := api.NewYubiKeyStore(fileKeyStore, retriever) | ||||
| 	var cs signed.CryptoService | ||||
| 	if err != nil { | ||||
| 		cmd.Printf("No Yubikey detected, importing to local filesystem.") | ||||
| 		cs = cryptoservice.NewCryptoService("", fileKeyStore) | ||||
| 	} else { | ||||
| 		cs = cryptoservice.NewCryptoService("", yubiStore, fileKeyStore) | ||||
| 	} | ||||
| 	cs := getCryptoService(cmd, trustDir, retriever, true) | ||||
| 
 | ||||
| 	importFile, err := os.Open(importFilename) | ||||
| 	if err != nil { | ||||
|  |  | |||
|  | @ -0,0 +1,24 @@ | |||
| // +build !pkcs11
 | ||||
| 
 | ||||
| package main | ||||
| 
 | ||||
| import ( | ||||
| 	"path/filepath" | ||||
| 
 | ||||
| 	"github.com/docker/notary" | ||||
| 	"github.com/docker/notary/cryptoservice" | ||||
| 	"github.com/docker/notary/passphrase" | ||||
| 	"github.com/docker/notary/trustmanager" | ||||
| 	"github.com/spf13/cobra" | ||||
| ) | ||||
| 
 | ||||
| func getCryptoService(cmd *cobra.Command, directory string, | ||||
| 	ret passphrase.Retriever, _ bool) *cryptoservice.CryptoService { | ||||
| 
 | ||||
| 	keysPath := filepath.Join(directory, notary.PrivDir) | ||||
| 	fileKeyStore, err := trustmanager.NewKeyFileStore(keysPath, ret) | ||||
| 	if err != nil { | ||||
| 		fatalf("Failed to create private key store in directory: %s", keysPath) | ||||
| 	} | ||||
| 	return cryptoservice.NewCryptoService("", fileKeyStore) | ||||
| } | ||||
|  | @ -0,0 +1,41 @@ | |||
| // +build pkcs11
 | ||||
| 
 | ||||
| package main | ||||
| 
 | ||||
| import ( | ||||
| 	"path/filepath" | ||||
| 
 | ||||
| 	"github.com/docker/notary" | ||||
| 	"github.com/docker/notary/cryptoservice" | ||||
| 	"github.com/docker/notary/passphrase" | ||||
| 	"github.com/docker/notary/signer/api" | ||||
| 	"github.com/docker/notary/trustmanager" | ||||
| 	"github.com/spf13/cobra" | ||||
| ) | ||||
| 
 | ||||
| // Build a CryptoService, optionally including a hardware keystore.  Returns
 | ||||
| // the CryptoService and whether or not a hardware keystore was included.
 | ||||
| func getCryptoService(cmd *cobra.Command, directory string, | ||||
| 	ret passphrase.Retriever, withHardware bool) *cryptoservice.CryptoService { | ||||
| 
 | ||||
| 	keysPath := filepath.Join(directory, notary.PrivDir) | ||||
| 	fileKeyStore, err := trustmanager.NewKeyFileStore(keysPath, ret) | ||||
| 	if err != nil { | ||||
| 		fatalf("Failed to create private key store in directory: %s", keysPath) | ||||
| 	} | ||||
| 
 | ||||
| 	ks := []trustmanager.KeyStore{fileKeyStore} | ||||
| 
 | ||||
| 	if withHardware { | ||||
| 		yubiStore, err := api.NewYubiKeyStore(fileKeyStore, ret) | ||||
| 		if err != nil { | ||||
| 			cmd.Println("No YubiKey detected - using local filesystem only.") | ||||
| 		} else { | ||||
| 			// Note that the order is important, since we want to prioritize
 | ||||
| 			// the yubikey store
 | ||||
| 			ks = []trustmanager.KeyStore{yubiStore, fileKeyStore} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return cryptoservice.NewCryptoService("", ks...) | ||||
| } | ||||
|  | @ -3,10 +3,21 @@ | |||
| package api_test | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 	"testing" | ||||
| 
 | ||||
| 	"github.com/docker/notary/signer" | ||||
| 	"github.com/docker/notary/tuf/data" | ||||
| 	"github.com/docker/notary/tuf/signed" | ||||
| 	"github.com/miekg/pkcs11" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 
 | ||||
| 	pb "github.com/docker/notary/proto" | ||||
| ) | ||||
| 
 | ||||
| func SetupHSMEnv(t *testing.T) (*pkcs11.Ctx, pkcs11.SessionHandle) { | ||||
|  | @ -41,3 +52,66 @@ func SetupHSMEnv(t *testing.T) (*pkcs11.Ctx, pkcs11.SessionHandle) { | |||
| 
 | ||||
| 	return p, session | ||||
| } | ||||
| 
 | ||||
| func TestHSMCreateKeyHandler(t *testing.T) { | ||||
| 	ctx, session := SetupHSMEnv(t) | ||||
| 	defer ctx.Destroy() | ||||
| 	defer ctx.Finalize() | ||||
| 	defer ctx.CloseSession(session) | ||||
| 	defer ctx.Logout(session) | ||||
| 
 | ||||
| 	cryptoService := signed.NewEd25519() | ||||
| 	setup(signer.CryptoServiceIndex{data.RSAKey: cryptoService}) | ||||
| 
 | ||||
| 	createKeyURL := fmt.Sprintf("%s/%s", createKeyBaseURL, data.RSAKey) | ||||
| 
 | ||||
| 	request, err := http.NewRequest("POST", createKeyURL, nil) | ||||
| 	assert.Nil(t, err) | ||||
| 
 | ||||
| 	res, err := http.DefaultClient.Do(request) | ||||
| 	assert.Nil(t, err) | ||||
| 
 | ||||
| 	jsonBlob, err := ioutil.ReadAll(res.Body) | ||||
| 	assert.Nil(t, err) | ||||
| 
 | ||||
| 	var keyInfo *pb.PublicKey | ||||
| 	err = json.Unmarshal(jsonBlob, &keyInfo) | ||||
| 	assert.Nil(t, err) | ||||
| 
 | ||||
| 	assert.Equal(t, 200, res.StatusCode) | ||||
| } | ||||
| 
 | ||||
| func TestHSMSignHandler(t *testing.T) { | ||||
| 	ctx, session := SetupHSMEnv(t) | ||||
| 	defer ctx.Destroy() | ||||
| 	defer ctx.Finalize() | ||||
| 	defer ctx.CloseSession(session) | ||||
| 	defer ctx.Logout(session) | ||||
| 
 | ||||
| 	cryptoService := signed.NewEd25519() | ||||
| 	setup(signer.CryptoServiceIndex{data.RSAKey: cryptoService}) | ||||
| 
 | ||||
| 	tufKey, _ := cryptoService.Create("", data.RSAKey) | ||||
| 
 | ||||
| 	sigRequest := &pb.SignatureRequest{KeyID: &pb.KeyID{ID: tufKey.ID()}, Content: make([]byte, 10)} | ||||
| 	requestJson, _ := json.Marshal(sigRequest) | ||||
| 
 | ||||
| 	reader = strings.NewReader(string(requestJson)) | ||||
| 
 | ||||
| 	request, err := http.NewRequest("POST", signBaseURL, reader) | ||||
| 
 | ||||
| 	assert.Nil(t, err) | ||||
| 
 | ||||
| 	res, err := http.DefaultClient.Do(request) | ||||
| 	assert.Nil(t, err) | ||||
| 
 | ||||
| 	jsonBlob, err := ioutil.ReadAll(res.Body) | ||||
| 	assert.Nil(t, err) | ||||
| 
 | ||||
| 	var sig *pb.Signature | ||||
| 	err = json.Unmarshal(jsonBlob, &sig) | ||||
| 	assert.Nil(t, err) | ||||
| 
 | ||||
| 	assert.Equal(t, tufKey.ID, sig.KeyInfo.KeyID.ID) | ||||
| 	assert.Equal(t, 200, res.StatusCode) | ||||
| } | ||||
|  |  | |||
|  | @ -15,7 +15,6 @@ import ( | |||
| 	"github.com/docker/notary/signer/api" | ||||
| 	"github.com/docker/notary/trustmanager" | ||||
| 	"github.com/docker/notary/tuf/data" | ||||
| 	"github.com/docker/notary/tuf/signed" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| 
 | ||||
| 	pb "github.com/docker/notary/proto" | ||||
|  | @ -125,34 +124,6 @@ func TestKeyInfoHandlerReturns404WithNonexistentKey(t *testing.T) { | |||
| 	assert.Equal(t, 404, res.StatusCode) | ||||
| } | ||||
| 
 | ||||
| func TestHSMCreateKeyHandler(t *testing.T) { | ||||
| 	ctx, session := SetupHSMEnv(t) | ||||
| 	defer ctx.Destroy() | ||||
| 	defer ctx.Finalize() | ||||
| 	defer ctx.CloseSession(session) | ||||
| 	defer ctx.Logout(session) | ||||
| 
 | ||||
| 	cryptoService := signed.NewEd25519() | ||||
| 	setup(signer.CryptoServiceIndex{data.RSAKey: cryptoService}) | ||||
| 
 | ||||
| 	createKeyURL := fmt.Sprintf("%s/%s", createKeyBaseURL, data.RSAKey) | ||||
| 
 | ||||
| 	request, err := http.NewRequest("POST", createKeyURL, nil) | ||||
| 	assert.Nil(t, err) | ||||
| 
 | ||||
| 	res, err := http.DefaultClient.Do(request) | ||||
| 	assert.Nil(t, err) | ||||
| 
 | ||||
| 	jsonBlob, err := ioutil.ReadAll(res.Body) | ||||
| 	assert.Nil(t, err) | ||||
| 
 | ||||
| 	var keyInfo *pb.PublicKey | ||||
| 	err = json.Unmarshal(jsonBlob, &keyInfo) | ||||
| 	assert.Nil(t, err) | ||||
| 
 | ||||
| 	assert.Equal(t, 200, res.StatusCode) | ||||
| } | ||||
| 
 | ||||
| func TestSoftwareCreateKeyHandler(t *testing.T) { | ||||
| 	keyStore := trustmanager.NewKeyMemoryStore(passphraseRetriever) | ||||
| 	cryptoService := cryptoservice.NewCryptoService("", keyStore) | ||||
|  | @ -176,41 +147,6 @@ func TestSoftwareCreateKeyHandler(t *testing.T) { | |||
| 	assert.Nil(t, err) | ||||
| } | ||||
| 
 | ||||
| func TestHSMSignHandler(t *testing.T) { | ||||
| 	ctx, session := SetupHSMEnv(t) | ||||
| 	defer ctx.Destroy() | ||||
| 	defer ctx.Finalize() | ||||
| 	defer ctx.CloseSession(session) | ||||
| 	defer ctx.Logout(session) | ||||
| 
 | ||||
| 	cryptoService := signed.NewEd25519() | ||||
| 	setup(signer.CryptoServiceIndex{data.RSAKey: cryptoService}) | ||||
| 
 | ||||
| 	tufKey, _ := cryptoService.Create("", data.RSAKey) | ||||
| 
 | ||||
| 	sigRequest := &pb.SignatureRequest{KeyID: &pb.KeyID{ID: tufKey.ID()}, Content: make([]byte, 10)} | ||||
| 	requestJson, _ := json.Marshal(sigRequest) | ||||
| 
 | ||||
| 	reader = strings.NewReader(string(requestJson)) | ||||
| 
 | ||||
| 	request, err := http.NewRequest("POST", signBaseURL, reader) | ||||
| 
 | ||||
| 	assert.Nil(t, err) | ||||
| 
 | ||||
| 	res, err := http.DefaultClient.Do(request) | ||||
| 	assert.Nil(t, err) | ||||
| 
 | ||||
| 	jsonBlob, err := ioutil.ReadAll(res.Body) | ||||
| 	assert.Nil(t, err) | ||||
| 
 | ||||
| 	var sig *pb.Signature | ||||
| 	err = json.Unmarshal(jsonBlob, &sig) | ||||
| 	assert.Nil(t, err) | ||||
| 
 | ||||
| 	assert.Equal(t, tufKey.ID, sig.KeyInfo.KeyID.ID) | ||||
| 	assert.Equal(t, 200, res.StatusCode) | ||||
| } | ||||
| 
 | ||||
| func TestSoftwareSignHandler(t *testing.T) { | ||||
| 	keyStore := trustmanager.NewKeyMemoryStore(passphraseRetriever) | ||||
| 	cryptoService := cryptoservice.NewCryptoService("", keyStore) | ||||
|  |  | |||
|  | @ -1,13 +1,6 @@ | |||
| // +build pkcs11
 | ||||
| 
 | ||||
| package keys | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 
 | ||||
| 	"github.com/docker/notary/tuf/data" | ||||
| 	"github.com/miekg/pkcs11" | ||||
| ) | ||||
| import "errors" | ||||
| 
 | ||||
| var ( | ||||
| 	// ErrExists happens when a Key already exists in a database
 | ||||
|  | @ -17,49 +10,3 @@ var ( | |||
| 	// ErrFailedKeyGeneration happens when there is a failure in generating a key
 | ||||
| 	ErrFailedKeyGeneration = errors.New("notary-signer: failed to generate new key") | ||||
| ) | ||||
| 
 | ||||
| // HSMRSAKey represents the information for an HSMRSAKey with ObjectHandle for private portion
 | ||||
| type HSMRSAKey struct { | ||||
| 	id      string | ||||
| 	public  []byte | ||||
| 	private pkcs11.ObjectHandle | ||||
| } | ||||
| 
 | ||||
| // NewHSMRSAKey returns a HSMRSAKey
 | ||||
| func NewHSMRSAKey(public []byte, private pkcs11.ObjectHandle) *HSMRSAKey { | ||||
| 	return &HSMRSAKey{ | ||||
| 		public:  public, | ||||
| 		private: private, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Algorithm implements a method of the data.Key interface
 | ||||
| func (rsa *HSMRSAKey) Algorithm() string { | ||||
| 	return data.RSAKey | ||||
| } | ||||
| 
 | ||||
| // ID implements a method of the data.Key interface
 | ||||
| func (rsa *HSMRSAKey) ID() string { | ||||
| 	if rsa.id == "" { | ||||
| 		pubK := data.NewPublicKey(rsa.Algorithm(), rsa.Public()) | ||||
| 		rsa.id = pubK.ID() | ||||
| 	} | ||||
| 	return rsa.id | ||||
| } | ||||
| 
 | ||||
| // Public implements a method of the data.Key interface
 | ||||
| func (rsa *HSMRSAKey) Public() []byte { | ||||
| 	return rsa.public | ||||
| } | ||||
| 
 | ||||
| // Private implements a method of the data.PrivateKey interface
 | ||||
| func (rsa *HSMRSAKey) Private() []byte { | ||||
| 	// Not possible to return private key bytes from a hardware device
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // PKCS11ObjectHandle returns the PKCS11 object handle stored in the HSMRSAKey
 | ||||
| // structure
 | ||||
| func (rsa *HSMRSAKey) PKCS11ObjectHandle() pkcs11.ObjectHandle { | ||||
| 	return rsa.private | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,54 @@ | |||
| // +build pkcs11
 | ||||
| 
 | ||||
| package keys | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/docker/notary/tuf/data" | ||||
| 	"github.com/miekg/pkcs11" | ||||
| ) | ||||
| 
 | ||||
| // HSMRSAKey represents the information for an HSMRSAKey with ObjectHandle for private portion
 | ||||
| type HSMRSAKey struct { | ||||
| 	id      string | ||||
| 	public  []byte | ||||
| 	private pkcs11.ObjectHandle | ||||
| } | ||||
| 
 | ||||
| // NewHSMRSAKey returns a HSMRSAKey
 | ||||
| func NewHSMRSAKey(public []byte, private pkcs11.ObjectHandle) *HSMRSAKey { | ||||
| 	return &HSMRSAKey{ | ||||
| 		public:  public, | ||||
| 		private: private, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Algorithm implements a method of the data.Key interface
 | ||||
| func (rsa *HSMRSAKey) Algorithm() string { | ||||
| 	return data.RSAKey | ||||
| } | ||||
| 
 | ||||
| // ID implements a method of the data.Key interface
 | ||||
| func (rsa *HSMRSAKey) ID() string { | ||||
| 	if rsa.id == "" { | ||||
| 		pubK := data.NewPublicKey(rsa.Algorithm(), rsa.Public()) | ||||
| 		rsa.id = pubK.ID() | ||||
| 	} | ||||
| 	return rsa.id | ||||
| } | ||||
| 
 | ||||
| // Public implements a method of the data.Key interface
 | ||||
| func (rsa *HSMRSAKey) Public() []byte { | ||||
| 	return rsa.public | ||||
| } | ||||
| 
 | ||||
| // Private implements a method of the data.PrivateKey interface
 | ||||
| func (rsa *HSMRSAKey) Private() []byte { | ||||
| 	// Not possible to return private key bytes from a hardware device
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // PKCS11ObjectHandle returns the PKCS11 object handle stored in the HSMRSAKey
 | ||||
| // structure
 | ||||
| func (rsa *HSMRSAKey) PKCS11ObjectHandle() pkcs11.ObjectHandle { | ||||
| 	return rsa.private | ||||
| } | ||||
		Loading…
	
		Reference in New Issue