@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/.jsii +4508 -0
- package/LICENSE +15 -0
- package/README.md +150 -0
- package/examples/python/hyperledger.py +90 -0
- package/examples/typescript/hyperledger.ts +106 -0
- package/lambdas/fabric/.eslintrc.js +17 -0
- package/lambdas/fabric/enroll-admin.js +33 -0
- package/lambdas/fabric/package.json +14 -0
- package/lambdas/fabric/register-user.js +62 -0
- package/lambdas/fabric/utilities.js +54 -0
- package/lib/client.d.ts +31 -0
- package/lib/client.js +40 -0
- package/lib/identity.d.ts +25 -0
- package/lib/identity.js +107 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.js +22 -0
- package/lib/network.d.ts +183 -0
- package/lib/network.js +225 -0
- package/lib/node.d.ts +88 -0
- package/lib/node.js +161 -0
- package/lib/user.d.ts +40 -0
- package/lib/user.js +56 -0
- package/lib/utilities.d.ts +12 -0
- package/lib/utilities.js +116 -0
- package/package.json +154 -0
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
|
+

|
|
4
|
+

|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+

|
|
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
|
+
};
|
package/lib/client.d.ts
ADDED
|
@@ -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
|
+
}
|