Skip to content

Commit

Permalink
[FAB-3453] cryptogen: generate tls artifacts
Browse files Browse the repository at this point in the history
This patch structures the cryptogen output in a way that
makes it more directly consumable.  The output for each
node looks like:

└── peer4.org1
    ├── msp
    │   ├── admincerts
    │   │   └── Admin@org1-cert.pem
    │   ├── cacerts
    │   │   └── org1-cert.pem
    │   ├── keystore
    │   │   └── 0aa7a89070ce8322a4dc3fac2206fa8313b88fb625c70963934714d4129d2897_sk
    │   └── signcerts
    │       └── peer4.org1-cert.pem
    └── tls
        ├── ca.crt
        ├── server.crt
        └── server.key

The notable differences are that we push the msp content down under ./msp, and we
add the ./tls directory.  The crypto material under tls is simply duplicated
content from the MSP, as appropriate, to present a consistent layout for
consumption by the TLS layer.  We also update the default paths in the config
to be consistent with this layout.

Fixes FAB-3453

Change-Id: I8e149035b92a4758d6c87c03306c08b82687683f
Signed-off-by: Gregory Haskins <gregory.haskins@gmail.com>
  • Loading branch information
ghaskins committed Apr 28, 2017
1 parent f825608 commit 0d8c255
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 60 deletions.
6 changes: 3 additions & 3 deletions common/tools/cryptogen/ca/ca_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,23 +71,23 @@ func TestGenerateSignCertificate(t *testing.T) {
rootCA, err := ca.NewCA(caDir, testCA2Name)
assert.NoError(t, err, "Error generating CA")

err = rootCA.SignCertificate(certDir, testName, ecPubKey)
_, err = rootCA.SignCertificate(certDir, testName, ecPubKey)
assert.NoError(t, err, "Failed to generate signed certificate")

// check to make sure the signed public key was stored
pemFile := filepath.Join(certDir, testName+"-cert.pem")
assert.Equal(t, true, checkForFile(pemFile),
"Expected to find file "+pemFile)

err = rootCA.SignCertificate(certDir, "empty/CA", ecPubKey)
_, err = rootCA.SignCertificate(certDir, "empty/CA", ecPubKey)
assert.Error(t, err, "Bad name should fail")

// use an empty CA to test error path
badCA := &ca.CA{
Name: "badCA",
SignCert: &x509.Certificate{},
}
err = badCA.SignCertificate(certDir, testName, &ecdsa.PublicKey{})
_, err = badCA.SignCertificate(certDir, testName, &ecdsa.PublicKey{})
assert.Error(t, err, "Empty CA should not be able to sign")
cleanup(testDir)

Expand Down
8 changes: 4 additions & 4 deletions common/tools/cryptogen/ca/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func NewCA(baseDir, name string) (*CA, error) {

// SignCertificate creates a signed certificate based on a built-in template
// and saves it in baseDir/name
func (ca *CA) SignCertificate(baseDir, name string, pub *ecdsa.PublicKey) error {
func (ca *CA) SignCertificate(baseDir, name string, pub *ecdsa.PublicKey) (*x509.Certificate, error) {

template := x509Template()
template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}
Expand All @@ -97,14 +97,14 @@ func (ca *CA) SignCertificate(baseDir, name string, pub *ecdsa.PublicKey) error

template.Subject = subject

_, err := genCertificateECDSA(baseDir, name, &template, ca.SignCert,
cert, err := genCertificateECDSA(baseDir, name, &template, ca.SignCert,
pub, ca.Signer)

if err != nil {
return err
return nil, err
}

return nil
return cert, nil
}

// default template for X509 subject
Expand Down
11 changes: 6 additions & 5 deletions common/tools/cryptogen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,9 @@ func generatePeerOrg(baseDir string, orgSpec OrgSpec) {

// copy the admin cert to each of the org's peer's MSP admincerts
for _, peerName := range peerNames {
err = copyAdminCert(usersDir, filepath.Join(peersDir, peerName,
"admincerts"), adminUserName)
err = copyAdminCert(usersDir,
filepath.Join(peersDir, peerName, "msp", "admincerts"),
adminUserName)
if err != nil {
fmt.Printf("Error copying admin cert for org %s peer %s:\n%v\n",
orgName, peerName, err)
Expand All @@ -372,7 +373,7 @@ func copyAdminCert(usersDir, adminCertsDir, adminUserName string) error {
if err != nil {
return err
}
err = copyFile(filepath.Join(usersDir, adminUserName, "signcerts",
err = copyFile(filepath.Join(usersDir, adminUserName, "msp", "signcerts",
adminUserName+"-cert.pem"), filepath.Join(adminCertsDir,
adminUserName+"-cert.pem"))
if err != nil {
Expand Down Expand Up @@ -444,8 +445,8 @@ func generateOrdererOrg(baseDir string, orgSpec OrgSpec) {

// copy the admin cert to each of the org's orderers's MSP admincerts
for _, ordererName := range ordererNames {
err = copyAdminCert(usersDir, filepath.Join(orderersDir, ordererName,
"admincerts"), adminUserName)
err = copyAdminCert(usersDir,
filepath.Join(orderersDir, ordererName, "msp", "admincerts"), adminUserName)
if err != nil {
fmt.Printf("Error copying admin cert for org %s orderer %s:\n%v\n",
orgName, ordererName, err)
Expand Down
140 changes: 102 additions & 38 deletions common/tools/cryptogen/msp/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,59 +21,94 @@ import (
"os"
"path/filepath"

"encoding/hex"
"io"

"github.com/hyperledger/fabric/bccsp"
"github.com/hyperledger/fabric/common/tools/cryptogen/ca"
"github.com/hyperledger/fabric/common/tools/cryptogen/csp"
)

func GenerateLocalMSP(baseDir, name string, rootCA *ca.CA) error {

var response error
// create folder structure
err := createFolderStructure(baseDir)
response = err
if err == nil {
// generate private key
priv, _, err := csp.GeneratePrivateKey(filepath.Join(baseDir, "keystore"))
response = err
if err == nil {
// get public signing certificate
ecPubKey, err := csp.GetECPublicKey(priv)
response = err
if err == nil {
err = rootCA.SignCertificate(filepath.Join(baseDir, "signcerts"),
name, ecPubKey)
response = err
if err == nil {
// write root cert to folders
folders := []string{"admincerts", "cacerts"}
for _, folder := range folders {
err = x509ToFile(filepath.Join(baseDir, folder), rootCA.Name, rootCA.SignCert)
if err != nil {
return err
}
}
}
}
mspDir := filepath.Join(baseDir, "msp")
tlsDir := filepath.Join(baseDir, "tls")

err := createFolderStructure(mspDir)
if err != nil {
return err
}

err = os.MkdirAll(tlsDir, 0755)
if err != nil {
return err
}

// get keystore path
keystore := filepath.Join(mspDir, "keystore")

// generate private key
priv, _, err := csp.GeneratePrivateKey(keystore)
if err != nil {
return err
}

// get public signing certificate
ecPubKey, err := csp.GetECPublicKey(priv)
if err != nil {
return err
}

cert, err := rootCA.SignCertificate(filepath.Join(mspDir, "signcerts"), name, ecPubKey)
if err != nil {
return err
}

// write artifacts to MSP folders
folders := []string{"admincerts", "cacerts"}
for _, folder := range folders {
err = x509Export(filepath.Join(mspDir, folder, x509Filename(rootCA.Name)), rootCA.SignCert)
if err != nil {
return err
}
}
return response

// write artifacts to TLS folder
err = x509Export(filepath.Join(tlsDir, "ca.crt"), rootCA.SignCert)
if err != nil {
return err
}

err = x509Export(filepath.Join(tlsDir, "server.crt"), cert)
if err != nil {
return err
}

err = keyExport(keystore, filepath.Join(tlsDir, "server.key"), priv)
if err != nil {
return err
}

return nil
}

func GenerateVerifyingMSP(baseDir string, rootCA *ca.CA) error {

// create folder structure
err := createFolderStructure(baseDir)
if err == nil {
// write public cert to appropriate folders
// write MSP cert to appropriate folders
folders := []string{"admincerts", "cacerts", "signcerts"}
for _, folder := range folders {
err = x509ToFile(filepath.Join(baseDir, folder), rootCA.Name, rootCA.SignCert)
err = x509Export(filepath.Join(baseDir, folder, x509Filename(rootCA.Name)), rootCA.SignCert)
if err != nil {
return err
}
}
}
return err

return nil
}

func createFolderStructure(rootDir string) error {
Expand All @@ -92,21 +127,50 @@ func createFolderStructure(rootDir string) error {
return err
}
}

return nil
}

func x509ToFile(baseDir, name string, cert *x509.Certificate) error {
func x509Filename(name string) string {
return name + "-cert.pem"
}

//write cert out to file
fileName := filepath.Join(baseDir, name+"-cert.pem")
certFile, err := os.Create(fileName)
func x509Export(path string, cert *x509.Certificate) error {
return pemExport(path, "CERTIFICATE", cert.Raw)
}

func copyFile(src, dst string) error {
in, err := os.Open(src)
if err != nil {
return err
}
defer in.Close()
out, err := os.Create(dst)
if err != nil {
return err
}
defer out.Close()
_, err = io.Copy(out, in)
cerr := out.Close()
if err != nil {
return err
}
//pem encode the cert
err = pem.Encode(certFile, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw})
certFile.Close()
return cerr
}

func keyExport(keystore, output string, key bccsp.Key) error {
id := hex.EncodeToString(key.SKI())

return copyFile(filepath.Join(keystore, id+"_sk"), output)
}

return err
func pemExport(path, pemType string, bytes []byte) error {
//write pem out to file
file, err := os.Create(path)
if err != nil {
return err
}
defer file.Close()

return pem.Encode(file, &pem.Block{Type: pemType, Bytes: bytes})
}
2 changes: 1 addition & 1 deletion common/tools/cryptogen/msp/msp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func TestGenerateLocalMSP(t *testing.T) {
mspDir := filepath.Join(testDir, "msp")
rootCA, err := ca.NewCA(caDir, testCAName)
assert.NoError(t, err, "Error generating CA")
err = msp.GenerateLocalMSP(mspDir, testName, rootCA)
err = msp.GenerateLocalMSP(testDir, testName, rootCA)
assert.NoError(t, err, "Failed to generate local MSP")

// check to see that the right files were generated/saved
Expand Down
10 changes: 3 additions & 7 deletions sampleconfig/core.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -193,15 +193,11 @@ peer:
tls:
enabled: false
cert:
file: peer/tls.crt
file: tls/server.crt
key:
file: peer/tls.key
# Root cert file for selfsigned certificates
# This represents a self-signed x509 cert that was used to sign the cert.file,
# this is sent to client to validate the recived certificate from server when
# establishing TLS connection
file: tls/server.key
rootcert:
file: peer/tls.crt
file: tls/ca.crt

# The server name use to verify the hostname returned by TLS handshake
serverhostoverride:
Expand Down
5 changes: 3 additions & 2 deletions sampleconfig/orderer.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ General:
# TLS: TLS settings for the GRPC server.
TLS:
Enabled: false
PrivateKey:
Certificate:
PrivateKey: tls/server.key
Certificate: tls/server.crt
RootCAs:
- tls/ca.crt
ClientAuthEnabled: false
ClientRootCAs:

Expand Down

0 comments on commit 0d8c255

Please sign in to comment.