Ensure that tests pass and binaries build without the pkcs11 build tag.

Signed-off-by: Ying Li <ying.li@docker.com>
Signed-off-by: David Lawrence <david.lawrence@docker.com>

Signed-off-by: Ying Li <ying.li@docker.com> (github: endophage)
This commit is contained in:
Ying Li 2015-11-07 21:17:40 -08:00 committed by David Lawrence
parent 29c6b63c81
commit 4867410e98
7 changed files with 200 additions and 179 deletions

View File

@ -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 {

View File

@ -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)
}

41
cmd/notary/keys_pkcs11.go Normal file
View File

@ -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...)
}

View File

@ -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)
}

View File

@ -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)

View File

@ -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
}

View File

@ -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
}