@cdklabs/cdk-hyperledger-fabric-network 0.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ the Software, and to permit persons to whom the Software is furnished to do so.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
10
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
11
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
12
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
13
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
14
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
15
+
package/README.md ADDED
@@ -0,0 +1,150 @@
1
+ # Hyperledger Fabric on Amazon Managed Blockchain
2
+
3
+ ![license](https://img.shields.io/github/license/cdklabs/cdk-hyperledger-fabric-network?color=green)
4
+ ![release](https://img.shields.io/github/v/release/cdklabs/cdk-hyperledger-fabric-network?color=green)
5
+ ![npm:version](https://img.shields.io/npm/v/@cdklabs/cdk-hyperledger-fabric-network?color=blue)
6
+ ![PyPi:version](https://img.shields.io/pypi/v/cdklabs.cdk-hypderledger-fabric-network?color=blue)
7
+ ![Maven:version](https://img.shields.io/maven-central/v/io.github.cdklabs/cdk-hypderledger-fabric-network?color=blue)
8
+ ![NuGet:version](https://img.shields.io/nuget/v/Cdklabs.CdkHyperledgerFabricNetwork?color=blue)
9
+
10
+ This repository contains a CDK construct to deploy a Hyperledger Fabric network
11
+ running on Amazon Managed Blockchain. It builds out a member and its nodes, a VPC
12
+ and associated endpoint to access them, and a set of users enrolled on the network.
13
+
14
+ The following functionality is planned for future releases:
15
+
16
+ * Create channels on nodes
17
+ * Instantiate chaincode on nodes
18
+
19
+
20
+ ## Installation
21
+
22
+ Note that this construct requires [AWS CDK v2](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html#getting_started_install).
23
+
24
+ #### JavaScript
25
+
26
+ ```bash
27
+ npm install --save @cdklabs/cdk-hyperledger-fabric-network
28
+ ```
29
+
30
+ #### Python
31
+
32
+ ```bash
33
+ pip3 install cdklabs.cdk-hyperledger-fabric-network
34
+ ```
35
+
36
+ #### Java
37
+
38
+ Add the following to `pom.xml`:
39
+
40
+ ```xml
41
+ <dependency>
42
+ <groupId>io.github.cdklabs</groupId>
43
+ <artifactId>cdk-hypderledger-fabric-network</artifactId>
44
+ </dependency>
45
+ ```
46
+
47
+ #### .NET
48
+
49
+ ```bash
50
+ dotnet add package Cdklabs.CdkHyperledgerFabricNetwork
51
+ ```
52
+
53
+
54
+ ## Usage
55
+
56
+ A minimally complete deployment is shown below. By default, a standard network
57
+ will be created running Hyperledger Fabric 1.4 with a single `bc.t3.small` node.
58
+
59
+ ```typescript
60
+ import { Stack, StackProps } from 'aws-cdk-lib';
61
+ import { Construct } from 'constructs';
62
+ import { HyperledgerFabricNetwork } from '@cdklabs/cdk-hyperledger-fabric-network';
63
+
64
+ class MyStack extends Stack {
65
+ constructor(scope: Construct, id: string, props?: StackProps) {
66
+ super(scope, id, props);
67
+ new HyperledgerFabricNetwork(this, 'Example', {
68
+ networkName: 'MyNetwork',
69
+ memberName: 'MyMember',
70
+ });
71
+ }
72
+ }
73
+ ```
74
+
75
+ The equivalent Python code is as follows:
76
+
77
+ ```python
78
+ from aws_cdk import Stack
79
+ from cdklabs.cdk_hyperledger_fabric_network import HyperledgerFabricNetwork
80
+
81
+ class MyStack(Stack):
82
+ def __init__(self, scope, id, **kwargs):
83
+ super().__init__(scope, id, **kwargs)
84
+ HyperledgerFabricNetwork(
85
+ self, 'Example',
86
+ network_name='MyNetwork',
87
+ member_name='MyMember',
88
+ )
89
+ ```
90
+
91
+ The following is a more complex instantiation illustrating some of the options available.
92
+
93
+ ```typescript
94
+ new HyperledgerFabricNetwork(this, 'Example', {
95
+ networkName: 'MyNetwork',
96
+ networkDescription: 'This is my Hyperledger Fabric network',
97
+ memberName: 'MyMember',
98
+ networkDescription: 'This is my Hyperledger Fabric member',
99
+ frameworkVersion: hyperledger.FrameworkVersion.VERSION_1_2,
100
+ proposalDurationInHours: 48,
101
+ thresholdPercentage: 75,
102
+ nodes: [
103
+ {
104
+ availabilityZone: 'us-east-1a',
105
+ instanceType: hyperledger.InstanceType.STANDARD5_LARGE,
106
+ },
107
+ {
108
+ availabilityZone: 'us-east-1b',
109
+ instanceType: hyperledger.InstanceType.STANDARD5_LARGE,
110
+ },
111
+ ],
112
+ users: [
113
+ { userId: 'AppUser1', affilitation: 'MyMember' },
114
+ { userId: 'AppUser2', affilitation: 'MyMember.department1' },
115
+ ],
116
+ });
117
+ ```
118
+
119
+ See the [API Documentation](API.md) for details on all available input and output parameters.
120
+
121
+
122
+ ## References
123
+
124
+ * [AWS CDK](https://docs.aws.amazon.com/cdk/v2/guide/home.html)
125
+ * [Amazon Managed Blockchain](https://aws.amazon.com/managed-blockchain/)
126
+ * [Hyperledger Fabric](https://hyperledger-fabric.readthedocs.io/)
127
+ * [Node Fabric SDK](https://hyperledger.github.io/fabric-sdk-node/release-1.4/index.html)
128
+ * [Fabric Chaincode Node](https://hyperledger.github.io/fabric-chaincode-node/)
129
+
130
+
131
+ ## Contributing
132
+
133
+ Pull requests are welcomed. Please review the [Contributing Guidelines](CONTRIBUTING.md)
134
+ and the [Code of Conduct](CODE_OF_CONDUCT.md).
135
+
136
+
137
+ ## Security
138
+
139
+ See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information.
140
+
141
+
142
+ ## Authors
143
+
144
+ * Jud Neer (judneer@amazon.com)
145
+ * Vignesh Rajasingh (vrajasin@amazon.com)
146
+
147
+
148
+ ## License
149
+
150
+ This project is licensed under the MIT-0 License. See the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,90 @@
1
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ # SPDX-License-Identifier: MIT-0
3
+
4
+
5
+ import os
6
+
7
+ import aws_cdk as cdk
8
+
9
+ import cdk_hyperledger_fabric_network as hyperledger
10
+
11
+
12
+ class HyperledgerTestStack(cdk.Stack):
13
+
14
+ def __init__(self, scope, id, **kwargs):
15
+ super().__init__(scope, id, **kwargs)
16
+ network = hyperledger.HyperledgerFabricNetwork(
17
+ self, 'MyNetwork',
18
+ network_name='IntegrationTestNetwork',
19
+ member_name='IntegrationTestMember',
20
+ nodes=[
21
+ {'availability_zone': 'us-east-1a', 'instance_type': hyperledger.InstanceType.STANDARD5_LARGE},
22
+ {'availability_zone': 'us-east-1b', 'instance_yype': hyperledger.InstanceType.STANDARD5_LARGE},
23
+ ],
24
+ )
25
+ cdk.CfnOutput(
26
+ self, 'NetworkId',
27
+ description='Managed Blockchain network identifier',
28
+ value=network.networkId,
29
+ )
30
+ cdk.CfnOutput(
31
+ self, 'MemberId',
32
+ description='Managed Blockchain member identifier',
33
+ value=network.memberId,
34
+ )
35
+ cdk.CfnOutput(
36
+ self, 'VpcEndpointServiceName',
37
+ description='Managed Blockchain network VPC endpoint service name',
38
+ value=network.vpcEndpointServiceName,
39
+ )
40
+ cdk.CfnOutput(
41
+ self, 'OrdererEndpoint',
42
+ description='Managed Blockchain network ordering service endpoint',
43
+ value=network.ordererEndpoint,
44
+ )
45
+ cdk.CfnOutput(
46
+ self, 'CaEndpoint',
47
+ description='Managed Blockchain member CA endpoint',
48
+ value=network.caEndpoint,
49
+ )
50
+ cdk.CfnOutput(
51
+ self, 'AdminPasswordArn',
52
+ description='Secret ARN for the Hyperledger Fabric admin password',
53
+ value=network.adminPasswordSecret.secretFullArn or network.adminPasswordSecret.secretArn,
54
+ )
55
+ cdk.CfnOutput(
56
+ self, 'AdminPrivateKeyArn',
57
+ description='Secret ARN for Hyperledger Fabric admin private key',
58
+ value=network.adminPrivateKeySecret.secretFullArn or network.adminPrivateKeySecret.secretArn,
59
+ )
60
+ cdk.CfnOutput(
61
+ self, 'AdminSignedCertArn',
62
+ description='Secret ARN for Hyperledger Fabric admin signed certificate',
63
+ value=network.adminSignedCertSecret.secretFullArn or network.adminSignedCertSecret.secretArn,
64
+ )
65
+ cdk.CfnOutput(
66
+ self, 'NodeIds',
67
+ description='Comma-separated list of Managed Blockchain node identifiers',
68
+ value=','.join(n.nodeId for n in network.nodes),
69
+ )
70
+ cdk.CfnOutput(
71
+ self, 'NodeEndpoints',
72
+ description='Comma-separated list of Managed Blockchain node endpoints',
73
+ value=','.join(n.endpoint for n in network.nodes),
74
+ )
75
+ cdk.CfnOutput(
76
+ self, 'NodeEventEndpoints',
77
+ description='Comma-separated list of Managed Blockchain node event endpoints',
78
+ value=','.join(n.eventEndpoint for n in network.nodes),
79
+ )
80
+
81
+
82
+ app = cdk.App()
83
+
84
+ HyperledgerTestStack(
85
+ app, 'HyperledgerTestStack',
86
+ env={
87
+ 'account': os.environ['CDK_DEFAULT_ACCOUNT'],
88
+ 'region': os.environ['CDK_DEFAULT_REGION'],
89
+ }
90
+ )
@@ -0,0 +1,106 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: MIT-0
3
+
4
+
5
+ import * as cdk from 'aws-cdk-lib';
6
+ import * as cdknag from 'cdk-nag';
7
+ import * as constructs from 'constructs';
8
+
9
+ import * as hyperledger from 'cdk-hyperledger-fabric-network';
10
+
11
+
12
+ class HyperledgerTestStack extends cdk.Stack {
13
+
14
+ constructor(scope: constructs.Construct, id: string, props?: cdk.StackProps) {
15
+
16
+ super(scope, id, props);
17
+
18
+ const network = new hyperledger.HyperledgerFabricNetwork(this, 'IntegrationTestNetwork', {
19
+ networkName: 'IntegrationTestNetwork',
20
+ memberName: 'IntegrationTestMember',
21
+ nodes: [
22
+ {
23
+ availabilityZone: 'us-east-1a',
24
+ instanceType: hyperledger.InstanceType.STANDARD5_LARGE,
25
+ },
26
+ {
27
+ availabilityZone: 'us-east-1b',
28
+ instanceType: hyperledger.InstanceType.STANDARD5_LARGE,
29
+ },
30
+ ],
31
+ });
32
+
33
+ new cdk.CfnOutput(this, 'NetworkId', {
34
+ description: 'Managed Blockchain network identifier',
35
+ value: network.networkId,
36
+ });
37
+
38
+ new cdk.CfnOutput(this, 'MemberId', {
39
+ description: 'Managed Blockchain member identifier',
40
+ value: network.memberId,
41
+ });
42
+
43
+ new cdk.CfnOutput(this, 'VpcEndpointServiceName', {
44
+ description: 'Managed Blockchain network VPC endpoint service name',
45
+ value: network.vpcEndpointServiceName,
46
+ });
47
+
48
+ new cdk.CfnOutput(this, 'OrdererEndpoint', {
49
+ description: 'Managed Blockchain network ordering service endpoint',
50
+ value: network.ordererEndpoint,
51
+ });
52
+
53
+ new cdk.CfnOutput(this, 'CaEndpoint', {
54
+ description: 'Managed Blockchain member CA endpoint',
55
+ value: network.caEndpoint,
56
+ });
57
+
58
+ new cdk.CfnOutput(this, 'AdminPasswordArn', {
59
+ description: 'Secret ARN for the Hyperledger Fabric admin password',
60
+ value: network.adminPasswordSecret.secretFullArn ?? network.adminPasswordSecret.secretArn,
61
+ });
62
+
63
+ new cdk.CfnOutput(this, 'AdminPrivateKeyArn', {
64
+ description: 'Secret ARN for Hyperledger Fabric admin private key',
65
+ value: network.adminPrivateKeySecret.secretFullArn ?? network.adminPrivateKeySecret.secretArn,
66
+ });
67
+
68
+ new cdk.CfnOutput(this, 'AdminSignedCertArn', {
69
+ description: 'Secret ARN for Hyperledger Fabric admin signed certificate',
70
+ value: network.adminSignedCertSecret.secretFullArn ?? network.adminSignedCertSecret.secretArn,
71
+ });
72
+
73
+ new cdk.CfnOutput(this, 'NodeIds', {
74
+ description: 'Comma-separated list of Managed Blockchain node identifiers',
75
+ value: network.nodes.map(n => n.nodeId).join(','),
76
+ });
77
+
78
+ new cdk.CfnOutput(this, 'NodeEndpoints', {
79
+ description: 'Comma-separated list of Managed Blockchain node endpoints',
80
+ value: network.nodes.map(n => n.endpoint).join(','),
81
+ });
82
+
83
+ new cdk.CfnOutput(this, 'NodeEventEndpoints', {
84
+ description: 'Comma-separated list of Managed Blockchain node event endpoints',
85
+ value: network.nodes.map(n => n.eventEndpoint).join(','),
86
+ });
87
+
88
+ }
89
+ }
90
+
91
+
92
+ const app = new cdk.App();
93
+
94
+ const stack = new HyperledgerTestStack(app, 'HyperledgerTestStack', {
95
+ env: {
96
+ account: process.env.CDK_DEFAULT_ACCOUNT,
97
+ region: process.env.CDK_DEFAULT_REGION,
98
+ },
99
+ });
100
+
101
+ cdk.Aspects.of(stack).add(new cdknag.AwsSolutionsChecks({ verbose: true }));
102
+
103
+ cdknag.NagSuppressions.addStackSuppressions(stack, [
104
+ { id: 'AwsSolutions-SMG4', reason: 'Secrets created for Managed Blockchain users do not support auto-rotation' },
105
+ { id: 'AwsSolutions-IAM4', reason: 'The CDK custom resource framework uses a managed policy for its Lambda' },
106
+ ]);
@@ -0,0 +1,17 @@
1
+ module.exports = {
2
+ "env": {
3
+ "browser": false,
4
+ "commonjs": false,
5
+ "es2021": true,
6
+ },
7
+ "extends": "airbnb",
8
+ "parserOptions": {
9
+ "ecmaVersion": 13,
10
+ },
11
+ "rules": {
12
+ "max-len": ["error", {
13
+ "code": 120,
14
+ }],
15
+ "no-console": "off",
16
+ },
17
+ };
@@ -0,0 +1,33 @@
1
+ const FabricCAClient = require('fabric-ca-client');
2
+ const utilities = require('./utilities');
3
+
4
+ // Extract environment variables
5
+ const adminPasswordArn = process.env.ADMIN_PASSWORD_ARN;
6
+ const caEndpoint = process.env.CA_ENDPOINT;
7
+ const privateKeyArn = process.env.PRIVATE_KEY_ARN;
8
+ const signedCertArn = process.env.SIGNED_CERT_ARN;
9
+ const tlsCertBucket = process.env.TLS_CERT_BUCKET;
10
+ const tlsCertKey = process.env.TLS_CERT_KEY;
11
+
12
+ const caUrl = `https://${caEndpoint}`;
13
+ const caName = utilities.getCaName(caEndpoint);
14
+
15
+ // Enroll the admin only on creation
16
+ exports.handler = async (event) => {
17
+ if (event.RequestType === 'Create') {
18
+ try {
19
+ // Get the TLS cert from S3
20
+ const caTlsCert = await utilities.getS3Object(tlsCertBucket, tlsCertKey);
21
+ // Get the admin credentials from Secrets Manager
22
+ const adminPwd = await utilities.getSecret(adminPasswordArn);
23
+ // Create a new client for interacting with the CA
24
+ const ca = new FabricCAClient(caUrl, { trustedRoots: caTlsCert, verify: false }, caName);
25
+ // Enroll the admin user, and import the new identity into Secrets Manager
26
+ const enrollment = await ca.enroll({ enrollmentID: 'admin', enrollmentSecret: adminPwd });
27
+ await utilities.putSecret(privateKeyArn, enrollment.key.toBytes());
28
+ await utilities.putSecret(signedCertArn, enrollment.certificate);
29
+ } catch (error) {
30
+ console.error(`Failed to enroll admin user: ${error}`);
31
+ }
32
+ }
33
+ };
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "fabric",
3
+ "version": "0.0.1",
4
+ "dependencies": {
5
+ "@aws-sdk/client-s3": "3.53.1",
6
+ "@aws-sdk/client-secrets-manager": "3.53.0",
7
+ "fabric-ca-client": "2.2.13",
8
+ "fabric-common": "2.2.13"
9
+ },
10
+ "devDependencies": {
11
+ "eslint": "^8.11.0",
12
+ "eslint-config-airbnb": "^19.0.4"
13
+ }
14
+ }
@@ -0,0 +1,62 @@
1
+ const FabricCAClient = require('fabric-ca-client');
2
+ const { User } = require('fabric-common');
3
+ const utilities = require('./utilities');
4
+
5
+ // Extract environment variables
6
+ const caEndpoint = process.env.CA_ENDPOINT;
7
+ const orgName = process.env.MEMBER_NAME;
8
+ const privateKeyArn = process.env.PRIVATE_KEY_ARN;
9
+ const signedCertArn = process.env.SIGNED_CERT_ARN;
10
+ const tlsCertBucket = process.env.TLS_CERT_BUCKET;
11
+ const tlsCertKey = process.env.TLS_CERT_KEY;
12
+
13
+ const adminId = 'admin';
14
+ const caUrl = `https://${caEndpoint}`;
15
+ const caName = utilities.getCaName(caEndpoint);
16
+ const mspId = `${orgName}Msp`;
17
+
18
+ // Register and enroll users only on Create
19
+ exports.handler = async (event) => {
20
+ const userData = event.ResourceProperties;
21
+ const { userId, affiliation } = userData;
22
+ if (event.RequestType === 'Create') {
23
+ try {
24
+ // Get the TLS cert from S3
25
+ const caTlsCert = await utilities.getS3Object(tlsCertBucket, tlsCertKey);
26
+ // Get the admin credentials from Secrets Manager
27
+ const adminPrivateKey = await utilities.getSecret(privateKeyArn);
28
+ const adminSignedCert = await utilities.getSecret(signedCertArn);
29
+ // Create a new client for interacting with the CA
30
+ const ca = new FabricCAClient(caUrl, { trustedRoots: caTlsCert, verify: false }, caName);
31
+ // Create a user object for the Admin; the password argument on createUser method
32
+ // is not used in creating the signed identity, so default it to an empty string
33
+ const adminUser = User.createUser(adminId, '', mspId, adminSignedCert, adminPrivateKey);
34
+ // Check if user is already registered; return if it already exists
35
+ const identityService = ca.newIdentityService();
36
+ const identityObject = await identityService.getAll(adminUser);
37
+ const userResult = identityObject.result;
38
+ if (userResult.identities && userResult.identities.find((e) => e.id === userId)) {
39
+ console.info(`${userId} already exist.`);
40
+ return;
41
+ }
42
+ // Admin user has the org(member) as the root affiliation by default; if another
43
+ // affiliation is requested, check for its existence and add if it does not exist
44
+ if (affiliation !== orgName) {
45
+ const affObject = ca.newAffiliationService();
46
+ const affRequest = await affObject.getAll(adminUser);
47
+ const affResult = affRequest.result;
48
+ if (!affResult.affiliations || !affResult.affiliations.find((e) => e.name === affiliation)) {
49
+ await affObject.create({ name: affiliation }, adminUser);
50
+ }
51
+ }
52
+ // Register and enroll the user as client, and import the new identity into Secrets Manager
53
+ const userSecret = await ca.register({ enrollmentID: userId, role: 'client', affiliation }, adminUser);
54
+ const userEnroll = await ca.enroll({ enrollmentID: userId, enrollmentSecret: userSecret });
55
+ await utilities.putSecret(userData.passwordArn, userSecret);
56
+ await utilities.putSecret(userData.privateKeyArn, userEnroll.key.toBytes());
57
+ await utilities.putSecret(userData.signedCertArn, userEnroll.certificate);
58
+ } catch (error) {
59
+ console.error(`Failed to enroll user ${userId}: ${error}`);
60
+ }
61
+ }
62
+ };
@@ -0,0 +1,54 @@
1
+ const {
2
+ GetObjectCommand,
3
+ S3Client,
4
+ } = require('@aws-sdk/client-s3');
5
+
6
+ const {
7
+ GetSecretValueCommand,
8
+ PutSecretValueCommand,
9
+ SecretsManagerClient,
10
+ } = require('@aws-sdk/client-secrets-manager');
11
+
12
+ const s3Client = new S3Client();
13
+ const smClient = new SecretsManagerClient();
14
+
15
+ // Convert a ReadableStream to a string
16
+ async function streamToString(stream) {
17
+ stream.setEncoding('utf8');
18
+ let data = '';
19
+ for await (const chunk of stream) { /* eslint-disable-line no-restricted-syntax */
20
+ data += chunk;
21
+ }
22
+ return data;
23
+ }
24
+
25
+ // Extract the name from a CA endpoint
26
+ function getCaName(caEndpoint) {
27
+ const caName = caEndpoint.split('.')[1].split('-');
28
+ caName[1] = caName[1].toUpperCase();
29
+ return caName.join('-');
30
+ }
31
+
32
+ // Retrieve an object from S3
33
+ async function getS3Object(bucketName, key) {
34
+ const objectData = await s3Client.send(new GetObjectCommand({ Bucket: bucketName, Key: key }));
35
+ return streamToString(objectData.Body);
36
+ }
37
+
38
+ // Retrieve a secret from Secrets Manager
39
+ async function getSecret(secretArn) {
40
+ const secretData = await smClient.send(new GetSecretValueCommand({ SecretId: secretArn }));
41
+ return secretData.SecretString;
42
+ }
43
+
44
+ // Store a secret in Secrets Manager
45
+ async function putSecret(secretArn, secret) {
46
+ return smClient.send(new PutSecretValueCommand({ SecretId: secretArn, SecretString: secret }));
47
+ }
48
+
49
+ module.exports = {
50
+ getCaName,
51
+ getS3Object,
52
+ getSecret,
53
+ putSecret,
54
+ };
@@ -0,0 +1,31 @@
1
+ import * as ec2 from 'aws-cdk-lib/aws-ec2';
2
+ import * as constructs from 'constructs';
3
+ import * as network from './network';
4
+ /**
5
+ * Construct properties for `HyperledgerFabricVpc`
6
+ */
7
+ export interface HyperledgerFabricClientProps {
8
+ /**
9
+ * Client VPC to create the endpoints. If not provided,
10
+ * VPC will be created with the default properties
11
+ * (CIDR-`10.0.0.0/16` and subnets of type `PRIVATE_ISOLATED`)
12
+ *
13
+ */
14
+ readonly vpc?: ec2.IVpc;
15
+ }
16
+ /**
17
+ * Creates a VPC and endpoint that allows Hyperledger Fabric client to
18
+ * interact with the Hyperledger Fabric endpoints that Amazon Managed Blockchain
19
+ * exposes for the member and network resources.
20
+ */
21
+ export declare class HyperledgerFabricClient extends constructs.Construct {
22
+ /**
23
+ * The client VPC that has endpoint to access the Amazon Managed Blockchain
24
+ */
25
+ readonly vpc: ec2.IVpc;
26
+ /**
27
+ * Managed Blockchain network VPC endpoint
28
+ */
29
+ readonly vpcEndpoint: ec2.InterfaceVpcEndpoint;
30
+ constructor(scope: network.HyperledgerFabricNetwork, id: string, props?: HyperledgerFabricClientProps);
31
+ }
package/lib/client.js ADDED
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var _a;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.HyperledgerFabricClient = void 0;
5
+ const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
6
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
7
+ // SPDX-License-Identifier: MIT-0
8
+ const cdk = require("aws-cdk-lib");
9
+ const ec2 = require("aws-cdk-lib/aws-ec2");
10
+ const constructs = require("constructs");
11
+ /**
12
+ * Creates a VPC and endpoint that allows Hyperledger Fabric client to
13
+ * interact with the Hyperledger Fabric endpoints that Amazon Managed Blockchain
14
+ * exposes for the member and network resources.
15
+ */
16
+ class HyperledgerFabricClient extends constructs.Construct {
17
+ constructor(scope, id, props) {
18
+ super(scope, id);
19
+ // Collect metadata on the stack
20
+ const region = cdk.Stack.of(this).region;
21
+ // Populate instance variables from input properties, using defaults if values not provided
22
+ if (typeof props === 'undefined')
23
+ props = {};
24
+ this.vpc = props.vpc ?? new ec2.Vpc(this, 'ClientVpc', { subnetConfiguration: [{ name: 'Private', subnetType: ec2.SubnetType.PRIVATE_ISOLATED }] });
25
+ const vpcEndpointServiceName = scope.vpcEndpointServiceName.replace(`com.amazonaws.${region}.`, '');
26
+ // Add VPC FlowLogs with the default setting of trafficType:ALL and destination:CloudWatchLogs
27
+ this.vpc.addFlowLog('FlowLog');
28
+ // Add a VPC endpoint to access the Managed Blockchain
29
+ const vpcService = new ec2.InterfaceVpcEndpointService(vpcEndpointServiceName);
30
+ this.vpcEndpoint = this.vpc.addInterfaceEndpoint('NetworkEndpoint', { service: vpcService, open: false, privateDnsEnabled: true });
31
+ // Add VPC endpoint to access Secrets Manager
32
+ this.vpc.addInterfaceEndpoint('SecretsManagerEndpoint', { service: ec2.InterfaceVpcEndpointAwsService.SECRETS_MANAGER });
33
+ // Add VPC endpoint to access S3
34
+ this.vpc.addGatewayEndpoint('S3Endpoint', { service: ec2.GatewayVpcEndpointAwsService.S3 });
35
+ }
36
+ }
37
+ exports.HyperledgerFabricClient = HyperledgerFabricClient;
38
+ _a = JSII_RTTI_SYMBOL_1;
39
+ HyperledgerFabricClient[_a] = { fqn: "@cdklabs/cdk-hyperledger-fabric-network.HyperledgerFabricClient", version: "0.0.20" };
40
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLHFFQUFxRTtBQUNyRSxpQ0FBaUM7QUFFakMsbUNBQW1DO0FBQ25DLDJDQUEyQztBQUMzQyx5Q0FBeUM7QUFrQnpDOzs7O0dBSUc7QUFDSCxNQUFhLHVCQUF3QixTQUFRLFVBQVUsQ0FBQyxTQUFTO0lBWS9ELFlBQVksS0FBdUMsRUFBRSxFQUFVLEVBQUUsS0FBb0M7UUFDbkcsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUVqQixnQ0FBZ0M7UUFDaEMsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDO1FBRXpDLDJGQUEyRjtRQUMzRixJQUFJLE9BQU8sS0FBSyxLQUFLLFdBQVc7WUFBRSxLQUFLLEdBQUcsRUFBRSxDQUFDO1FBQzdDLElBQUksQ0FBQyxHQUFHLEdBQUcsS0FBSyxDQUFDLEdBQUcsSUFBSSxJQUFJLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRSxFQUFFLG1CQUFtQixFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxHQUFHLENBQUMsVUFBVSxDQUFDLGdCQUFnQixFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDcEosTUFBTSxzQkFBc0IsR0FBRyxLQUFLLENBQUMsc0JBQXNCLENBQUMsT0FBTyxDQUFDLGlCQUFpQixNQUFNLEdBQUcsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUVwRyw4RkFBOEY7UUFDOUYsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLENBQUM7UUFFL0Isc0RBQXNEO1FBQ3RELE1BQU0sVUFBVSxHQUFHLElBQUksR0FBRyxDQUFDLDJCQUEyQixDQUFFLHNCQUFzQixDQUFFLENBQUM7UUFDakYsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLG9CQUFvQixDQUFDLGlCQUFpQixFQUFFLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLGlCQUFpQixFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFFbkksNkNBQTZDO1FBQzdDLElBQUksQ0FBQyxHQUFHLENBQUMsb0JBQW9CLENBQUMsd0JBQXdCLEVBQUUsRUFBRSxPQUFPLEVBQUUsR0FBRyxDQUFDLDhCQUE4QixDQUFDLGVBQWUsRUFBRSxDQUFDLENBQUM7UUFFekgsZ0NBQWdDO1FBQ2hDLElBQUksQ0FBQyxHQUFHLENBQUMsa0JBQWtCLENBQUMsWUFBWSxFQUFFLEVBQUUsT0FBTyxFQUFFLEdBQUcsQ0FBQyw0QkFBNEIsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBRTlGLENBQUM7O0FBcENILDBEQXNDQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCBBbWF6b24uY29tLCBJbmMuIG9yIGl0cyBhZmZpbGlhdGVzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVC0wXG5cbmltcG9ydCAqIGFzIGNkayBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgKiBhcyBlYzIgZnJvbSAnYXdzLWNkay1saWIvYXdzLWVjMic7XG5pbXBvcnQgKiBhcyBjb25zdHJ1Y3RzIGZyb20gJ2NvbnN0cnVjdHMnO1xuXG5pbXBvcnQgKiBhcyBuZXR3b3JrIGZyb20gJy4vbmV0d29yayc7XG5cbi8qKlxuICogQ29uc3RydWN0IHByb3BlcnRpZXMgZm9yIGBIeXBlcmxlZGdlckZhYnJpY1ZwY2BcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBIeXBlcmxlZGdlckZhYnJpY0NsaWVudFByb3BzIHtcbiAgLyoqXG4gICAqIENsaWVudCBWUEMgdG8gY3JlYXRlIHRoZSBlbmRwb2ludHMuIElmIG5vdCBwcm92aWRlZCxcbiAgICogVlBDIHdpbGwgYmUgY3JlYXRlZCB3aXRoIHRoZSBkZWZhdWx0IHByb3BlcnRpZXNcbiAgICogKENJRFItYDEwLjAuMC4wLzE2YCBhbmQgc3VibmV0cyBvZiB0eXBlIGBQUklWQVRFX0lTT0xBVEVEYClcbiAgICpcbiAgICovXG4gIHJlYWRvbmx5IHZwYz86IGVjMi5JVnBjO1xuXG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIFZQQyBhbmQgZW5kcG9pbnQgdGhhdCBhbGxvd3MgSHlwZXJsZWRnZXIgRmFicmljIGNsaWVudCB0b1xuICogaW50ZXJhY3Qgd2l0aCB0aGUgSHlwZXJsZWRnZXIgRmFicmljIGVuZHBvaW50cyB0aGF0IEFtYXpvbiBNYW5hZ2VkIEJsb2NrY2hhaW5cbiAqIGV4cG9zZXMgZm9yIHRoZSBtZW1iZXIgYW5kIG5ldHdvcmsgcmVzb3VyY2VzLlxuICovXG5leHBvcnQgY2xhc3MgSHlwZXJsZWRnZXJGYWJyaWNDbGllbnQgZXh0ZW5kcyBjb25zdHJ1Y3RzLkNvbnN0cnVjdCB7XG5cbiAgLyoqXG4gICAqIFRoZSBjbGllbnQgVlBDIHRoYXQgaGFzIGVuZHBvaW50IHRvIGFjY2VzcyB0aGUgQW1hem9uIE1hbmFnZWQgQmxvY2tjaGFpblxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHZwYzogZWMyLklWcGM7XG5cbiAgLyoqXG4gICAqIE1hbmFnZWQgQmxvY2tjaGFpbiBuZXR3b3JrIFZQQyBlbmRwb2ludFxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHZwY0VuZHBvaW50OiBlYzIuSW50ZXJmYWNlVnBjRW5kcG9pbnQ7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IG5ldHdvcmsuSHlwZXJsZWRnZXJGYWJyaWNOZXR3b3JrLCBpZDogc3RyaW5nLCBwcm9wcz86IEh5cGVybGVkZ2VyRmFicmljQ2xpZW50UHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgLy8gQ29sbGVjdCBtZXRhZGF0YSBvbiB0aGUgc3RhY2tcbiAgICBjb25zdCByZWdpb24gPSBjZGsuU3RhY2sub2YodGhpcykucmVnaW9uO1xuXG4gICAgLy8gUG9wdWxhdGUgaW5zdGFuY2UgdmFyaWFibGVzIGZyb20gaW5wdXQgcHJvcGVydGllcywgdXNpbmcgZGVmYXVsdHMgaWYgdmFsdWVzIG5vdCBwcm92aWRlZFxuICAgIGlmICh0eXBlb2YgcHJvcHMgPT09ICd1bmRlZmluZWQnKSBwcm9wcyA9IHt9O1xuICAgIHRoaXMudnBjID0gcHJvcHMudnBjID8/IG5ldyBlYzIuVnBjKHRoaXMsICdDbGllbnRWcGMnLCB7IHN1Ym5ldENvbmZpZ3VyYXRpb246IFt7IG5hbWU6ICdQcml2YXRlJywgc3VibmV0VHlwZTogZWMyLlN1Ym5ldFR5cGUuUFJJVkFURV9JU09MQVRFRCB9XSB9KTtcbiAgICBjb25zdCB2cGNFbmRwb2ludFNlcnZpY2VOYW1lID0gc2NvcGUudnBjRW5kcG9pbnRTZXJ2aWNlTmFtZS5yZXBsYWNlKGBjb20uYW1hem9uYXdzLiR7cmVnaW9ufS5gLCAnJyk7XG5cbiAgICAvLyBBZGQgVlBDIEZsb3dMb2dzIHdpdGggdGhlIGRlZmF1bHQgc2V0dGluZyBvZiB0cmFmZmljVHlwZTpBTEwgYW5kIGRlc3RpbmF0aW9uOkNsb3VkV2F0Y2hMb2dzXG4gICAgdGhpcy52cGMuYWRkRmxvd0xvZygnRmxvd0xvZycpO1xuXG4gICAgLy8gQWRkIGEgVlBDIGVuZHBvaW50IHRvIGFjY2VzcyB0aGUgTWFuYWdlZCBCbG9ja2NoYWluXG4gICAgY29uc3QgdnBjU2VydmljZSA9IG5ldyBlYzIuSW50ZXJmYWNlVnBjRW5kcG9pbnRTZXJ2aWNlKCB2cGNFbmRwb2ludFNlcnZpY2VOYW1lICk7XG4gICAgdGhpcy52cGNFbmRwb2ludCA9IHRoaXMudnBjLmFkZEludGVyZmFjZUVuZHBvaW50KCdOZXR3b3JrRW5kcG9pbnQnLCB7IHNlcnZpY2U6IHZwY1NlcnZpY2UsIG9wZW46IGZhbHNlLCBwcml2YXRlRG5zRW5hYmxlZDogdHJ1ZSB9KTtcblxuICAgIC8vIEFkZCBWUEMgZW5kcG9pbnQgdG8gYWNjZXNzIFNlY3JldHMgTWFuYWdlclxuICAgIHRoaXMudnBjLmFkZEludGVyZmFjZUVuZHBvaW50KCdTZWNyZXRzTWFuYWdlckVuZHBvaW50JywgeyBzZXJ2aWNlOiBlYzIuSW50ZXJmYWNlVnBjRW5kcG9pbnRBd3NTZXJ2aWNlLlNFQ1JFVFNfTUFOQUdFUiB9KTtcblxuICAgIC8vIEFkZCBWUEMgZW5kcG9pbnQgdG8gYWNjZXNzIFMzXG4gICAgdGhpcy52cGMuYWRkR2F0ZXdheUVuZHBvaW50KCdTM0VuZHBvaW50JywgeyBzZXJ2aWNlOiBlYzIuR2F0ZXdheVZwY0VuZHBvaW50QXdzU2VydmljZS5TMyB9KTtcblxuICB9XG5cbn1cbiJdfQ==
@@ -0,0 +1,25 @@
1
+ import * as iam from 'aws-cdk-lib/aws-iam';
2
+ import * as customresources from 'aws-cdk-lib/custom-resources';
3
+ import * as constructs from 'constructs';
4
+ import * as network from './network';
5
+ /**
6
+ * Creates custom resources to enroll admin and register user
7
+ * identities with the CA using the fabric-ca-client SDK.
8
+ * Admin identity is enrolled by default. User identities are
9
+ * registered and enrolled, if provided.
10
+ */
11
+ export declare class HyperledgerFabricIdentity extends constructs.Construct {
12
+ /**
13
+ * Role for custom resource lambda to assume
14
+ */
15
+ static customRole: iam.Role;
16
+ /**
17
+ * Custom provider to register user identity
18
+ */
19
+ static userProvider: customresources.Provider;
20
+ /**
21
+ * Custom provider to enroll admin identity
22
+ */
23
+ readonly adminProvider: customresources.Provider;
24
+ constructor(scope: network.HyperledgerFabricNetwork, id: string);
25
+ }