Skip to content

Commit

Permalink
feat(connector-fabric): add support for vault transit secret engine
Browse files Browse the repository at this point in the history
Signed-off-by: Pritam Singh <pkspritam16@gmail.com>
  • Loading branch information
Zzocker authored and petermetz committed Aug 31, 2021
1 parent f5ffb92 commit 2161e0d
Show file tree
Hide file tree
Showing 22 changed files with 1,833 additions and 42 deletions.
6 changes: 6 additions & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"DHTAPI",
"DockerOde",
"ealen",
"ecparams",
"Errorf",
"escc",
"execa",
Expand All @@ -49,8 +50,11 @@
"isready",
"jboss",
"JORDI",
"jsrsasign",
"Keychain",
"Keycloak",
"KEYUTIL",
"KJUR",
"Knetic",
"LEDGERBLOCKACK",
"lmify",
Expand Down Expand Up @@ -85,7 +89,9 @@
"protoc",
"protos",
"RUSTC",
"sbjpubkey",
"Secp",
"shrn",
"socketio",
"SPDX",
"Sprintf",
Expand Down
128 changes: 128 additions & 0 deletions packages/cactus-plugin-ledger-connector-fabric/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ This plugin provides `Cactus` a way to interact with Fabric networks. Using this
- [Getting Started](#getting-started)
- [Architecture](#architecture)
- [Usage](#usage)
- [Identity Providers](#identity-providers)
- [Runing the tests](#running-the-tests)
- [Built With](#built-with)
- [Prometheus Exporter](#prometheus-exporter)
Expand Down Expand Up @@ -43,6 +44,10 @@ The above diagram shows the sequence diagram of run-transaction-endpoint. User A
![run-transaction-endpoint transact() method](docs/architecture/images/run-transaction-endpoint-transact.png)
The above diagram shows the sequence diagraom of transact() method of the PluginLedgerConnectorFabric class. The caller to this function, which in reference to the above sequence diagram is API server, sends RunTransactionRequest object as an argument to the transact() method. Based on the invocationType (FabricContractInvocationType.CALL, FabricCOntractInvocationType.SEND), corresponding responses are send back to the caller.

![run-transaction-endpoint-enroll](docs/architecture/images/run-transaction-endpoint-enroll.png)

The above diagram shows the sequence diagraom of enroll() method of the PluginLedgerConnectorFabric class. The caller to this function, which in reference to the above sequence diagram is API server, sends Signer object along with EnrollmentRequest as an argument to the enroll() method. Based on the singerType (FabricSigningCredentialType.X509, FabricSigningCredentialType.VaultX509 .. more in TODO), corresponding identity is enrolled and stored inside keychain.

## Usage

To use this import public-api and create new **PluginLedgerConnectorFabric** and **ChainCodeCompiler**.
Expand All @@ -66,8 +71,131 @@ For compile the chaincodes:
const result = await compiler.compile(opts);
```

To support signing of message with multiple identity types
```typescript
// vault server config for supporting vault identity provider
const vaultConfig:IVaultConfig = {
endpoint : "http://localhost:8200",
transitEngineMountPath: "/transit",
}
// provide list of identity signing to be supported
const supportedIdentity:FabricSigningCredentialType[] = [FabricSigningCredentialType.VaultX509,FabricSigningCredentialType.X509]
const pluginOptions:IPluginLedgerConnectorFabricOptions = {
// other options
vaultConfig : vaultConfig,
supportedIdentity:supportedIdentity
// .. other options
}
const connector: PluginLedgerConnectorFabric = new PluginLedgerConnectorFabric(pluginOptions);
```

To enroll an identity
```typescript
await connector.enroll(
{
keychainId: "keychain-identifier-for storing-certData",
keychainRef: "cert-data-identifier",
type: FabricSigningCredentialType.VaultX509, // FabricSigningCredentialType.X509

// require in case of vault
vaultTransitKey: {
token: "vault-token",
keyName: "vault-key-label",
},
},
{
enrollmentID: "client2",
enrollmentSecret: "pw",
mspId: "Org1MSP",
caId: "ca.org1.example.com",
},
);
```
To Register an identity using register's key
```typescript
const secret = await connector.register(
{
keychainId: "keychain-id-that-store-certData-of-registrar",
keychainRef: "certData-label",
type: FabricSigningCredentialType.VaultX509, // FabricSigningCredentialType.X509

// require in case of vault
vaultTransitKey: {
token: testToken,
keyName: registrarKey,
},
},
{
enrollmentID: "client-enrollmentID",
enrollmentSecret: "pw",
affiliation: "org1.department1",
},
"ca.org1.example.com", // caID
);
```

To transact with fabric
```typescript
const resp = await connector.transact{
signingCredential: {
keychainId: keychainId,
keychainRef: "client-certData-id",
type: FabricSigningCredentialType.VaultX509, // FabricSigningCredentialType.X509

// require in case of vault
vaultTransitKey: {
token: testToken,
keyName: registrarKey,
},
},
// .. other options
}
```

To Rotate the key
```typescript
await connector.rotateKey(
{
keychainId: keychainId,
keychainRef: "client-certData-id",
type: FabricSigningCredentialType.VaultX509, // FabricSigningCredentialType.X509

// require in case of vault
vaultTransitKey: {
token: testToken,
keyName: registrarKey,
},
},
{
enrollmentID: string;
enrollmentSecret: string;
caId: string;
}
)
```

> Extensive documentation and examples in the [readthedocs](https://readthedocs.org/projects/hyperledger-cactus/) (WIP)
## Identity Providers

Identity providers allows client to manage their private more effectively and securely. Cactus Fabric Connector support multiple type of providers. Each provider differ based upon where the private are stored. On High level certificate credential are stored as

```typescript
{
type: FabricSigningCredentialType;
credentials: {
certificate: string;
// if identity type is IdentityProvidersType.X509
privateKey?: string;
};
mspId: string;
}
```

Currently Cactus Fabric Connector supports following Identity Providers

- X509 : Simple and unsecured provider wherein `private` key is stored along with certificate in some `datastore`. Whenever connector require signature on fabric message, private key is brought from the `datastore` and message signed at the connector.
- Vault-X.509 : Secure provider wherein `private` key is stored with vault's transit transit engine and certificate in `certDatastore`. Rather then bringing the key to the connector, message digest are sent to the vault server which returns the `signature`.
- WS-X.509 (Future Work) : Secure provider wherein `private` key is stored with `client` and certificate in `certDatastore`. To get the fabric messages signed, message digest is sent to the client via `webSocket` connection opened by the client in the beginning.

## Running the tests

Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
@startuml
title Hyperledger Cactus\nSequence Diagram\nRun Transaction Endpoint\enroll() method

skinparam sequenceArrowThickness 2
skinparam roundcorner 20
skinparam maxmessagesize 300
skinparam sequenceParticipant underline

actor "Caller" as caller
participant "PluginLedgerConnectorFabric" as t << (C,#ADD1B2) class >>

autoactivate on

activate caller
caller -> t : enroll(signer: FabricSigningCredential,\nreq: FabricEnrollmentRequest)
t->t: {\n\tenrollmentID: string,\n\tenrollmentSecret: string,\n\tcaId: string,\n\tmspId: string\n}

alt #LightBlue this.activatedSinger.includes(singer.type) === false
t-->caller: throw Error(`singer.type not activated`)
end

t->t : ca = this.createCaClient(caId)
t->t : enrollmentRequest = {enrollmentID,enrollmentSecret}

group #LightBlue if singer.type == FabricSigningCredentialType.DeafultX509
else #LightYellow if singer.type == FabricSigningCredentialType.VaulttX509
t->t : enrollmentRequest.csr = await (this.activatedSinger[VaulttX509] as VaultX509Provider)\n\t.getKey(singer.vaultTransitKey)\n\t.generateCSR(enrollmentID)
else #LightCoral default
t -> caller: throw Error('unknown SingerType')
end

t->t: resp = await ca.enroll(enrollmentRequest)
t->t: certData = {singer.type,mspId,certificate}

alt if resp.key !== undefined
t->t: resp.credentials.privateKey = resp.key.toBytes();
end

t->t : await certDatastore.put(singer.keychainref,certData)

deactivate caller
@enduml
11 changes: 8 additions & 3 deletions packages/cactus-plugin-ledger-connector-fabric/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,16 +78,19 @@
"@hyperledger/cactus-core-api": "0.8.0",
"axios": "0.21.1",
"bl": "5.0.0",
"bn.js": "4.12.0",
"express": "4.17.1",
"fabric-ca-client": "2.2.8",
"fabric-common": "2.2.8",
"fabric-network": "2.2.8",
"fabric-ca-client": "2.3.0-snapshot.49",
"fabric-common": "2.3.0-snapshot.49",
"fabric-network": "2.3.0-snapshot.49",
"fabric-protos": "2.2.8",
"form-data": "4.0.0",
"http-status-codes": "2.1.4",
"jsrsasign": "10.4.0",
"multer": "1.4.3",
"ngo": "2.7.0",
"node-ssh": "12.0.0",
"node-vault": "0.9.22",
"openapi-types": "9.1.0",
"prom-client": "13.2.0",
"temp": "0.9.4",
Expand All @@ -99,7 +102,9 @@
"@hyperledger/cactus-test-tooling": "0.8.0",
"@types/express": "4.17.13",
"@types/fs-extra": "9.0.12",
"@types/jsrsasign": "8.0.13",
"@types/multer": "1.4.7",
"@types/node-vault": "0.9.13",
"@types/temp": "0.9.1",
"@types/uuid": "8.3.1",
"fs-extra": "10.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,40 @@
],
"components": {
"schemas": {
"VaultTransitKey" : {
"type": "object",
"nullable": false,
"required": [
"keyName",
"token"
],
"properties": {
"keyName": {
"type": "string",
"minLength": 1,
"maxLength": 100,
"nullable": false,
"description": "label of private key"
},
"token": {
"type": "string",
"minLength": 1,
"maxLength": 100,
"nullable": false,
"description": "token for accessing private key"
}
},
"description": "vault key details for signing fabric message with private key stored with transit engine."
},
"FabricSigningCredentialType" : {
"type": "string",
"enum": [
"X.509",
"Vault-X.509"
],
"nullable": false,
"description": "different type of identity provider for singing fabric messages supported by this package"
},
"FabricSigningCredential": {
"type": "object",
"required": [
Expand All @@ -49,6 +83,14 @@
"minLength": 1,
"maxLength": 100,
"nullable": false
},
"type" : {
"$ref" : "#/components/schemas/FabricSigningCredentialType",
"description" : "singing identity type to be used for signing fabric message , by by default default is supported"
},
"vaultTransitKey" : {
"$ref" : "#/components/schemas/VaultTransitKey",
"properties" : "vault key details , if Vault-X.509 identity provider to be used for singing fabric messages"
}
}
},
Expand Down

0 comments on commit 2161e0d

Please sign in to comment.