From 3f06fd9e39b643873d9d10d6d996a2d760de5d2d Mon Sep 17 00:00:00 2001 From: Taku Shimosawa Date: Tue, 16 Jun 2020 06:46:44 -0700 Subject: [PATCH] [FABCN-412] TLS support for chaincode server (#164) This patch adds TLS support for chaincode server. To enable TLS, set tlsProps in the second argument for shim.server, or add --chaincode-tls-cert-file and --chaincode-tls.key-file for CLI. Client certificate validation can be enabled via tlsProps.clientCACerts for shim.server or --chaincode-tls-client-cacert-file for CLI. Also the -path options (for base64 encoded files) are supported. Signed-off-by: Taku Shimosawa --- libraries/fabric-shim/lib/chaincode.js | 20 ++- .../fabric-shim/lib/cmds/serverCommand.js | 50 +++++++ libraries/fabric-shim/lib/server.js | 31 ++++- libraries/fabric-shim/test/unit/chaincode.js | 4 +- .../test/unit/cmds/serverCommand.js | 124 ++++++++++++++++++ libraries/fabric-shim/test/unit/handler.js | 4 +- libraries/fabric-shim/test/unit/server.js | 110 +++++++++++++--- .../fabric-shim/test/unit/test-ca.base64 | 11 ++ .../fabric-shim/test/unit/test-cert.base64 | 1 + libraries/fabric-shim/test/unit/test-cert.pem | 12 +- .../fabric-shim/test/unit/test-key.base64 | 1 + libraries/fabric-shim/test/unit/test-key.pem | 8 +- 12 files changed, 340 insertions(+), 36 deletions(-) create mode 100644 libraries/fabric-shim/test/unit/test-ca.base64 create mode 100644 libraries/fabric-shim/test/unit/test-cert.base64 create mode 100644 libraries/fabric-shim/test/unit/test-key.base64 diff --git a/libraries/fabric-shim/lib/chaincode.js b/libraries/fabric-shim/lib/chaincode.js index 9aaaa001..2ae51b67 100644 --- a/libraries/fabric-shim/lib/chaincode.js +++ b/libraries/fabric-shim/lib/chaincode.js @@ -196,21 +196,27 @@ class Shim { return Logger.getLogger(name); } + /** + * @interface ChaincodeServerTLSProperties + * @property {Buffer} key Private key for TLS + * @property {Buffer} cert Certificate for TLS + * @property {Buffer} [clientCACerts] CA certificate for client certificates if mutual TLS is used. + */ + /** + * @interface ChaincodeServerOpts + * @property {string} ccid Chaincode ID + * @property {string} address Listen address for the server + * @property {ChaincodeServerTLSProperties} [tlsProps] TLS properties if TLS is required. + */ /** * Returns a new Chaincode server. Should be called when the chaincode is launched in a server mode. * @static * @param {ChaincodeInterface} chaincode User-provided object that must implement ChaincodeInterface - * @param {ChaincodeSeverOpts} serverOpts Chaincode server options + * @param {ChaincodeServerOpts} serverOpts Chaincode server options */ static server(chaincode, serverOpts) { return new ChaincodeServer(chaincode, serverOpts); } - /** - * @typedef {Object} ChaincodeServerOpts - * @property {string} ccid Chaincode ID - * @property {string} address Listen address for the server - * @property {Object} tlsProps TLS properties. To be implemented. Should be null if TLS is not used. - */ } // special OID used by Fabric to save attributes in X.509 certificates diff --git a/libraries/fabric-shim/lib/cmds/serverCommand.js b/libraries/fabric-shim/lib/cmds/serverCommand.js index 93024ba4..d23b72db 100644 --- a/libraries/fabric-shim/lib/cmds/serverCommand.js +++ b/libraries/fabric-shim/lib/cmds/serverCommand.js @@ -6,6 +6,8 @@ 'use strict'; +const fs = require('fs'); + exports.command = 'server [options]'; exports.desc = 'Start the chaincode as a server'; @@ -19,6 +21,12 @@ const validOptions = { 'grpc.http2.max_pings_without_data': {type: 'number', default: 0}, 'grpc.keepalive_permit_without_calls': {type: 'number', default: 1}, 'chaincode-id': {type: 'string', required: true}, + 'chaincode-tls-cert-file': {type: 'string', conflicts: 'chaincode-tls-cert-path'}, + 'chaincode-tls-cert-path': {type: 'string', conflicts: 'chaincode-tls-cert-file'}, + 'chaincode-tls-key-file': {type: 'string', conflicts: 'chaincode-tls-key-path'}, + 'chaincode-tls-key-path': {type: 'string', conflicts: 'chaincode-tls-key-file'}, + 'chaincode-tls-client-cacert-file': {type: 'string', conflicts: 'chaincode-tls-client-cacert-path'}, + 'chaincode-tls-client-cacert-path': {type: 'string', conflicts: 'chaincode-tls-client-cacert-file'}, 'module-path': {type: 'string', default: process.cwd()} }; @@ -29,6 +37,20 @@ exports.builder = function (yargs) { yargs.usage('fabric-chaincode-node server --chaincode-address 0.0.0.0:9999 --chaincode-id mycc_v0:abcdef12345678...'); + yargs.check((argv) => { + if (argv['chaincode-tls-key-file'] || argv['chaincode-tls-key-path'] || + argv['chaincode-tls-cert-file'] || argv['chaincode-tls-cert-path']) { + // TLS should be enabled + if (!argv['chaincode-tls-key-file'] && !argv['chaincode-tls-key-path']) { + throw new Error('A TLS option is set but no key is specified'); + } + if (!argv['chaincode-tls-cert-file'] && !argv['chaincode-tls-cert-path']) { + throw new Error('A TLS option is set but no cert is specified'); + } + } + return true; + }); + return yargs; }; @@ -45,6 +67,34 @@ exports.getArgs = function (yargs) { argv[name] = yargs.argv[name]; } + // Load the cryptographic files if TLS is enabled + if (argv['chaincode-tls-key-file'] || argv['chaincode-tls-key-path'] || + argv['chaincode-tls-cert-file'] || argv['chaincode-tls-cert-path']) { + + const tlsProps = {}; + + if (argv['chaincode-tls-key-file']) { + tlsProps.key = fs.readFileSync(argv['chaincode-tls-key-file']); + } else { + tlsProps.key = Buffer.from(fs.readFileSync(argv['chaincode-tls-key-path']).toString(), 'base64'); + } + + if (argv['chaincode-tls-cert-file']) { + tlsProps.cert = fs.readFileSync(argv['chaincode-tls-cert-file']); + } else { + tlsProps.cert = Buffer.from(fs.readFileSync(argv['chaincode-tls-cert-path']).toString(), 'base64'); + } + + // If cacert option is specified, enable client certificate validation + if (argv['chaincode-tls-client-cacert-file']) { + tlsProps.clientCACerts = fs.readFileSync(argv['chaincode-tls-client-cacert-file']); + } else if (argv['chaincode-tls-client-cacert-path']) { + tlsProps.clientCACerts = Buffer.from(fs.readFileSync(argv['chaincode-tls-client-cacert-path']).toString(), 'base64'); + } + + argv.tlsProps = tlsProps; + } + // Translate the options to server options argv.ccid = argv['chaincode-id']; argv.address = argv['chaincode-address']; diff --git a/libraries/fabric-shim/lib/server.js b/libraries/fabric-shim/lib/server.js index 58d63d78..005c5a47 100644 --- a/libraries/fabric-shim/lib/server.js +++ b/libraries/fabric-shim/lib/server.js @@ -47,10 +47,34 @@ class ChaincodeServer { throw new Error('The "chaincode" argument must implement Init() and Invoke() methods'); } if (typeof serverOpts.ccid !== 'string') { - throw new Error('Missing required property in severOpts: ccid'); + throw new Error('Missing required property in serverOpts: ccid'); } if (typeof serverOpts.address !== 'string') { - throw new Error('Missing required property in severOpts: address'); + throw new Error('Missing required property in serverOpts: address'); + } + if (typeof serverOpts.tlsProps === 'object' && serverOpts.tlsProps !== null) { + if (typeof serverOpts.tlsProps.key !== 'object' || serverOpts.tlsProps.key === null) { + throw new Error('Missing required property in serverOpts.tlsProps: key'); + } + if (typeof serverOpts.tlsProps.cert !== 'object' || serverOpts.tlsProps.cert === null) { + throw new Error('Missing required property in serverOpts.tlsProps: cert'); + } + + let clientCACerts; + if (typeof serverOpts.tlsProps.clientCACerts === 'object' && serverOpts.tlsProps.clientCACerts !== null) { + clientCACerts = serverOpts.tlsProps.clientCACerts; + } else { + clientCACerts = null; + } + + this._credentials = grpc.ServerCredentials.createSsl(clientCACerts, [ + { + private_key: serverOpts.tlsProps.key, + cert_chain: serverOpts.tlsProps.cert + } + ], clientCACerts === null ? false : true); + } else { + this._credentials = grpc.ServerCredentials.createInsecure(); } // Create GRPC Server and register RPC handler @@ -71,8 +95,7 @@ class ChaincodeServer { return new Promise((resolve, reject) => { logger.debug('ChaincodeServer trying to bind to ' + this._serverOpts.address); - // TODO: TLS Support - this._server.bindAsync(this._serverOpts.address, grpc.ServerCredentials.createInsecure(), (error, port) => { + this._server.bindAsync(this._serverOpts.address, this._credentials, (error, port) => { if (!error) { logger.debug('ChaincodeServer successfully bound to ' + port); diff --git a/libraries/fabric-shim/test/unit/chaincode.js b/libraries/fabric-shim/test/unit/chaincode.js index 89d488a2..2e7170b1 100644 --- a/libraries/fabric-shim/test/unit/chaincode.js +++ b/libraries/fabric-shim/test/unit/chaincode.js @@ -21,8 +21,8 @@ const chaincodePath = '../../lib/chaincode.js'; const StartCommand = require('../../lib/cmds/startCommand.js'); const caPath = path.join(__dirname, 'test-ca.pem'); -const certPath = path.join(__dirname, 'test-cert.pem'); -const keyPath = path.join(__dirname, 'test-key.pem'); +const certPath = path.join(__dirname, 'test-cert.base64'); +const keyPath = path.join(__dirname, 'test-key.base64'); const ca = fs.readFileSync(caPath, 'utf8'); const key = fs.readFileSync(keyPath, 'utf8'); diff --git a/libraries/fabric-shim/test/unit/cmds/serverCommand.js b/libraries/fabric-shim/test/unit/cmds/serverCommand.js index e0320b5e..14426b2f 100644 --- a/libraries/fabric-shim/test/unit/cmds/serverCommand.js +++ b/libraries/fabric-shim/test/unit/cmds/serverCommand.js @@ -10,6 +10,8 @@ const sinon = require('sinon'); const chai = require('chai'); const expect = chai.expect; +const fs = require('fs'); +const path = require('path'); const yargs = require('yargs'); const Bootstrap = require('../../../lib/contract-spi/bootstrap'); @@ -30,6 +32,7 @@ describe('server cmd', () => { it('should configure the builder function', () => { sandbox.stub(yargs, 'options'); sandbox.stub(yargs, 'usage'); + sandbox.stub(yargs, 'check'); chaincodeServerCommand.builder(yargs); @@ -49,6 +52,7 @@ describe('server cmd', () => { expect(args['module-path'].default).to.deep.equal(process.cwd()); expect(yargs.usage.calledOnce).to.be.true; + expect(yargs.check.calledOnce).to.be.true; }); }); @@ -64,6 +68,16 @@ describe('server cmd', () => { }); describe('.getArgs', () => { + const certFileEncoded = path.join(__dirname, '..', 'test-cert.base64'); + const keyFileEncoded = path.join(__dirname, '..', 'test-key.base64'); + const caFileEncoded = path.join(__dirname, '..', 'test-ca.base64'); + const certFile = path.join(__dirname, '..', 'test-cert.pem'); + const keyFile = path.join(__dirname, '..', 'test-key.pem'); + const caFile = path.join(__dirname, '..', 'test-ca.pem'); + const cert = Buffer.from(fs.readFileSync(certFileEncoded).toString(), 'base64'); + const key = Buffer.from(fs.readFileSync(keyFileEncoded).toString(), 'base64'); + const ca = Buffer.from(fs.readFileSync(caFileEncoded).toString(), 'base64'); + it('should return the arguments properly', () => { const argv = { 'chaincode-address': '0.0.0.0:9999', @@ -83,5 +97,115 @@ describe('server cmd', () => { expect(ret['chaincode-id']).to.be.undefined; expect(ret['extra-options']).to.be.undefined; }); + + it('should return the TLS arguments properly', () => { + const argv = { + 'chaincode-address': '0.0.0.0:9999', + 'chaincode-id': 'test_id:1', + 'module-path': '/tmp/example', + 'chaincode-tls-cert-path': certFileEncoded, + 'chaincode-tls-key-path': keyFileEncoded + }; + + const ret = chaincodeServerCommand.getArgs({argv}); + + expect(ret.address).to.equal('0.0.0.0:9999'); + expect(ret.ccid).to.equal('test_id:1'); + + expect(ret.tlsProps).to.deep.equal({ + cert, + key + }); + }); + + it('should return the mutual TLS arguments properly', () => { + const argv = { + 'chaincode-address': '0.0.0.0:9999', + 'chaincode-id': 'test_id:1', + 'module-path': '/tmp/example', + 'chaincode-tls-cert-path': certFileEncoded, + 'chaincode-tls-key-path': keyFileEncoded, + 'chaincode-tls-client-cacert-path': caFileEncoded + }; + + const ret = chaincodeServerCommand.getArgs({argv}); + + expect(ret.address).to.equal('0.0.0.0:9999'); + expect(ret.ccid).to.equal('test_id:1'); + + expect(ret.tlsProps).to.deep.equal({ + cert, + key, + clientCACerts: ca + }); + }); + + it('should return the TLS arguments with PEM files properly', () => { + const argv = { + 'chaincode-address': '0.0.0.0:9999', + 'chaincode-id': 'test_id:1', + 'module-path': '/tmp/example', + 'chaincode-tls-cert-file': certFile, + 'chaincode-tls-key-file': keyFile, + 'chaincode-tls-client-cacert-file': caFile + }; + + const ret = chaincodeServerCommand.getArgs({argv}); + + expect(ret.address).to.equal('0.0.0.0:9999'); + expect(ret.ccid).to.equal('test_id:1'); + + expect(ret.tlsProps).to.deep.equal({ + cert, + key, + clientCACerts: ca + }); + }); + }); + + describe('parse arguments', () => { + it('should parse the arguments successfully', () => { + expect(() => { + chaincodeServerCommand.builder(yargs) + .exitProcess(false) + .parse('--chaincode-id test_id:1 --chaincode-address 0.0.0.0:9999'); + }).not.to.throw(); + }); + + it('should parse the arguments successfully with TLS options', () => { + expect(() => { + chaincodeServerCommand.builder(yargs) + .exitProcess(false) + .parse('--chaincode-id test_id:1 --chaincode-address 0.0.0.0:9999 ' + + '--chaincode-tls-key-file tls.key --chaincode-tls-cert-file tls.pem'); + }).not.to.throw(); + }); + + it('should throw when conflicting arguments are passed', () => { + expect(() => { + chaincodeServerCommand.builder(yargs) + .exitProcess(false) + .parse('--chaincode-id test_id:1 --chaincode-address 0.0.0.0:9999 ' + + '--chaincode-tls-key-file tls.key --chaincode-tls-key-path tls.pem'); + }).to.throw(); + }); + + it('should throw when only TLS key is passed', () => { + expect(() => { + chaincodeServerCommand.builder(yargs) + .exitProcess(false) + .parse('--chaincode-id test_id:1 --chaincode-address 0.0.0.0:9999 ' + + '--chaincode-tls-key-file tls.key'); + }).to.throw(); + }); + + it('should throw when only TLS cert is passed', () => { + expect(() => { + chaincodeServerCommand.builder(yargs) + .exitProcess(false) + .parse('--chaincode-id test_id:1 --chaincode-address 0.0.0.0:9999 ' + + '--chaincode-tls-cert-file tls.pem'); + }).to.throw(); + }); }); }); diff --git a/libraries/fabric-shim/test/unit/handler.js b/libraries/fabric-shim/test/unit/handler.js index 30e19d41..5bcd5042 100644 --- a/libraries/fabric-shim/test/unit/handler.js +++ b/libraries/fabric-shim/test/unit/handler.js @@ -33,8 +33,8 @@ const mockChaincodeImpl = { }; const ca = fs.readFileSync(path.join(__dirname, 'test-ca.pem'), 'utf8'); -const key = fs.readFileSync(path.join(__dirname, 'test-key.pem'), 'utf8'); -const cert = fs.readFileSync(path.join(__dirname, 'test-cert.pem'), 'utf8'); +const key = fs.readFileSync(path.join(__dirname, 'test-key.base64'), 'utf8'); +const cert = fs.readFileSync(path.join(__dirname, 'test-cert.base64'), 'utf8'); const mockOpts = { pem: ca, diff --git a/libraries/fabric-shim/test/unit/server.js b/libraries/fabric-shim/test/unit/server.js index 667f0503..04c3520a 100644 --- a/libraries/fabric-shim/test/unit/server.js +++ b/libraries/fabric-shim/test/unit/server.js @@ -10,7 +10,10 @@ const sinon = require('sinon'); const chai = require('chai'); chai.use(require('chai-as-promised')); const expect = chai.expect; +const fs = require('fs'); +const path = require('path'); const rewire = require('rewire'); + const fabprotos = require('../../bundle'); const grpc = require('@grpc/grpc-js'); @@ -20,21 +23,53 @@ let ChaincodeServer = rewire(serverPath); const mockChaincode = {Init: () => {}, Invoke: () => {}}; describe('ChaincodeServer', () => { - const mockGrpcServerInstance = { - addService: sinon.stub() - }; + const tlsKey = Buffer.from(fs.readFileSync(path.join(__dirname, 'test-key.pem')).toString(), 'base64'); + const tlsCert = Buffer.from(fs.readFileSync(path.join(__dirname, 'test-cert.pem')).toString(), 'base64'); + const tlsClientCA = fs.readFileSync(path.join(__dirname, 'test-ca.pem')); + let grpcServerStub; const serverOpts = { + ccid: 'example-chaincode-id', + address: '0.0.0.0:9999' + }; + const serverTLSOpts = { + ccid: 'example-chaincode-id', + address: '0.0.0.0:9999', + tlsProps: { + // test-cert.pem and test-key.pem are base64-encoded and need to decode to make Buffer + key: tlsKey, + cert: tlsCert + } + }; + const serverMutualTLSOpts = { ccid: 'example-chaincode-id', address: '0.0.0.0:9999', - serverOpts: {} + tlsProps: { + key: tlsKey, + cert: tlsCert, + clientCACerts: tlsClientCA + } }; + const mockCredentials = {type: 'insecure'}; + const mockTLSCredentials = {type: 'secure'}; + let insecureCredentialsStub; + let sslCredentialsStub; + + let mockGrpcServerInstance; beforeEach(() => { + mockGrpcServerInstance = { + addService: sinon.stub() + }; + grpcServerStub = sinon.stub(grpc, 'Server').returns(mockGrpcServerInstance); + insecureCredentialsStub = sinon.stub(grpc.ServerCredentials, 'createInsecure').returns(mockCredentials); + sslCredentialsStub = sinon.stub(grpc.ServerCredentials, 'createSsl').returns(mockTLSCredentials); }); afterEach(() => { grpcServerStub.restore(); + insecureCredentialsStub.restore(); + sslCredentialsStub.restore(); }); describe('constructor', () => { @@ -46,6 +81,45 @@ describe('ChaincodeServer', () => { expect(server._server.addService.calledOnce).to.be.ok; expect(server._chaincode).to.deep.equal(mockChaincode); expect(server._serverOpts).to.deep.equal(serverOpts); + expect(server._credentials).to.deep.equal(mockCredentials); + + expect(insecureCredentialsStub.calledOnce).to.be.ok; + }); + it('should create a gRPC server instance with TLS credentials and call addService in the constructor', () => { + const server = new ChaincodeServer(mockChaincode, serverTLSOpts); + + expect(grpcServerStub.calledOnce).to.be.ok; + expect(server._server).to.deep.equal(mockGrpcServerInstance); + expect(server._server.addService.calledOnce).to.be.ok; + expect(server._chaincode).to.deep.equal(mockChaincode); + expect(server._serverOpts).to.deep.equal(serverTLSOpts); + expect(server._credentials).to.deep.equal(mockTLSCredentials); + + expect(sslCredentialsStub.calledOnce).to.be.ok; + expect(sslCredentialsStub.firstCall.args[0]).to.be.null; + expect(sslCredentialsStub.firstCall.args[1]).to.deep.equal([{ + private_key: tlsKey, + cert_chain: tlsCert + }]); + expect(sslCredentialsStub.firstCall.args[2]).to.be.false; + }); + it('should create a gRPC server instance with mutual TLS credentials and call addService in the constructor', () => { + const server = new ChaincodeServer(mockChaincode, serverMutualTLSOpts); + + expect(grpcServerStub.calledOnce).to.be.ok; + expect(server._server).to.deep.equal(mockGrpcServerInstance); + expect(server._server.addService.calledOnce).to.be.ok; + expect(server._chaincode).to.deep.equal(mockChaincode); + expect(server._serverOpts).to.deep.equal(serverMutualTLSOpts); + expect(server._credentials).to.deep.equal(mockTLSCredentials); + + expect(sslCredentialsStub.calledOnce).to.be.ok; + expect(sslCredentialsStub.firstCall.args[0]).to.deep.equal(tlsClientCA); + expect(sslCredentialsStub.firstCall.args[1]).to.deep.equal([{ + private_key: tlsKey, + cert_chain: tlsCert, + }]); + expect(sslCredentialsStub.firstCall.args[2]).to.be.true; }); it('should throw an error when chaincode is missing', () => { @@ -63,29 +137,27 @@ describe('ChaincodeServer', () => { expect(() => new ChaincodeServer(mockChaincode)).to.throw('Missing required argument: serverOpts'); }); it('should throw an error when serverOpts.ccid is missing', () => { - expect(() => new ChaincodeServer(mockChaincode, {})).to.throw('Missing required property in severOpts: ccid'); + expect(() => new ChaincodeServer(mockChaincode, {})).to.throw('Missing required property in serverOpts: ccid'); }); it('should throw an error when serverOpts.address is missing', () => { - expect(() => new ChaincodeServer(mockChaincode, {ccid: 'some id'})).to.throw('Missing required property in severOpts: address'); + expect(() => new ChaincodeServer(mockChaincode, {ccid: 'some id'})).to.throw('Missing required property in serverOpts: address'); }); - }); - - describe('start()', () => { - const mockCredential = {}; - let insecureCredentialStub; - - beforeEach(() => { - insecureCredentialStub = sinon.stub(grpc.ServerCredentials, 'createInsecure').returns(mockCredential); + it('should throw an error when serverOpts.tlsProps.key is missing', () => { + expect(() => new ChaincodeServer(mockChaincode, {ccid: 'some id', address: '0.0.0.0:9999', tlsProps: {}})). + to.throw('Missing required property in serverOpts.tlsProps: key'); }); - afterEach(() => { - insecureCredentialStub.restore(); + it('should throw an error when serverOpts.tlsProps.cert is missing', () => { + expect(() => new ChaincodeServer(mockChaincode, {ccid: 'some id', address: '0.0.0.0:9999', tlsProps: {key: Buffer.from('a')}})). + to.throw('Missing required property in serverOpts.tlsProps: cert'); }); + }); + describe('start()', () => { it('should call bindAsync and start', async () => { const server = new ChaincodeServer(mockChaincode, serverOpts); server._server = { - bindAsync: sinon.stub().callsFake((address, credential, callback) => { + bindAsync: sinon.stub().callsFake((address, credentials, callback) => { callback(null, 9999); }), start: sinon.stub() @@ -94,7 +166,7 @@ describe('ChaincodeServer', () => { expect(await server.start()).not.to.throw; expect(server._server.bindAsync.calledOnce).to.be.ok; expect(server._server.bindAsync.firstCall.args[0]).to.equal(serverOpts.address); - expect(server._server.bindAsync.firstCall.args[1]).to.equal(mockCredential); + expect(server._server.bindAsync.firstCall.args[1]).to.equal(mockCredentials); expect(server._server.start.calledOnce).to.be.ok; }); @@ -102,7 +174,7 @@ describe('ChaincodeServer', () => { const server = new ChaincodeServer(mockChaincode, serverOpts); server._server = { - bindAsync: sinon.stub().callsFake((address, credential, callback) => { + bindAsync: sinon.stub().callsFake((address, credentials, callback) => { callback('failed to bind', 9999); }), start: sinon.stub() diff --git a/libraries/fabric-shim/test/unit/test-ca.base64 b/libraries/fabric-shim/test/unit/test-ca.base64 new file mode 100644 index 00000000..fc88d63f --- /dev/null +++ b/libraries/fabric-shim/test/unit/test-ca.base64 @@ -0,0 +1,11 @@ +LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrekNCOVFJSkFKMFo4akZpUFBpOU1Bb0dD +Q3FHU000OUJBTUNNQTR4RERBS0JnTlZCQU1NQTNSc2N6QWUKRncweU1EQTFNRGN4TmpNME1qRmFG +dzB6TURBMU1EVXhOak0wTWpGYU1BNHhEREFLQmdOVkJBTU1BM1JzY3pDQgptekFRQmdjcWhrak9Q +UUlCQmdVcmdRUUFJd09CaGdBRUFDb1VTM3pnOVFqNUNnUWVOQ1krOXNQTTJZV1lIVVVRClNCRS9v +WXBncldWOEU4VHF0V2tXY2h3WFA0T29aQXE3Yk1KMmJOUUU1U3E2SVkrYlpyWXBPS2pmQVNweVM0 +cVIKNHhKZkN1bjdCSVpBallIdlZxbWN1RjhhSmFmaDhGOTNHQmprSUxIZ0hUcnRMTHNBcTZzQnB6 +RXVWSmxzdWYxaApMaEtuQ0FxdmZFdEMxSUJWTUFvR0NDcUdTTTQ5QkFNQ0E0R01BRENCaUFKQ0FO +R1VwNDU5UDNhTWh0VFpkWEZxCm1jOFFWTTdySFIzWmxpOWttV3NHVmRKdmJVYnVIY1g2KzBBVTFT +OFIyRGhQQThvZUJ1UVQ3ZGJvdllmd2V1VmIKUWZSM0FrSUFwYUtlc2lOOUxOeTlhclNCR1hURktK +cXVCVDYzdjRiaTRmeUNOaGhkQzN3eEtldHNKMURDcElkcgpCbDhabmNKeFVNakNyZDdCTmxrQk5Q +N2pDR2RLcFBrPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0t diff --git a/libraries/fabric-shim/test/unit/test-cert.base64 b/libraries/fabric-shim/test/unit/test-cert.base64 new file mode 100644 index 00000000..0181cedc --- /dev/null +++ b/libraries/fabric-shim/test/unit/test-cert.base64 @@ -0,0 +1 @@ +LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrakNCOVFJSkFPZTRqL3NqV3ltRE1Bb0dDQ3FHU000OUJBTUNNQTR4RERBS0JnTlZCQU1NQTNSc2N6QWUKRncweU1EQTFNRGN4TmpNek5UUmFGdzB6TURBMU1EVXhOak16TlRSYU1BNHhEREFLQmdOVkJBTU1BM1JzY3pDQgptekFRQmdjcWhrak9QUUlCQmdVcmdRUUFJd09CaGdBRUFPcllIem5BZmVXZ3pVM3dVZ1Q1Ylk5NkUvT2ZMb3p4CitlUUFIL2Y5cDV3TUxuUzliMTJZczBHWitTNEdjSEYva1FBNlpoMVZBcFdKYnJ6MjFYVWhSbU5QQVRibDd3K2cKbytyazJ2cVZ5Y0E3dU1tUERlL0J2MVlldEh1WXZCd05vajVLVm9vVnVpUnJPOUlkU2N3ZUxkai9WOXoyQUkvQgpmUC9iN01aYWFwbUdUQjVFTUFvR0NDcUdTTTQ5QkFNQ0E0R0xBRENCaHdKQmVZQ1ZPclFWR3dmb1Q3OWRqRWpqCm1YVkVIL3hWcGk4b1ZhWkxVRm0yN2RldkYwb1ViZHowZSt2MzhZdkx6aERnWWh2MUtMQzhnYWxxaFdleTI2MmkKVVcwQ1FnRWRrUHFOYUZlbjF0WEQ5RWJoTjhSdVRyQWE3RGphNzZ3SWVMZUZSdFloZ0hCZlMvZmM0VWR3N1hWbgpQcG9nQ0xhM0ZMNkNDSUZIQWEyTU9kc3VMeld4V2c9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0t \ No newline at end of file diff --git a/libraries/fabric-shim/test/unit/test-cert.pem b/libraries/fabric-shim/test/unit/test-cert.pem index 0181cedc..11719b04 100644 --- a/libraries/fabric-shim/test/unit/test-cert.pem +++ b/libraries/fabric-shim/test/unit/test-cert.pem @@ -1 +1,11 @@ -LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrakNCOVFJSkFPZTRqL3NqV3ltRE1Bb0dDQ3FHU000OUJBTUNNQTR4RERBS0JnTlZCQU1NQTNSc2N6QWUKRncweU1EQTFNRGN4TmpNek5UUmFGdzB6TURBMU1EVXhOak16TlRSYU1BNHhEREFLQmdOVkJBTU1BM1JzY3pDQgptekFRQmdjcWhrak9QUUlCQmdVcmdRUUFJd09CaGdBRUFPcllIem5BZmVXZ3pVM3dVZ1Q1Ylk5NkUvT2ZMb3p4CitlUUFIL2Y5cDV3TUxuUzliMTJZczBHWitTNEdjSEYva1FBNlpoMVZBcFdKYnJ6MjFYVWhSbU5QQVRibDd3K2cKbytyazJ2cVZ5Y0E3dU1tUERlL0J2MVlldEh1WXZCd05vajVLVm9vVnVpUnJPOUlkU2N3ZUxkai9WOXoyQUkvQgpmUC9iN01aYWFwbUdUQjVFTUFvR0NDcUdTTTQ5QkFNQ0E0R0xBRENCaHdKQmVZQ1ZPclFWR3dmb1Q3OWRqRWpqCm1YVkVIL3hWcGk4b1ZhWkxVRm0yN2RldkYwb1ViZHowZSt2MzhZdkx6aERnWWh2MUtMQzhnYWxxaFdleTI2MmkKVVcwQ1FnRWRrUHFOYUZlbjF0WEQ5RWJoTjhSdVRyQWE3RGphNzZ3SWVMZUZSdFloZ0hCZlMvZmM0VWR3N1hWbgpQcG9nQ0xhM0ZMNkNDSUZIQWEyTU9kc3VMeld4V2c9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0t \ No newline at end of file +-----BEGIN CERTIFICATE----- +MIIBkjCB9QIJAOe4j/sjWymDMAoGCCqGSM49BAMCMA4xDDAKBgNVBAMMA3RsczAe +Fw0yMDA1MDcxNjMzNTRaFw0zMDA1MDUxNjMzNTRaMA4xDDAKBgNVBAMMA3RsczCB +mzAQBgcqhkjOPQIBBgUrgQQAIwOBhgAEAOrYHznAfeWgzU3wUgT5bY96E/OfLozx ++eQAH/f9p5wMLnS9b12Ys0GZ+S4GcHF/kQA6Zh1VApWJbrz21XUhRmNPATbl7w+g +o+rk2vqVycA7uMmPDe/Bv1YetHuYvBwNoj5KVooVuiRrO9IdScweLdj/V9z2AI/B +fP/b7MZaapmGTB5EMAoGCCqGSM49BAMCA4GLADCBhwJBeYCVOrQVGwfoT79djEjj +mXVEH/xVpi8oVaZLUFm27devF0oUbdz0e+v38YvLzhDgYhv1KLC8galqhWey262i +UW0CQgEdkPqNaFen1tXD9EbhN8RuTrAa7Dja76wIeLeFRtYhgHBfS/fc4Udw7XVn +PpogCLa3FL6CCIFHAa2MOdsuLzWxWg== +-----END CERTIFICATE----- \ No newline at end of file diff --git a/libraries/fabric-shim/test/unit/test-key.base64 b/libraries/fabric-shim/test/unit/test-key.base64 new file mode 100644 index 00000000..d9368608 --- /dev/null +++ b/libraries/fabric-shim/test/unit/test-key.base64 @@ -0,0 +1 @@ +LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1JSGNBZ0VCQkVJQmZXcmJQam9pdHcwd3AwUjA3dHdKeDhxaDZGenhpVFArekpFNEZHZ3EvTXh6Sy9kdUhIN2YKRjNzOWtmM1dkcWxYNlkwTnM2K3VRR2hmK2laODZtd01zaU9nQndZRks0RUVBQ09oZ1lrRGdZWUFCQURxMkI4NQp3SDNsb00xTjhGSUUrVzJQZWhQem55Nk04Zm5rQUIvMy9hZWNEQzUwdlc5ZG1MTkJtZmt1Qm5CeGY1RUFPbVlkClZRS1ZpVzY4OXRWMUlVWmpUd0UyNWU4UG9LUHE1TnI2bGNuQU83akpqdzN2d2I5V0hyUjdtTHdjRGFJK1NsYUsKRmJva2F6dlNIVW5NSGkzWS8xZmM5Z0NQd1h6LzIrekdXbXFaaGt3ZVJBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQ== \ No newline at end of file diff --git a/libraries/fabric-shim/test/unit/test-key.pem b/libraries/fabric-shim/test/unit/test-key.pem index d9368608..f42cbdc2 100644 --- a/libraries/fabric-shim/test/unit/test-key.pem +++ b/libraries/fabric-shim/test/unit/test-key.pem @@ -1 +1,7 @@ -LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1JSGNBZ0VCQkVJQmZXcmJQam9pdHcwd3AwUjA3dHdKeDhxaDZGenhpVFArekpFNEZHZ3EvTXh6Sy9kdUhIN2YKRjNzOWtmM1dkcWxYNlkwTnM2K3VRR2hmK2laODZtd01zaU9nQndZRks0RUVBQ09oZ1lrRGdZWUFCQURxMkI4NQp3SDNsb00xTjhGSUUrVzJQZWhQem55Nk04Zm5rQUIvMy9hZWNEQzUwdlc5ZG1MTkJtZmt1Qm5CeGY1RUFPbVlkClZRS1ZpVzY4OXRWMUlVWmpUd0UyNWU4UG9LUHE1TnI2bGNuQU83akpqdzN2d2I5V0hyUjdtTHdjRGFJK1NsYUsKRmJva2F6dlNIVW5NSGkzWS8xZmM5Z0NQd1h6LzIrekdXbXFaaGt3ZVJBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQ== \ No newline at end of file +-----BEGIN EC PRIVATE KEY----- +MIHcAgEBBEIBfWrbPjoitw0wp0R07twJx8qh6FzxiTP+zJE4FGgq/MxzK/duHH7f +F3s9kf3WdqlX6Y0Ns6+uQGhf+iZ86mwMsiOgBwYFK4EEACOhgYkDgYYABADq2B85 +wH3loM1N8FIE+W2PehPzny6M8fnkAB/3/aecDC50vW9dmLNBmfkuBnBxf5EAOmYd +VQKViW689tV1IUZjTwE25e8PoKPq5Nr6lcnAO7jJjw3vwb9WHrR7mLwcDaI+SlaK +FbokazvSHUnMHi3Y/1fc9gCPwXz/2+zGWmqZhkweRA== +-----END EC PRIVATE KEY----- \ No newline at end of file