From da1cb1bc3c3751b5d10f98a457ae0ec62b6bdebf Mon Sep 17 00:00:00 2001 From: Peter Somogyvari Date: Thu, 29 Apr 2021 14:16:31 -0700 Subject: [PATCH] feat(connector-fabric): enrollAdmin() and createCaClient() These are methods that come in handy while working with Fabric networks. Signed-off-by: Peter Somogyvari --- .../plugin-ledger-connector-fabric.ts | 60 ++++++++++++++++++- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/plugin-ledger-connector-fabric.ts b/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/plugin-ledger-connector-fabric.ts index 39bfd6f324..1a1dcc9b4b 100644 --- a/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/plugin-ledger-connector-fabric.ts +++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/plugin-ledger-connector-fabric.ts @@ -17,6 +17,7 @@ import { DefaultEventHandlerStrategies, Gateway, GatewayOptions, + Identity, InMemoryWallet, X509WalletMixin, } from "fabric-network"; @@ -83,6 +84,7 @@ import { IDeployContractEndpointV1Options, } from "./deploy-contract/deploy-contract-endpoint-v1"; import { sourceLangToRuntimeLang } from "./peer/source-lang-to-runtime-lang"; +import FabricCAServices from "fabric-ca-client"; /** * Constant value holding the default $GOPATH in the Fabric CLI container as @@ -170,8 +172,8 @@ export class PluginLedgerConnectorFabric this.prometheusExporter.startMetricsCollection(); } - public shutdown(): Promise { - throw new Error("Method not implemented."); + public async shutdown(): Promise { + return; } public getPrometheusExporter(): PrometheusExporter { @@ -895,4 +897,58 @@ export class PluginLedgerConnectorFabric throw new Error(`${fnTag} Unable to run transaction: ${ex.message}`); } } + + /** + * @param caId The key of the CA in the Fabric connection profile's + * `certificateAuthorities` attribute. + * @returns The instantiated `FabricCAServices` object. + */ + public async createCaClient(caId: string): Promise { + const fnTag = `${this.className}#createCaClient()`; + try { + const ccp = this.opts.connectionProfile; + if (!ccp.certificateAuthorities) { + throw new Error(`${fnTag} conn. profile certificateAuthorities falsy.`); + } + const caInfo = ccp.certificateAuthorities[caId] as Record; + const { tlsCACerts, url: caUrl, caName } = caInfo; + const { pem: caTLSCACertPem } = tlsCACerts; + const tlsOptions = { trustedRoots: caTLSCACertPem, verify: false }; + this.log.debug(`createCaClient() caName=%o caUrl=%o`, caName, caUrl); + this.log.debug(`createCaClient() tlsOptions=%o`, tlsOptions); + return new FabricCAServices(caUrl, tlsOptions, caName); + } catch (ex) { + this.log.error(`createCaClient() Failure:`, ex); + throw new Error(`${fnTag} Inner Exception: ${ex?.message}`); + } + } + + public async enrollAdmin( + caId: string, + identityId: string, + mspId: string, + enrollmentID: string, + enrollmentSecret: string, + ): Promise<[Identity, InMemoryWallet]> { + const fnTag = `${this.className}#enrollAdmin()`; + try { + const ca = await this.createCaClient(caId); + const wallet = new InMemoryWallet(new X509WalletMixin()); + + // Enroll the admin user, and import the new identity into the wallet. + const request = { enrollmentID, enrollmentSecret }; + const enrollment = await ca.enroll(request); + + const { certificate: cert, key } = enrollment; + const keyBytes = key.toBytes(); + + const identity = X509WalletMixin.createIdentity(mspId, cert, keyBytes); + await wallet.import(identityId, identity); + + return [identity, wallet]; + } catch (ex) { + this.log.error(`enrollAdmin() Failure:`, ex); + throw new Error(`${fnTag} Exception: ${ex?.message}`); + } + } }