Skip to content

Commit

Permalink
Allow client TLS certificate and key to be specified in connection pr…
Browse files Browse the repository at this point in the history
…ofile (#261)

Signed-off-by: Sheng Guo <[email protected]>
(cherry picked from commit 678746b)
  • Loading branch information
irririki authored and bestbeforetoday committed Feb 13, 2023
1 parent 51ddbbf commit 7fac5e4
Show file tree
Hide file tree
Showing 9 changed files with 289 additions and 51 deletions.
32 changes: 16 additions & 16 deletions src/main/java/org/hyperledger/fabric/sdk/Channel.java
Original file line number Diff line number Diff line change
Expand Up @@ -1627,25 +1627,25 @@ public Orderer addOrderer(SDOrdererAdditionInfo sdOrdererAdditionInfo) throws In

String protocol = (String) findClientProp(config, "protocol", mspid, endpoint, sdOrdererAdditionInfo.isTLS() ? "grpcs:" : "grpc:");

String clientCertFile = (String) findClientProp(config, "clientCertFile", mspid, endpoint, null);
String clientCertFile = (String) findClientProp(config, NetworkConfig.CLIENT_CERT_FILE, mspid, endpoint, null);

if (null != clientCertFile) {
properties.put("clientCertFile", clientCertFile);
properties.put(NetworkConfig.CLIENT_CERT_FILE, clientCertFile);
}

String clientKeyFile = (String) findClientProp(config, "clientKeyFile", mspid, endpoint, null);
String clientKeyFile = (String) findClientProp(config, NetworkConfig.CLIENT_KEY_FILE, mspid, endpoint, null);
if (null != clientKeyFile) {
properties.put("clientKeyFile", clientKeyFile);
properties.put(NetworkConfig.CLIENT_KEY_FILE, clientKeyFile);
}

byte[] clientCertBytes = (byte[]) findClientProp(config, "clientCertBytes", mspid, endpoint, null);
byte[] clientCertBytes = (byte[]) findClientProp(config, NetworkConfig.CLIENT_CERT_BYTES, mspid, endpoint, null);
if (null != clientCertBytes) {
properties.put("clientCertBytes", clientCertBytes);
properties.put(NetworkConfig.CLIENT_CERT_BYTES, clientCertBytes);
}

byte[] clientKeyBytes = (byte[]) findClientProp(config, "clientKeyBytes", mspid, endpoint, null);
byte[] clientKeyBytes = (byte[]) findClientProp(config, NetworkConfig.CLIENT_KEY_BYTES, mspid, endpoint, null);
if (null != clientKeyBytes) {
properties.put("clientKeyBytes", clientKeyBytes);
properties.put(NetworkConfig.CLIENT_KEY_BYTES, clientKeyBytes);
}

String hostnameOverride = (String) findClientProp(config, "hostnameOverride", mspid, endpoint, null);
Expand Down Expand Up @@ -1693,23 +1693,23 @@ public Peer addPeer(SDPeerAdditionInfo sdPeerAddition) throws InvalidArgumentExc

}

String clientCertFile = (String) findClientProp(config, "clientCertFile", mspid, endpoint, null);
String clientCertFile = (String) findClientProp(config, NetworkConfig.CLIENT_CERT_FILE, mspid, endpoint, null);

byte[] clientCertBytes = (byte[]) findClientProp(config, "clientCertBytes", mspid, endpoint, null);
byte[] clientCertBytes = (byte[]) findClientProp(config, NetworkConfig.CLIENT_CERT_BYTES, mspid, endpoint, null);
if (null != clientCertBytes) {
properties.put("clientCertBytes", clientCertBytes);
properties.put(NetworkConfig.CLIENT_CERT_BYTES, clientCertBytes);
} else if (null != clientCertFile) {
properties.put("clientCertFile", clientCertFile);
properties.put(NetworkConfig.CLIENT_CERT_FILE, clientCertFile);
}

properties.put(Peer.PEER_ORGANIZATION_MSPID_PROPERTY, sdPeerAddition.getMspId());

