Skip to content

Commit

Permalink
[FAB-7516] Cert/Key embed & file path combo
Browse files Browse the repository at this point in the history
Change-Id: I59c3d22cd01034fc7a79f70138dc81401f1820a4
Signed-off-by: Baha Shaaban <baha.shaaban@securekey.com>
  • Loading branch information
Baha Shaaban committed Dec 20, 2017
1 parent 24f9ecc commit 56a7adb
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 13 deletions.
5 changes: 3 additions & 2 deletions internal/github.com/hyperledger/fabric-ca/util/csp.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,11 @@ func ImportBCCSPKeyFromPEM(keyFile string, myCSP apicryptosuite.CryptoSuite, tem
}

key, err := ImportBCCSPKeyFromPEMBytes(keyBuff, myCSP, temporary)

if err != nil {
return nil, errors.WithMessage(err, fmt.Sprintf("Failed parsing private key from %s", keyFile))
}

return key, nil
}

Expand All @@ -159,6 +159,7 @@ func ImportBCCSPKeyFromPEMBytes(keyBuff []byte, myCSP apicryptosuite.CryptoSuite
return nil, errors.Errorf("Failed to import key: invalid secret key type")
}
}

// LoadX509KeyPair reads and parses a public/private key pair from a pair
// of files. The files must contain PEM encoded data. The certificate file
// may contain intermediate certificates following the leaf certificate to
Expand Down
61 changes: 51 additions & 10 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -826,25 +826,66 @@ func (c *Config) TLSClientCerts() ([]tls.Certificate, error) {

clientConfig := config.Client
var clientCerts tls.Certificate

var cb, kb []byte
if clientConfig.TLSCerts.Client.CertPem != "" {
clientCerts, err = tls.X509KeyPair([]byte(clientConfig.TLSCerts.Client.CertPem), []byte(clientConfig.TLSCerts.Client.KeyPem))
if err != nil {
return nil, errors.Errorf("Error loading cert/key pair as TLS client credentials: %v", err)
cb = []byte(clientConfig.TLSCerts.Client.CertPem)
if clientConfig.TLSCerts.Client.KeyPem != "" {
kb = []byte(clientConfig.TLSCerts.Client.KeyPem)
} else if clientConfig.TLSCerts.Client.Keyfile != "" {
kb, err = loadByteKeyOrCertFromFile(&clientConfig, true)
if err != nil {
return nil, err
}
} else {
return nil, errors.Errorf("Missing key for cert/key pair TLS client credentials. Ensure either the key file path or the key content is embedded in the client config.")
}

} else if clientConfig.TLSCerts.Client.Certfile != "" {
clientConfig.TLSCerts.Client.Keyfile = substPathVars(clientConfig.TLSCerts.Client.Keyfile)
clientConfig.TLSCerts.Client.Certfile = substPathVars(clientConfig.TLSCerts.Client.Certfile)
clientCerts, err = tls.LoadX509KeyPair(clientConfig.TLSCerts.Client.Certfile, clientConfig.TLSCerts.Client.Keyfile)
if err != nil {
return nil, errors.Errorf("Error loading cert/key pair as TLS client credentials: %v", err)
cb, err = loadByteKeyOrCertFromFile(&clientConfig, false)
if clientConfig.TLSCerts.Client.KeyPem != "" {
kb = []byte(clientConfig.TLSCerts.Client.KeyPem)
if err != nil {
return nil, err
}
} else if clientConfig.TLSCerts.Client.Keyfile != "" {
kb, err = loadByteKeyOrCertFromFile(&clientConfig, true)
if err != nil {
return nil, err
}
} else {
return nil, errors.Errorf("Missing key for cert/key pair TLS client credentials. Ensure either the key file path or the key content is embedded in the client config.")
}
} else {
// if no cert found in the config, return empty cert chain
return []tls.Certificate{clientCerts}, nil
}

// load the key/cert pair from []byte
clientCerts, err = tls.X509KeyPair(cb, kb)
if err != nil {
return nil, errors.Errorf("Error loading cert/key pair as TLS client credentials: %v", err)
}

return []tls.Certificate{clientCerts}, nil
}

func loadByteKeyOrCertFromFile(c *apiconfig.ClientConfig, isKey bool) ([]byte, error) {
var path string
a := "key"
if isKey {
path = substPathVars(c.TLSCerts.Client.Keyfile)
c.TLSCerts.Client.Keyfile = path
} else {
a = "cert"
path = substPathVars(c.TLSCerts.Client.Certfile)
c.TLSCerts.Client.Certfile = path
}
bts, err := ioutil.ReadFile(path)
if err != nil {
return nil, errors.Errorf("Error loading %s file from '%s' err: %v", a, path, err)
}
return bts, nil
}

// loadCAKey
func loadCAKey(rawData []byte) (*x509.Certificate, error) {
block, _ := pem.Decode(rawData)
Expand Down
72 changes: 71 additions & 1 deletion pkg/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,76 @@ YZjcDi7YEOZ3Fs1hxKmIxR+TTR2vf9I=
}
}

func TestTLSClientCertFromPemAndKeyFromFile(t *testing.T) {
configImpl.networkConfig.Client.TLSCerts.Client.Certfile = ""
configImpl.networkConfig.Client.TLSCerts.Client.Keyfile = "../../test/fixtures/config/mutual_tls/client_sdk_go-key.pem"

configImpl.networkConfig.Client.TLSCerts.Client.CertPem = `-----BEGIN CERTIFICATE-----
MIIC5TCCAkagAwIBAgIUMYhiY5MS3jEmQ7Fz4X/e1Dx33J0wCgYIKoZIzj0EAwQw
gYwxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdPbnRhcmlvMRAwDgYDVQQHEwdUb3Jv
bnRvMREwDwYDVQQKEwhsaW51eGN0bDEMMAoGA1UECxMDTGFiMTgwNgYDVQQDEy9s
aW51eGN0bCBFQ0MgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAoTGFiKTAe
Fw0xNzEyMDEyMTEzMDBaFw0xODEyMDEyMTEzMDBaMGMxCzAJBgNVBAYTAkNBMRAw
DgYDVQQIEwdPbnRhcmlvMRAwDgYDVQQHEwdUb3JvbnRvMREwDwYDVQQKEwhsaW51
eGN0bDEMMAoGA1UECxMDTGFiMQ8wDQYDVQQDDAZzZGtfZ28wdjAQBgcqhkjOPQIB
BgUrgQQAIgNiAAT6I1CGNrkchIAEmeJGo53XhDsoJwRiohBv2PotEEGuO6rMyaOu
pulj2VOj+YtgWw4ZtU49g4Nv6rq1QlKwRYyMwwRJSAZHIUMhYZjcDi7YEOZ3Fs1h
xKmIxR+TTR2vf9KjgZAwgY0wDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsG
AQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFDwS3xhpAWs81OVWvZt+iUNL
z26DMB8GA1UdIwQYMBaAFLRasbknomawJKuQGiyKs/RzTCujMBgGA1UdEQQRMA+C
DWZhYnJpY19zZGtfZ28wCgYIKoZIzj0EAwQDgYwAMIGIAkIAk1MxMogtMtNO0rM8
gw2rrxqbW67ulwmMQzp6EJbm/28T2pIoYWWyIwpzrquypI7BOuf8is5b7Jcgn9oz
7sdMTggCQgF7/8ZFl+wikAAPbciIL1I+LyCXKwXosdFL6KMT6/myYjsGNeeDeMbg
3YkZ9DhdH1tN4U/h+YulG/CkKOtUATtQxg==
-----END CERTIFICATE-----`

configImpl.networkConfig.Client.TLSCerts.Client.KeyPem = ""

certs, err := configImpl.TLSClientCerts()
if err != nil {
t.Fatalf("Expected no errors but got error instead: %s", err)
}

if len(certs) != 1 {
t.Fatalf("Expected only one tls cert struct")
}

emptyCert := tls.Certificate{}

if reflect.DeepEqual(certs[0], emptyCert) {
t.Fatalf("Actual cert is empty")
}
}

func TestTLSClientCertFromFileAndKeyFromPem(t *testing.T) {
configImpl.networkConfig.Client.TLSCerts.Client.Certfile = "../../test/fixtures/config/mutual_tls/client_sdk_go.pem"
configImpl.networkConfig.Client.TLSCerts.Client.Keyfile = ""

configImpl.networkConfig.Client.TLSCerts.Client.CertPem = ""

configImpl.networkConfig.Client.TLSCerts.Client.KeyPem = `-----BEGIN EC PRIVATE KEY-----
MIGkAgEBBDByldj7VTpqTQESGgJpR9PFW9b6YTTde2WN6/IiBo2nW+CIDmwQgmAl
c/EOc9wmgu+gBwYFK4EEACKhZANiAAT6I1CGNrkchIAEmeJGo53XhDsoJwRiohBv
2PotEEGuO6rMyaOupulj2VOj+YtgWw4ZtU49g4Nv6rq1QlKwRYyMwwRJSAZHIUMh
YZjcDi7YEOZ3Fs1hxKmIxR+TTR2vf9I=
-----END EC PRIVATE KEY-----`

certs, err := configImpl.TLSClientCerts()
if err != nil {
t.Fatalf("Expected no errors but got error instead: %s", err)
}

if len(certs) != 1 {
t.Fatalf("Expected only one tls cert struct")
}

emptyCert := tls.Certificate{}

if reflect.DeepEqual(certs[0], emptyCert) {
t.Fatalf("Actual cert is empty")
}
}

func TestTLSClientCertsPemBeforeFiles(t *testing.T) {
// files have incorrect paths, but pems are loaded first
configImpl.networkConfig.Client.TLSCerts.Client.Certfile = "/test/fixtures/config/mutual_tls/client_sdk_go.pem"
Expand Down Expand Up @@ -1042,7 +1112,7 @@ func TestTLSClientCertsNoCerts(t *testing.T) {
}

if len(certs) != 1 {
t.Fatalf("Expected only emppty tls cert struct")
t.Fatalf("Expected only empty tls cert struct")
}

emptyCert := tls.Certificate{}
Expand Down

0 comments on commit 56a7adb

Please sign in to comment.