Skip to content

Commit 4d97069

Browse files
author
Mr. Angry
committed
Adding TLS changes to SDK
Merging in TLS related changes from previous work which were mistakenly left out of this branch. These changes were originally made and tested on the Fabric05 branch. Fixes FAB-374 Change-Id: If5b482d00297d840924dab78f35824a4245e1f02 Signed-off-by: Anna D Derbakova <[email protected]> Signed-off-by: Allen Bailey <[email protected]>
1 parent cc111e2 commit 4d97069

File tree

2 files changed

+94
-24
lines changed

2 files changed

+94
-24
lines changed

sdk/node/src/hfc.ts

+92-23
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,16 @@
4343
* the server side transaction processing path.
4444
*/
4545

46-
// Instruct boringssl to use ECC for tls.
47-
process.env['GRPC_SSL_CIPHER_SUITES'] = 'HIGH+ECDSA';
46+
process.env.GRPC_SSL_CIPHER_SUITES = process.env.GRPC_SSL_CIPHER_SUITES
47+
? process.env.GRPC_SSL_CIPHER_SUITES
48+
: 'ECDHE-RSA-AES128-GCM-SHA256:' +
49+
'ECDHE-RSA-AES128-SHA256:' +
50+
'ECDHE-RSA-AES256-SHA384:' +
51+
'ECDHE-RSA-AES256-GCM-SHA384:' +
52+
'ECDHE-ECDSA-AES128-GCM-SHA256:' +
53+
'ECDHE-ECDSA-AES128-SHA256:' +
54+
'ECDHE-ECDSA-AES256-SHA384:' +
55+
'ECDHE-ECDSA-AES256-GCM-SHA384' ;
4856

4957
var debugModule = require('debug');
5058
var fs = require('fs');
@@ -209,6 +217,12 @@ export interface Enrollment {
209217
chainKey:string;
210218
}
211219