byte[] clientKeyBytes = (byte[]) findClientProp(config, "clientKeyBytes", mspid, endpoint, null);
String clientKeyFile = (String) findClientProp(config, "clientKeyFile", mspid, endpoint, null);
byte[] clientKeyBytes = (byte[]) findClientProp(config, NetworkConfig.CLIENT_KEY_BYTES, mspid, endpoint, null);
String clientKeyFile = (String) findClientProp(config, NetworkConfig.CLIENT_KEY_FILE, mspid, endpoint, null);
if (null != clientKeyBytes) {
properties.put("clientKeyBytes", clientKeyBytes);
properties.put(NetworkConfig.CLIENT_KEY_BYTES, clientKeyBytes);
} else if (null != clientKeyFile) {
properties.put("clientKeyFile", clientKeyFile);
properties.put(NetworkConfig.CLIENT_KEY_FILE, clientKeyFile);
}

String hostnameOverride = (String) findClientProp(config, "hostnameOverride", mspid, endpoint, null);
Expand Down
53 changes: 27 additions & 26 deletions src/main/java/org/hyperledger/fabric/sdk/Endpoint.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
import static org.hyperledger.fabric.sdk.helper.Utils.parseGrpcUrl;

class Endpoint {

private static final Log logger = LogFactory.getLog(Endpoint.class);

private static final String SSLPROVIDER = Config.getConfig().getDefaultSSLProvider();
Expand Down Expand Up @@ -172,28 +173,28 @@ class Endpoint {
}
// check for mutual TLS - both clientKey and clientCert must be present
byte[] ckb = null, ccb = null;
if (properties.containsKey("clientKeyFile") && properties.containsKey("clientKeyBytes")) {
if (properties.containsKey(NetworkConfig.CLIENT_KEY_FILE) && properties.containsKey(NetworkConfig.CLIENT_KEY_BYTES)) {
throw new RuntimeException("Properties \"clientKeyFile\" and \"clientKeyBytes\" must cannot both be set");
} else if (properties.containsKey("clientCertFile") && properties.containsKey("clientCertBytes")) {
} else if (properties.containsKey(NetworkConfig.CLIENT_CERT_FILE) && properties.containsKey(NetworkConfig.CLIENT_CERT_BYTES)) {
throw new RuntimeException("Properties \"clientCertFile\" and \"clientCertBytes\" must cannot both be set");
} else if (properties.containsKey("clientKeyFile") || properties.containsKey("clientCertFile")) {
if ((properties.getProperty("clientKeyFile") != null) && (properties.getProperty("clientCertFile") != null)) {
} else if (properties.containsKey(NetworkConfig.CLIENT_KEY_FILE) || properties.containsKey(NetworkConfig.CLIENT_CERT_FILE)) {
if ((properties.getProperty(NetworkConfig.CLIENT_KEY_FILE) != null) && (properties.getProperty(NetworkConfig.CLIENT_CERT_FILE) != null)) {
try {
logger.trace(format("Endpoint %s reading clientKeyFile: %s", url, properties.getProperty("clientKeyFile")));
ckb = Files.readAllBytes(Paths.get(properties.getProperty("clientKeyFile")));
logger.trace(format("Endpoint %s reading clientCertFile: %s", url, properties.getProperty("clientCertFile")));
ccb = Files.readAllBytes(Paths.get(properties.getProperty("clientCertFile")));
logger.trace(format("Endpoint %s reading clientKeyFile: %s", url, properties.getProperty(NetworkConfig.CLIENT_KEY_FILE)));
ckb = Files.readAllBytes(Paths.get(properties.getProperty(NetworkConfig.CLIENT_KEY_FILE)));
logger.trace(format("Endpoint %s reading clientCertFile: %s", url, properties.getProperty(NetworkConfig.CLIENT_CERT_FILE)));
ccb = Files.readAllBytes(Paths.get(properties.getProperty(NetworkConfig.CLIENT_CERT_FILE)));
} catch (IOException e) {
throw new RuntimeException("Failed to parse TLS client key and/or cert", e);
}
} else {
throw new RuntimeException("Properties \"clientKeyFile\" and \"clientCertFile\" must both be set or both be null");
throw new RuntimeException(String.format("Properties \"%s\" and \"%s\" must both be set or both be null", NetworkConfig.CLIENT_KEY_FILE, NetworkConfig.CLIENT_CERT_FILE));
}
} else if (properties.containsKey("clientKeyBytes") || properties.containsKey("clientCertBytes")) {
ckb = (byte[]) properties.get("clientKeyBytes");
ccb = (byte[]) properties.get("clientCertBytes");
} else if (properties.containsKey(NetworkConfig.CLIENT_KEY_BYTES) || properties.containsKey(NetworkConfig.CLIENT_CERT_BYTES)) {
ckb = (byte[]) properties.get(NetworkConfig.CLIENT_KEY_BYTES);
ccb = (byte[]) properties.get(NetworkConfig.CLIENT_CERT_BYTES);
if ((ckb == null) || (ccb == null)) {
throw new RuntimeException("Properties \"clientKeyBytes\" and \"clientCertBytes\" must both be set or both be null");
throw new RuntimeException(String.format("Properties \"%s\" and \"%s\" must both be set or both be null", NetworkConfig.CLIENT_KEY_BYTES, NetworkConfig.CLIENT_CERT_BYTES));
}
}

Expand Down Expand Up @@ -400,28 +401,28 @@ AbstractMap.SimpleImmutableEntry<PrivateKey, X509Certificate[]> getClientTLSProp

// check for mutual TLS - both clientKey and clientCert must be present
byte[] ckb = null, ccb = null;
if (properties.containsKey("clientKeyFile") && properties.containsKey("clientKeyBytes")) {
if (properties.containsKey(NetworkConfig.CLIENT_KEY_FILE) && properties.containsKey(NetworkConfig.CLIENT_KEY_BYTES)) {
throw new RuntimeException("Properties \"clientKeyFile\" and \"clientKeyBytes\" must cannot both be set");
} else if (properties.containsKey("clientCertFile") && properties.containsKey("clientCertBytes")) {
} else if (properties.containsKey(NetworkConfig.CLIENT_CERT_FILE) && properties.containsKey(NetworkConfig.CLIENT_CERT_BYTES)) {
throw new RuntimeException("Properties \"clientCertFile\" and \"clientCertBytes\" must cannot both be set");
} else if (properties.containsKey("clientKeyFile") || properties.containsKey("clientCertFile")) {
if ((properties.getProperty("clientKeyFile") != null) && (properties.getProperty("clientCertFile") != null)) {
} else if (properties.containsKey(NetworkConfig.CLIENT_KEY_FILE) || properties.containsKey(NetworkConfig.CLIENT_CERT_FILE)) {
if ((properties.getProperty(NetworkConfig.CLIENT_KEY_FILE) != null) && (properties.getProperty(NetworkConfig.CLIENT_CERT_FILE) != null)) {
try {
logger.trace(format("Endpoint %s reading clientKeyFile: %s", url, new File(properties.getProperty("clientKeyFile")).getAbsolutePath()));
ckb = Files.readAllBytes(Paths.get(properties.getProperty("clientKeyFile")));
logger.trace(format("Endpoint %s reading clientCertFile: %s", url, new File(properties.getProperty("clientCertFile")).getAbsolutePath()));
ccb = Files.readAllBytes(Paths.get(properties.getProperty("clientCertFile")));
logger.trace(format("Endpoint %s reading clientKeyFile: %s", url, new File(properties.getProperty(NetworkConfig.CLIENT_KEY_FILE)).getAbsolutePath()));
ckb = Files.readAllBytes(Paths.get(properties.getProperty(NetworkConfig.CLIENT_KEY_FILE)));
logger.trace(format("Endpoint %s reading clientCertFile: %s", url, new File(properties.getProperty(NetworkConfig.CLIENT_CERT_FILE)).getAbsolutePath()));
ccb = Files.readAllBytes(Paths.get(properties.getProperty(NetworkConfig.CLIENT_CERT_FILE)));
} catch (IOException e) {
throw new RuntimeException("Failed to parse TLS client key and/or cert", e);
}
} else {
throw new RuntimeException("Properties \"clientKeyFile\" and \"clientCertFile\" must both be set or both be null");
throw new RuntimeException(String.format("Properties \"%s\" and \"%s\" must both be set or both be null", NetworkConfig.CLIENT_KEY_FILE, NetworkConfig.CLIENT_CERT_FILE));
}
} else if (properties.containsKey("clientKeyBytes") || properties.containsKey("clientCertBytes")) {
ckb = (byte[]) properties.get("clientKeyBytes");
ccb = (byte[]) properties.get("clientCertBytes");
} else if (properties.containsKey(NetworkConfig.CLIENT_KEY_BYTES) || properties.containsKey(NetworkConfig.CLIENT_CERT_BYTES)) {
ckb = (byte[]) properties.get(NetworkConfig.CLIENT_KEY_BYTES);
ccb = (byte[]) properties.get(NetworkConfig.CLIENT_CERT_BYTES);
if ((ckb == null) || (ccb == null)) {
throw new RuntimeException("Properties \"clientKeyBytes\" and \"clientCertBytes\" must both be set or both be null");
throw new RuntimeException(String.format("Properties \"%s\" and \"%s\" must both be set or both be null", NetworkConfig.CLIENT_KEY_BYTES, NetworkConfig.CLIENT_CERT_BYTES));
}
}

Expand Down
16 changes: 12 additions & 4 deletions src/main/java/org/hyperledger/fabric/sdk/NetworkConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@
*/

public class NetworkConfig {
public static final String CLIENT_CERT_BYTES = "clientCertBytes";

public static final String CLIENT_KEY_BYTES = "clientKeyBytes";

public static final String CLIENT_CERT_FILE = "clientCertFile";

public static final String CLIENT_KEY_FILE = "clientKeyFile";

private static final String URL_PROP_NAME = "url";

private final JsonObject jsonConfig;
Expand Down Expand Up @@ -843,22 +851,22 @@ private void getTLSCerts(JsonObject jsonOrderer, Properties props) {
String certfile = getJsonValueAsString(jsonTlsClientCerts.get("certfile"));

if (keyfile != null) {
props.put("tlsClientKeyFile", keyfile);
props.put(CLIENT_KEY_FILE, keyfile);
}

if (certfile != null) {
props.put("tlsClientCertFile", certfile);
props.put(CLIENT_CERT_FILE, certfile);
}

String keyBytes = getJsonValueAsString(jsonTlsClientCerts.get("keyPem"));
String certBytes = getJsonValueAsString(jsonTlsClientCerts.get("certPem"));

if (keyBytes != null) {
props.put("tlsClientKeyBytes", keyBytes.getBytes());
props.put(CLIENT_KEY_BYTES, keyBytes.getBytes());
}

if (certBytes != null) {
props.put("tlsClientCertBytes", certBytes.getBytes());
props.put(CLIENT_CERT_BYTES, certBytes.getBytes());
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/org/hyperledger/fabric_ca/sdk/HFCAClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -1617,17 +1617,17 @@ private void setUpSSL() throws InvalidArgumentException {
}
}

String tlsClientKeyFile = properties.getProperty("tlsClientKeyFile");
String tlsClientCertFile = properties.getProperty("tlsClientCertFile");
String tlsClientKeyFile = properties.getProperty(NetworkConfig.CLIENT_KEY_FILE);
String tlsClientCertFile = properties.getProperty(NetworkConfig.CLIENT_CERT_FILE);

byte[] tlsClientKeyAsBytes = (byte[]) properties.get("tlsClientKeyBytes");
byte[] tlsClientKeyAsBytes = (byte[]) properties.get(NetworkConfig.CLIENT_KEY_BYTES);
if (tlsClientKeyFile != null && tlsClientKeyAsBytes != null) {
logger.warn("SSL CA client key is specified as bytes and as a file path. Using client key specified as bytes.");
}
if (tlsClientKeyFile != null && tlsClientKeyAsBytes == null) {
tlsClientKeyAsBytes = Files.readAllBytes(Paths.get(tlsClientKeyFile));
}
byte[] tlsClientCertAsBytes = (byte[]) properties.get("tlsClientCertBytes");
byte[] tlsClientCertAsBytes = (byte[]) properties.get(NetworkConfig.CLIENT_CERT_BYTES);
if (tlsClientCertFile != null && tlsClientCertAsBytes != null) {
logger.warn("SSL CA client cert is specified as bytes and as a file path. Using client cert specified as bytes.");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
{
"name": "global-trade-network",
"x-type": "hlfv1",
"description": "The network to be in if you want to stay in the global trade business",
"version": "1.0.0",
"client": {
"organization": "Org1",
"credentialStore": {
"path": "/tmp/hfc-kvs",
"cryptoStore": {
"path": "/tmp/hfc-cvs"
},
"wallet": "wallet-name"
}
},
"channels": {
"mychannel": {
"orderers": [
"orderer.example.com"
],
"peers": {
"peer0.org1.example.com": {
"endorsingPeer": true,
"chaincodeQuery": true,
"ledgerQuery": true,
"eventSource": true

},
"peer1.org1.example.com": {
"endorsingPeer": true,
"chaincodeQuery": true,
"ledgerQuery": true,
"eventSource": true
}
},
"chaincodes": [
"example02:v1",
"marbles:1.0"
]
}
},
"organizations": {
"Org1": {
"mspid": "Org1MSP",
"peers": [
"peer0.org1.example.com",
"peer1.org1.example.com"
],
"certificateAuthorities": [
"ca-org1"
],
"adminPrivateKey": {
"pem": "-----BEGIN PRIVATE KEY-----\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQghnA7rdgbZi/wndusiXjyf0KgE6OKZjQ+5INjwelRAC6hRANCAASb3u+hY+U/FZvhYDN6d08HJ1v56UJUyz/n2NHyJgTg6kC05AaJMeGIinEF0JeJtRDNVQGzoQJQYjnzUTS9FvGh\n-----END PRIVATE KEY-----"
},
"signedCert": {
"path": "src/test/fixture/sdkintegration/e2e-2Orgs/v1.3/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/msp/signcerts/[email protected]"
}
}
},
"orderers": {
"orderer.example.com": {
"url": "grpcs://localhost:7050",
"grpcOptions": {
"ssl-target-name-override": "orderer.example.com",
"grpc-max-send-message-length": 15
},
"tlsCACerts": {
"pem": "-----BEGIN CERTIFICATE----- <etc>"
}
}
},
"peers": {
"peer0.org1.example.com": {
"url": "grpcs://localhost:7051",
"grpcOptions": {
"ssl-target-name-override": "peer0.org1.example.com",
"grpc.http2.keepalive_time": 15
},
"tlsCACerts": {
"path": "src/test/fixture/sdkintegration/e2e-2Orgs/v1.3/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt",
"client": {
"certfile": "./tls/sign.pem",
"keyfile": "./tls/key.pem"
}
}
},
"peer1.org1.example.com": {
"url": "grpcs://localhost:7051",
"grpcOptions": {
"ssl-target-name-override": "peer1.org1.example.com",
"grpc.http2.keepalive_time": 15
},
"tlsCACerts": {
"path": "src/test/fixture/sdkintegration/e2e-2Orgs/v1.3/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/server.crt",
"client": {
"certPem": "-----BEGIN CERTIFICATE----- <etc>",
"keyPem": "-----BEGIN PRIVATE KEY----- <etc>"
}
}
}
},"certificateAuthorities": {
"ca-org1": {
"url": "https://localhost:7054",
"httpOptions": {
"verify": true
},
"tlsCACerts": {
"path": "peerOrganizations/org1.example.com/ca/org1.example.com-cert.pem",
"pem": "-----BEGIN CERTIFICATE----- <etc>"
},
"registrar": [
{
"enrollId": "admin",
"enrollSecret": "adminpw"
}
],
"caName": "caNameHere"
}
}
}
5 changes: 5 additions & 0 deletions src/test/fixture/testPems/client.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEILaiKBtmV7pPCel9NBp74A6jJWHc/Vobug5AyMkncB3ToAoGCCqGSM49
AwEHoUQDQgAEJT+fZ/nl8t38QY6VmddSvjB9HMITio6JUFZhDJ3qoAqCVAfKi6EI
sH+zLZuZA/324j3iHRYkNFUqkNA9wU91qw==
-----END EC PRIVATE KEY-----
Loading

0 comments on commit 7fac5e4

Please sign in to comment.