Skip to content

Commit

Permalink
feat: Enroll admin/user and store creds on SecretsManager
Browse files Browse the repository at this point in the history
  • Loading branch information
vponselvan authored and lordjabez committed Apr 10, 2022
1 parent 8c4765d commit 484aa81
Show file tree
Hide file tree
Showing 15 changed files with 827 additions and 46 deletions.
192 changes: 176 additions & 16 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,21 +46,8 @@ new HyperledgerFabricClient(scope: HyperledgerFabricNetwork, id: string, props?:

| **Name** | **Type** | **Description** |
| --- | --- | --- |
| [`secretsManagerVpcEndpoint`](#cdkhyperledgerfabricnetworkhyperledgerfabricclientpropertysecretsmanagervpcendpoint)<span title="Required">*</span> | [`aws-cdk-lib.aws_ec2.VpcEndpoint`](#aws-cdk-lib.aws_ec2.VpcEndpoint) | VPC endpoint to access Secret Manager. |
| [`vpc`](#cdkhyperledgerfabricnetworkhyperledgerfabricclientpropertyvpc)<span title="Required">*</span> | [`aws-cdk-lib.aws_ec2.IVpc`](#aws-cdk-lib.aws_ec2.IVpc) | The client VPC that has endpoint to access the Amazon Managed Blockchain. |
| [`vpcEndpoint`](#cdkhyperledgerfabricnetworkhyperledgerfabricclientpropertyvpcendpoint)<span title="Required">*</span> | [`aws-cdk-lib.aws_ec2.VpcEndpoint`](#aws-cdk-lib.aws_ec2.VpcEndpoint) | Managed Blockchain network VPC endpoint. |

---

##### `secretsManagerVpcEndpoint`<sup>Required</sup> <a name="cdk-hyperledger-fabric-network.HyperledgerFabricClient.property.secretsManagerVpcEndpoint" id="cdkhyperledgerfabricnetworkhyperledgerfabricclientpropertysecretsmanagervpcendpoint"></a>

```typescript
public readonly secretsManagerVpcEndpoint: VpcEndpoint;
```

- *Type:* [`aws-cdk-lib.aws_ec2.VpcEndpoint`](#aws-cdk-lib.aws_ec2.VpcEndpoint)

VPC endpoint to access Secret Manager.
| [`vpcEndpoint`](#cdkhyperledgerfabricnetworkhyperledgerfabricclientpropertyvpcendpoint)<span title="Required">*</span> | [`aws-cdk-lib.aws_ec2.InterfaceVpcEndpoint`](#aws-cdk-lib.aws_ec2.InterfaceVpcEndpoint) | Managed Blockchain network VPC endpoint. |

---

Expand All @@ -79,10 +66,10 @@ The client VPC that has endpoint to access the Amazon Managed Blockchain.
##### `vpcEndpoint`<sup>Required</sup> <a name="cdk-hyperledger-fabric-network.HyperledgerFabricClient.property.vpcEndpoint" id="cdkhyperledgerfabricnetworkhyperledgerfabricclientpropertyvpcendpoint"></a>

```typescript
public readonly vpcEndpoint: VpcEndpoint;
public readonly vpcEndpoint: InterfaceVpcEndpoint;
```

- *Type:* [`aws-cdk-lib.aws_ec2.VpcEndpoint`](#aws-cdk-lib.aws_ec2.VpcEndpoint)
- *Type:* [`aws-cdk-lib.aws_ec2.InterfaceVpcEndpoint`](#aws-cdk-lib.aws_ec2.InterfaceVpcEndpoint)

Managed Blockchain network VPC endpoint.

Expand Down Expand Up @@ -152,6 +139,7 @@ new HyperledgerFabricNetwork(scope: Construct, id: string, props: HyperledgerFab
| [`proposalDurationInHours`](#cdkhyperledgerfabricnetworkhyperledgerfabricnetworkpropertyproposaldurationinhours)<span title="Required">*</span> | `number` | The duration from the time that a proposal is created until it expires. |
| [`thresholdComparator`](#cdkhyperledgerfabricnetworkhyperledgerfabricnetworkpropertythresholdcomparator)<span title="Required">*</span> | [`cdk-hyperledger-fabric-network.ThresholdComparator`](#cdk-hyperledger-fabric-network.ThresholdComparator) | Determines whether the yes votes must be greater than the threshold percentage or must be greater than or equal to the threhold percentage to be approved. |
| [`thresholdPercentage`](#cdkhyperledgerfabricnetworkhyperledgerfabricnetworkpropertythresholdpercentage)<span title="Required">*</span> | `number` | The percentage of votes among all members that must be yes for a proposal to be approved. |
| [`users`](#cdkhyperledgerfabricnetworkhyperledgerfabricnetworkpropertyusers)<span title="Required">*</span> | [`cdk-hyperledger-fabric-network.HyperledgerFabricUser`](#cdk-hyperledger-fabric-network.HyperledgerFabricUser)[] | List of users registered with CA. |
| [`vpcEndpointServiceName`](#cdkhyperledgerfabricnetworkhyperledgerfabricnetworkpropertyvpcendpointservicename)<span title="Required">*</span> | `string` | Managed Blockchain network VPC endpoint service name. |

---
Expand Down Expand Up @@ -384,6 +372,18 @@ The percentage of votes among all members that must be yes for a proposal to be

---

##### `users`<sup>Required</sup> <a name="cdk-hyperledger-fabric-network.HyperledgerFabricNetwork.property.users" id="cdkhyperledgerfabricnetworkhyperledgerfabricnetworkpropertyusers"></a>

```typescript
public readonly users: HyperledgerFabricUser[];
```

- *Type:* [`cdk-hyperledger-fabric-network.HyperledgerFabricUser`](#cdk-hyperledger-fabric-network.HyperledgerFabricUser)[]

List of users registered with CA.

---

##### `vpcEndpointServiceName`<sup>Required</sup> <a name="cdk-hyperledger-fabric-network.HyperledgerFabricNetwork.property.vpcEndpointServiceName" id="cdkhyperledgerfabricnetworkhyperledgerfabricnetworkpropertyvpcendpointservicename"></a>

```typescript
Expand Down Expand Up @@ -617,6 +617,106 @@ public readonly eventEndpoint: string;
---


### HyperledgerFabricUser <a name="cdk-hyperledger-fabric-network.HyperledgerFabricUser" id="cdkhyperledgerfabricnetworkhyperledgerfabricuser"></a>

Creates custom resources to register and enroll users identities with the CA using the fabric-ca-client SDK.

#### Initializers <a name="cdk-hyperledger-fabric-network.HyperledgerFabricUser.Initializer" id="cdkhyperledgerfabricnetworkhyperledgerfabricuserinitializer"></a>

```typescript
import { HyperledgerFabricUser } from 'cdk-hyperledger-fabric-network'

new HyperledgerFabricUser(scope: HyperledgerFabricNetwork, id: string, props: HyperledgerFabricUserProps)
```

| **Name** | **Type** | **Description** |
| --- | --- | --- |
| [`scope`](#cdkhyperledgerfabricnetworkhyperledgerfabricuserparameterscope)<span title="Required">*</span> | [`cdk-hyperledger-fabric-network.HyperledgerFabricNetwork`](#cdk-hyperledger-fabric-network.HyperledgerFabricNetwork) | *No description.* |
| [`id`](#cdkhyperledgerfabricnetworkhyperledgerfabricuserparameterid)<span title="Required">*</span> | `string` | *No description.* |
| [`props`](#cdkhyperledgerfabricnetworkhyperledgerfabricuserparameterprops)<span title="Required">*</span> | [`cdk-hyperledger-fabric-network.HyperledgerFabricUserProps`](#cdk-hyperledger-fabric-network.HyperledgerFabricUserProps) | *No description.* |

---

##### `scope`<sup>Required</sup> <a name="cdk-hyperledger-fabric-network.HyperledgerFabricUser.parameter.scope" id="cdkhyperledgerfabricnetworkhyperledgerfabricuserparameterscope"></a>

- *Type:* [`cdk-hyperledger-fabric-network.HyperledgerFabricNetwork`](#cdk-hyperledger-fabric-network.HyperledgerFabricNetwork)

---

##### `id`<sup>Required</sup> <a name="cdk-hyperledger-fabric-network.HyperledgerFabricUser.parameter.id" id="cdkhyperledgerfabricnetworkhyperledgerfabricuserparameterid"></a>

- *Type:* `string`

---

##### `props`<sup>Required</sup> <a name="cdk-hyperledger-fabric-network.HyperledgerFabricUser.parameter.props" id="cdkhyperledgerfabricnetworkhyperledgerfabricuserparameterprops"></a>

- *Type:* [`cdk-hyperledger-fabric-network.HyperledgerFabricUserProps`](#cdk-hyperledger-fabric-network.HyperledgerFabricUserProps)

---



#### Properties <a name="Properties" id="properties"></a>

| **Name** | **Type** | **Description** |
| --- | --- | --- |
| [`affiliation`](#cdkhyperledgerfabricnetworkhyperledgerfabricuserpropertyaffiliation)<span title="Required">*</span> | `string` | User's affiliation to the member. |
| [`userId`](#cdkhyperledgerfabricnetworkhyperledgerfabricuserpropertyuserid)<span title="Required">*</span> | `string` | User ID registered with CA. |
| [`userPrivateKeySecret`](#cdkhyperledgerfabricnetworkhyperledgerfabricuserpropertyuserprivatekeysecret)<span title="Required">*</span> | [`aws-cdk-lib.aws_secretsmanager.Secret`](#aws-cdk-lib.aws_secretsmanager.Secret) | Secret for user private key. |
| [`userSignedCertSecret`](#cdkhyperledgerfabricnetworkhyperledgerfabricuserpropertyusersignedcertsecret)<span title="Required">*</span> | [`aws-cdk-lib.aws_secretsmanager.Secret`](#aws-cdk-lib.aws_secretsmanager.Secret) | Secret for user signed certificate. |

---

##### `affiliation`<sup>Required</sup> <a name="cdk-hyperledger-fabric-network.HyperledgerFabricUser.property.affiliation" id="cdkhyperledgerfabricnetworkhyperledgerfabricuserpropertyaffiliation"></a>

```typescript
public readonly affiliation: string;
```

- *Type:* `string`

User's affiliation to the member.

---

##### `userId`<sup>Required</sup> <a name="cdk-hyperledger-fabric-network.HyperledgerFabricUser.property.userId" id="cdkhyperledgerfabricnetworkhyperledgerfabricuserpropertyuserid"></a>

```typescript
public readonly userId: string;
```

- *Type:* `string`

User ID registered with CA.

---

##### `userPrivateKeySecret`<sup>Required</sup> <a name="cdk-hyperledger-fabric-network.HyperledgerFabricUser.property.userPrivateKeySecret" id="cdkhyperledgerfabricnetworkhyperledgerfabricuserpropertyuserprivatekeysecret"></a>

```typescript
public readonly userPrivateKeySecret: Secret;
```

- *Type:* [`aws-cdk-lib.aws_secretsmanager.Secret`](#aws-cdk-lib.aws_secretsmanager.Secret)

Secret for user private key.

---

##### `userSignedCertSecret`<sup>Required</sup> <a name="cdk-hyperledger-fabric-network.HyperledgerFabricUser.property.userSignedCertSecret" id="cdkhyperledgerfabricnetworkhyperledgerfabricuserpropertyusersignedcertsecret"></a>

```typescript
public readonly userSignedCertSecret: Secret;
```

- *Type:* [`aws-cdk-lib.aws_secretsmanager.Secret`](#aws-cdk-lib.aws_secretsmanager.Secret)

Secret for user signed certificate.

---


## Structs <a name="Structs" id="structs"></a>

### HyperledgerFabricClientProps <a name="cdk-hyperledger-fabric-network.HyperledgerFabricClientProps" id="cdkhyperledgerfabricnetworkhyperledgerfabricclientprops"></a>
Expand Down Expand Up @@ -681,6 +781,7 @@ const hyperledgerFabricNetworkProps: HyperledgerFabricNetworkProps = { ... }
| [`proposalDurationInHours`](#cdkhyperledgerfabricnetworkhyperledgerfabricnetworkpropspropertyproposaldurationinhours) | `number` | The duration from the time that a proposal is created until it expires. |
| [`thresholdComparator`](#cdkhyperledgerfabricnetworkhyperledgerfabricnetworkpropspropertythresholdcomparator) | [`cdk-hyperledger-fabric-network.ThresholdComparator`](#cdk-hyperledger-fabric-network.ThresholdComparator) | Determines whether the yes votes must be greater than the threshold percentage or must be greater than or equal to the threhold percentage to be approved. |
| [`thresholdPercentage`](#cdkhyperledgerfabricnetworkhyperledgerfabricnetworkpropspropertythresholdpercentage) | `number` | The percentage of votes among all members that must be yes for a proposal to be approved. |
| [`users`](#cdkhyperledgerfabricnetworkhyperledgerfabricnetworkpropspropertyusers) | [`cdk-hyperledger-fabric-network.HyperledgerFabricUserProps`](#cdk-hyperledger-fabric-network.HyperledgerFabricUserProps)[] | List of users to register with Fabric CA. |

---

Expand Down Expand Up @@ -838,6 +939,18 @@ The percentage of votes among all members that must be yes for a proposal to be

---

##### `users`<sup>Optional</sup> <a name="cdk-hyperledger-fabric-network.HyperledgerFabricNetworkProps.property.users" id="cdkhyperledgerfabricnetworkhyperledgerfabricnetworkpropspropertyusers"></a>

```typescript
public readonly users: HyperledgerFabricUserProps[];
```

- *Type:* [`cdk-hyperledger-fabric-network.HyperledgerFabricUserProps`](#cdk-hyperledger-fabric-network.HyperledgerFabricUserProps)[]

List of users to register with Fabric CA.

---

### HyperledgerFabricNodeProps <a name="cdk-hyperledger-fabric-network.HyperledgerFabricNodeProps" id="cdkhyperledgerfabricnetworkhyperledgerfabricnodeprops"></a>

Construct properties for `HyperledgerFabricNode`.
Expand Down Expand Up @@ -913,6 +1026,53 @@ The Amazon Managed Blockchain instance type for the node.

---

### HyperledgerFabricUserProps <a name="cdk-hyperledger-fabric-network.HyperledgerFabricUserProps" id="cdkhyperledgerfabricnetworkhyperledgerfabricuserprops"></a>

Construct properties for `HyperledgerFabricUser`.

#### Initializer <a name="[object Object].Initializer" id="object-objectinitializer"></a>

```typescript
import { HyperledgerFabricUserProps } from 'cdk-hyperledger-fabric-network'

const hyperledgerFabricUserProps: HyperledgerFabricUserProps = { ... }
```

#### Properties <a name="Properties" id="properties"></a>

| **Name** | **Type** | **Description** |
| --- | --- | --- |
| [`affilitation`](#cdkhyperledgerfabricnetworkhyperledgerfabricuserpropspropertyaffilitation)<span title="Required">*</span> | `string` | User's affiliation to the member. |
| [`userId`](#cdkhyperledgerfabricnetworkhyperledgerfabricuserpropspropertyuserid)<span title="Required">*</span> | `string` | User ID to register with CA. |

---

##### `affilitation`<sup>Required</sup> <a name="cdk-hyperledger-fabric-network.HyperledgerFabricUserProps.property.affilitation" id="cdkhyperledgerfabricnetworkhyperledgerfabricuserpropspropertyaffilitation"></a>

```typescript
public readonly affilitation: string;
```

- *Type:* `string`

User's affiliation to the member.

Should be hierarchical with member name as root(`MemberName.Dept1`).

---

##### `userId`<sup>Required</sup> <a name="cdk-hyperledger-fabric-network.HyperledgerFabricUserProps.property.userId" id="cdkhyperledgerfabricnetworkhyperledgerfabricuserpropspropertyuserid"></a>

```typescript
public readonly userId: string;
```

- *Type:* `string`

User ID to register with CA.

---



## Enums <a name="Enums" id="enums"></a>
Expand Down
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
![license](https://img.shields.io/github/license/aws-samples/cdk-hyperledger-fabric-network?color=green&style=flat-square)

This repository contains a CDK construct to deploy a Hyperledger Fabric network
running on Amazon Managed Blockchain. It currently builds out a member and its
nodes, but the following enhanced functionality is planned for future releases:
running on Amazon Managed Blockchain. It builds out a member and its nodes, a VPC
and associated endpoint to access them, and a set of users enrolled on the network.

The following functionality is planned for future releases:

* Add support for Java and .NET
* Enroll users, storing their credentials in Secrets Manager
* Create channels on nodes
* Instantiate chaincode on nodes
* Support for Java and .NET


## Installation
Expand Down Expand Up @@ -84,6 +85,10 @@ new HyperledgerFabricNetwork(this, 'Example', {
instanceType: hyperledger.InstanceType.STANDARD5_LARGE,
},
],
users: [
{ userId: 'AppUser1', affilitation: 'MyMember' },
{ userId: 'AppUser2', affilitation: 'MyMember.department1' },
],
});
```

Expand Down
17 changes: 17 additions & 0 deletions lambdas/fabric/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module.exports = {
"env": {
"browser": false,
"commonjs": false,
"es2021": true,
},
"extends": "airbnb",
"parserOptions": {
"ecmaVersion": 13,
},
"rules": {
"max-len": ["error", {
"code": 120,
}],
"no-console": "off",
},
};
33 changes: 33 additions & 0 deletions lambdas/fabric/enroll-admin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const FabricCAClient = require('fabric-ca-client');
const utilities = require('./utilities');

// Extract environment variables
const adminPasswordArn = process.env.ADMIN_PASSWORD_ARN;
const caEndpoint = process.env.CA_ENDPOINT;
const privateKeyArn = process.env.PRIVATE_KEY_ARN;
const signedCertArn = process.env.SIGNED_CERT_ARN;
const tlsCertBucket = process.env.TLS_CERT_BUCKET;
const tlsCertKey = process.env.TLS_CERT_KEY;

const caUrl = `https://${caEndpoint}`;
const caName = utilities.getCaName(caEndpoint);

// Enroll the admin only on creation
exports.handler = async (event) => {
if (event.RequestType === 'Create') {
try {
// Get the TLS cert from S3
const caTlsCert = await utilities.getS3Object(tlsCertBucket, tlsCertKey);
// Get the admin credentials from Secrets Manager
const adminPwd = await utilities.getSecret(adminPasswordArn);
// Create a new client for interacting with the CA
const ca = new FabricCAClient(caUrl, { trustedRoots: caTlsCert, verify: false }, caName);
// Enroll the admin user, and import the new identity into Secrets Manager
const enrollment = await ca.enroll({ enrollmentID: 'admin', enrollmentSecret: adminPwd });
await utilities.putSecret(privateKeyArn, enrollment.key.toBytes());
await utilities.putSecret(signedCertArn, enrollment.certificate);
} catch (error) {
console.error(`Failed to enroll admin user: ${error}`);
}
}
};
14 changes: 14 additions & 0 deletions lambdas/fabric/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "fabric",
"version": "0.0.1",
"dependencies": {
"@aws-sdk/client-s3": "3.53.1",
"@aws-sdk/client-secrets-manager": "3.53.0",
"fabric-ca-client": "2.2.11",
"fabric-common": "2.2.11"
},
"devDependencies": {
"eslint": "^8.11.0",
"eslint-config-airbnb": "^19.0.4"
}
}
Loading

0 comments on commit 484aa81

Please sign in to comment.