220+
// GRPCOptions
221+
export interface GRPCOptions {
222+
pem: string;
223+
hostnameOverride: string;
224+
}
225+
212226
// A request to get a batch of TCerts
213227
export class GetTCertBatchRequest {
214228
constructor( public name: string,
@@ -346,6 +360,8 @@ export interface DeployRequest extends TransactionRequest {
346360
chaincodePath:string;
347361
// The name identifier for the chaincode to deploy in development mode.
348362
chaincodeName:string;
363+
// The directory on the server side, where the certificate.pem will be copied
364+
certificatePath:string;
349365
}
350366

351367
/**
@@ -461,10 +477,11 @@ export class Chain {
461477

462478
/**
463479
* Add a peer given an endpoint specification.
464-
* @param endpoint The endpoint of the form: { url: "grpcs://host:port", tls: { .... } }
480+
* @param url The URL of the peer.
481+
* @param opts Optional GRPC options.
465482
* @returns {Peer} Returns a new peer.
466483
*/
467-
addPeer(url:string, pem?:string):Peer {
484+
addPeer(url:string, opts?:GRPCOptions):Peer {
468485

469486
//check to see if the peer is already part of the chain
470487
this.peers.forEach(function(peer){
@@ -477,7 +494,7 @@ export class Chain {
477494
}
478495
})
479496

480-
let peer = new Peer(url, this, pem);
497+
let peer = new Peer(url, this, opts);
481498
this.peers.push(peer);
482499
return peer;
483500
};
@@ -508,9 +525,10 @@ export class Chain {
508525
/**
509526
* Set the member services URL
510527
* @param {string} url Member services URL of the form: "grpc://host:port" or "grpcs://host:port"
528+
* @param {GRPCOptions} opts optional GRPC options
511529
*/
512-
setMemberServicesUrl(url:string, pem?:string):void {
513-
this.setMemberServices(newMemberServices(url,pem));
530+
setMemberServicesUrl(url:string, opts?:GRPCOptions):void {
531+
this.setMemberServices(newMemberServices(url,opts));
514532
}
515533

516534
/**
@@ -552,6 +570,20 @@ export class Chain {
552570
this.preFetchMode = preFetchMode;
553571
}
554572

573+
/**
574+
* Enable or disable ECDSA mode for GRPC.
575+
*/
576+
setECDSAModeForGRPC(enabled:boolean):void {
577+
// TODO: Handle multiple chains in different modes appropriately; this will not currently work
578+
// since it is based env variables.
579+
if (enabled) {
580+
// Instruct boringssl to use ECC for tls.
581+
process.env.GRPC_SSL_CIPHER_SUITES = 'HIGH+ECDSA';
582+
} else {
583+
delete process.env.GRPC_SSL_CIPHER_SUITES;
584+
}
585+
}
586+
555587
/**
556588
* Determine if dev mode is enabled.
557589
*/
@@ -1677,6 +1709,16 @@ export class TransactionContext extends events.EventEmitter {
16771709
// Substitute the hashStrHash for the image name
16781710
dockerFileContents = util.format(dockerFileContents, hash);
16791711

1712+
// Add the certificate path on the server, if it is being passed in
1713+
debug("type of request.certificatePath: " + typeof(request.certificatePath));
1714+
debug("request.certificatePath: " + request.certificatePath);
1715+
if (request.certificatePath !== "" && request.certificatePath !== undefined) {
1716+
debug("Adding COPY certificate.pem command");
1717+
1718+
dockerFileContents = dockerFileContents + "\n" + "COPY certificate.pem %s";
1719+
dockerFileContents = util.format(dockerFileContents, request.certificatePath);
1720+
}
1721+
16801722
// Create a Docker file with dockerFileContents
16811723
let dockerFilePath = projDir + "/Dockerfile";
16821724
fs.writeFile(dockerFilePath, dockerFileContents, function(err) {
@@ -2077,16 +2119,19 @@ export class Peer {
20772119
* and returns the new Peer.
20782120
* @param {string} url The URL with format of "grpcs://host:port".
20792121
* @param {Chain} chain The chain of which this peer is a member.
2080-
* @param {string} pem The certificate file, in PEM format,
2081-
* to use with the gRPC protocol (that is, with TransportCredentials).
2082-
* Required when using the grpcs protocol.
2122+
* @param {GRPCOptions} optional GRPC options to use with the gRPC,
2123+
* protocol (that is, with TransportCredentials) including a root
2124+
* certificate file, in PEM format, and hostnameOverride. A certificate
2125+
* is required when using the grpcs (TLS) protocol.
20832126
* @returns {Peer} The new peer.
20842127
*/
2085-
constructor(url:string, chain:Chain, pem:string) {
2128+
constructor(url:string, chain:Chain, opts:GRPCOptions) {
20862129
this.url = url;
20872130
this.chain = chain;
2131+
let pem = getPemFromOpts(opts);
2132+
opts = getOptsFromOpts(opts);
20882133
this.ep = new Endpoint(url,pem);
2089-
this.peerClient = new _fabricProto.Peer(this.ep.addr, this.ep.creds);
2134+
this.peerClient = new _fabricProto.Peer(this.ep.addr, this.ep.creds, opts);
20902135
}
20912136

20922137
/**
@@ -2272,16 +2317,14 @@ class MemberServicesImpl implements MemberServices {
22722317
* @param config The config information required by this member services implementation.
22732318
* @returns {MemberServices} A MemberServices object.
22742319
*/
2275-
constructor(url:string,pem:string) {
2320+
constructor(url:string,opts:GRPCOptions) {
2321+
var pem = getPemFromOpts(opts);
2322+
opts = getOptsFromOpts(opts);
22762323
let ep = new Endpoint(url,pem);
2277-
var options = {
2278-
'grpc.ssl_target_name_override' : 'tlsca',
2279-
'grpc.default_authority': 'tlsca'
2280-
};
2281-
this.ecaaClient = new _caProto.ECAA(ep.addr, ep.creds, options);
2282-
this.ecapClient = new _caProto.ECAP(ep.addr, ep.creds, options);
2283-
this.tcapClient = new _caProto.TCAP(ep.addr, ep.creds, options);
2284-
this.tlscapClient = new _caProto.TLSCAP(ep.addr, ep.creds, options);
2324+
this.ecaaClient = new _caProto.ECAA(ep.addr, ep.creds, opts);
2325+
this.ecapClient = new _caProto.ECAP(ep.addr, ep.creds, opts);
2326+
this.tcapClient = new _caProto.TCAP(ep.addr, ep.creds, opts);
2327+
this.tlscapClient = new _caProto.TLSCAP(ep.addr, ep.creds, opts);
22852328
this.cryptoPrimitives = new crypto.Crypto(DEFAULT_HASH_ALGORITHM, DEFAULT_SECURITY_LEVEL);
22862329
}
22872330

@@ -2317,6 +2360,9 @@ class MemberServicesImpl implements MemberServices {
23172360
this.cryptoPrimitives.setHashAlgorithm(hashAlgorithm);
23182361
}
23192362

2363+
/**
2364+
* Get the crypto object.
2365+
*/
23202366
getCrypto():crypto.Crypto {
23212367
return this.cryptoPrimitives;
23222368
}
@@ -2599,8 +2645,8 @@ class MemberServicesImpl implements MemberServices {
25992645

26002646
} // end MemberServicesImpl
26012647

2602-
function newMemberServices(url,pem) {
2603-
return new MemberServicesImpl(url,pem);
2648+
function newMemberServices(url:string,opts:GRPCOptions) {
2649+
return new MemberServicesImpl(url,opts);
26042650
}
26052651

26062652
/**
@@ -2709,6 +2755,29 @@ function rolesToMask(roles?:string[]):number {
27092755
return mask;
27102756
}
27112757

2758+
// Get the PEM from the options
2759+
function getPemFromOpts(opts:any):string {
2760+
if (isObject(opts)) return opts.pem;
2761+
return opts;
2762+
}
2763+
2764+
// Normalize opts
2765+
function getOptsFromOpts(opts:any):GRPCOptions {
2766+
if (isObject(opts)) {
2767+
delete opts.pem;
2768+
if (opts.hostnameOverride) {
2769+
opts['grpc.ssl_target_name_override'] = opts.hostnameOverride;
2770+
opts['grpc.default_authority'] = opts.hostnameOverride;
2771+
delete opts.hostnameOverride;
2772+
}
2773+
return <GRPCOptions>opts;
2774+
}
2775+
if (isString(opts)) {
2776+
// backwards compatible to handle pem as opts
2777+
return <GRPCOptions>{ pem: opts };
2778+
}
2779+
}
2780+
27122781
function endsWith(str:string, suffix:string) {
27132782
return str.length >= suffix.length && str.substr(str.length - suffix.length) === suffix;
27142783
};

sdk/node/src/sdk_util.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,8 @@ export function GenerateTarGz(src, dest, cb) {
149149
".yaml",
150150
".json",
151151
".c",
152-
".h"
152+
".h",
153+
".pem"
153154
];
154155

155156
// Create the pack stream specifying the ignore/filtering function

0 commit comments

Comments
 (0)