Skip to content

Commit 9de9c66

Browse files
RafaelAPBraynatopedrajeta
authored andcommitted
feat(cactus-connector-fabric): add get tx receipt by tx id
Authored-by: Eduardo Vasques <[email protected]> Signed-off-by: Rafael Belchior <[email protected]>
1 parent 8ee9c62 commit 9de9c66

File tree

4 files changed

+105
-37
lines changed

4 files changed

+105
-37
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
name: DAST_Scan_Nuclei
2-
2+
33
env:
44
NODEJS_VERSION: v18.18.2
5-
5+
66
on:
77
push:
88
branches: [main, dev]
9-
9+
1010
pull_request:
1111
branches: [main, dev]
12-
12+
1313
jobs:
1414
nuclei-scan:
1515
runs-on: ubuntu-22.04
@@ -25,30 +25,30 @@ jobs:
2525
libvcx \
2626
indy-cli \
2727
&& sudo rm -f /etc/apt/sources.list.d/sovrin.list*
28-
28+
2929
- name: Set up NodeJS ${{ env.NODEJS_VERSION }}
3030
uses: actions/[email protected]
3131
with:
3232
node-version: ${{ env.NODEJS_VERSION }}
33-
33+
3434
- name: Install jq
3535
run: sudo apt update && sudo apt install -y jq
36-
36+
3737
- name: Verify jq
3838
run: jq --version
39-
39+
4040
- uses: actions/[email protected]
41-
41+
4242
- uses: actions/[email protected]
4343
with:
4444
go-version: 1.23
45-
45+
4646
- run: go install -v github.com/projectdiscovery/nuclei/v3/cmd/[email protected]
47-
47+
4848
- run: nuclei --version
49-
49+
5050
- run: npm run configure
51-
51+
5252
- name: Create URLs file for Nuclei
5353
run: |
5454
echo https://localhost:4000/ > urls.txt
@@ -73,58 +73,91 @@ jobs:
7373
echo https://localhost:4000/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-besu/get-prometheus-exporter-metrics
7474
echo https://localhost:4000/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-besu/get-besu-record
7575
} >> urls.txt
76-
76+
7777
- run: yarn generate-api-server-config
78-
79-
- run: jq '.authorizationProtocol = "NONE"' .config.json > .config2.json && mv .config2.json .config.json
80-
78+
8179
# Delete the first and the second items in the array (remove keychain and manual consortium plugins)
8280
- run: jq 'del(.plugins[0,1])' .config.json > .config2.json && mv .config2.json .config.json
83-
81+
8482
- name: Install Keychain manual plugin into the API server
8583
run: jq '.plugins += [{ "packageName":"@hyperledger/cactus-plugin-keychain-memory","type":"org.hyperledger.cactus.plugin_import_type.LOCAL","action":"org.hyperledger.cactus.plugin_import_action.INSTALL","options":{"packageSrc":"/home/runner/work/cacti/cacti/packages/cactus-plugin-keychain-memory/","instanceId":"0daacd05-d1cd-4eab-9332-4ad1aff4b909","keychainId":"d29d728e-eaa0-4e2d-b187-d132242b0d9a"}}]' .config.json > .config2.json && mv .config2.json .config.json
86-
84+
8785
- name: Install Fabric connector into the API server
8886
run: jq '.plugins += [{ "packageName":"@hyperledger/cactus-plugin-ledger-connector-fabric", "type":"org.hyperledger.cactus.plugin_import_type.LOCAL", "action":"org.hyperledger.cactus.plugin_import_action.INSTALL", "options":{ "packageSrc":"/home/runner/work/cacti/cacti/packages/cactus-plugin-ledger-connector-fabric/", "instanceId":"some-unique-fabric-connector-instance-id", "peerBinary":"/fabric-samples/bin/peer", "connectionProfile":"{}", "dockerBinary":"usr/local/bin/docker","cliContainerEnv":{"CORE_PEER_LOCALMSPID":"Org1MSP","CORE_PEER_ADDRESS":"peer0.org1.example.com:7051","CORE_PEER_MSPCONFIGPATH":"/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/[email protected]/msp","CORE_PEER_TLS_ROOTCERT_FILE":"/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt","ORDERER_TLS_ROOTCERT_FILE":"/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"},"discoveryOptions":{"enabled":true,"asLocalhost":true}}}] ' .config.json > .config2.json && mv .config2.json .config.json
89-
87+
9088
- name: Install Besu connector into the API server
9189
run: jq '.plugins += [{"packageName":"@hyperledger/cactus-plugin-ledger-connector-besu","type":"org.hyperledger.cactus.plugin_import_type.LOCAL","action":"org.hyperledger.cactus.plugin_import_action.INSTALL","options":{"packageSrc":"/home/runner/work/cacti/cacti/packages/cactus-plugin-ledger-connector-besu/", "rpcApiHttpHost":"http://127.0.0.1:8545", "rpcApiWsHost":"ws://127.0.0.1:8546", "instanceId":"some-unique-besu-connector-instance-id"}}]' .config.json > .config2.json && mv .config2.json .config.json
92-
90+
9391
- name: Run Besu all-in-one image
9492
run: |
9593
docker run -d -p 0.0.0.0:8545:8545/tcp -p 0.0.0.0:8546:8546/tcp -p 0.0.0.0:8888:8888/tcp -p 0.0.0.0:9001:9001/tcp -p 0.0.0.0:9545:9545/tcp ghcr.io/hyperledger/cactus-besu-all-in-one:v2.0.0-rc.7
9694
until curl --fail -X POST --data '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' localhost:8545; do sleep 5; done
97-
95+
9896
- name: Print API Server Config File - ./.config.json
9997
run: cat .config.json
100-
98+
10199
- name: Print Nuclei Config File - ./.nuclei-config.yaml
102100
run: cat .nuclei-config.yaml
103-
101+
104102
- name: Print Nuclei URL List File - ./urls.txt
105103
run: cat urls.txt
106104

105+
- name: Generate Audience and Issuer
106+
id: generate_ids
107+
run: |
108+
echo "audience=$(uuidgen)" >> $GITHUB_ENV
109+
echo "issuer=$(uuidgen)" >> $GITHUB_ENV
110+
111+
- name: Generate RSA Keys
112+
run: |
113+
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:2048
114+
openssl rsa -in private_key.pem -pubout -out public_key.pem
115+
116+
- name: Display Results
117+
run: |
118+
echo "Audience: ${{ env.audience }}"
119+
echo "Issuer: ${{ env.issuer }}"
120+
echo "Public Key:"
121+
cat public_key.pem
122+
echo "Private Key:"
123+
cat private_key.pem
124+
125+
- run: jq '.expressJwtOptions.secret = "-----BEGIN PUBLIC KEY-----\n$(cat public_key.pem)\n-----END PUBLIC KEY-----" |
126+
.expressJwtOptions.algorithms = ["RS256"] |
127+
.expressJwtOptions.issuer = "${{ env.issuer }}" |
128+
.expressJwtOptions.audience = "${{ env.audience }}"' .config.json > .config2.json && mv .config2.json .config.json
129+
130+
- name: Generate Auth Bearer Token
131+
run: |
132+
HEADER_B64=$(echo '{"alg":"RS256"}' | openssl base64 -e -A | tr -d '=' | tr '/+' '_-')
133+
PAYLOAD_B64=$(cat '{"scope":"read:health","iss":"${{ env.issuer }}","aud":"${{ env.audience }}"}' | openssl base64 -e -A | tr -d '=' | tr '/+' '_-')
134+
135+
SIGNATURE=$(echo -n "$HEADER_B64.$PAYLOAD_B64" | openssl dgst -sha256 -sign cat private_key.pem | openssl base64 -e -A | tr -d '=' | tr '/+' '_-')
136+
JWT="$HEADER_B64.$PAYLOAD_B64.$SIGNATURE"
137+
echo dast_jwt=$JWT >> $GITHUB_ENV
138+
107139
- name: Start API Server & Run DAST
108140
uses: BerniWittmann/[email protected]
109141
env:
110-
# Needed because the wait-on syntax otherwise keeps thinking that
111-
# there is a problem due to our self signed certificates on the
112-
# test instance of the API server
113-
NODE_TLS_REJECT_UNAUTHORIZED: 0
142+
# Needed because the wait-on syntax otherwise keeps thinking that
143+
# there is a problem due to our self signed certificates on the
144+
# test instance of the API server
145+
NODE_TLS_REJECT_UNAUTHORIZED: 0
114146
with:
115147
build: yarn --version
116148
start: yarn start:api-server
117149
command: "nuclei -version"
118150
command-windows: echo "The project build is not supported on the Windows operating system. Please use Linux or macOS"
119-
wait-on: "https://localhost:4000/api/v1/api-server/healthcheck"
120151
# wait for 10 minutes for the server to respond
121152
wait-on-timeout: 120
122-
153+
wait-on-command: |
154+
curl -X GET https://localhost:4000/api/v1/api-server/healthcheck -k -H "Authorization: Bearer ${{ env.dast_jwt }}"
155+
123156
- name: Run the dast nuclei scan
124157
run: "nuclei -list=urls.txt -dast -severity=high,critical -sarif-export ~/nuclei.sarif -output=nuclei.log"
125-
158+
126159
- name: GitHub Workflow artifacts
127160
uses: actions/[email protected]
128161
with:
129162
name: nuclei.log
130-
path: nuclei.log
163+
path: nuclei.log

packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/common/get-transaction-receipt-by-tx-id.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ export async function getTransactionReceiptByTxID(
157157
if (!extensionNsRwset.rwset) continue;
158158

159159
const rwset = extensionNsRwset.rwset;
160-
if (!rwset.writes) continue;
160+
if (!rwset.writes || rwset.writes.length === 0) continue;
161161
const rwsetWrite = rwset.writes;
162162
if (!rwsetWrite[0].key) continue;
163163
const rwsetKey = rwsetWrite[0].key;

packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/plugin-ledger-connector-fabric.ts

+38-4
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ import {
147147
formatCactiFullBlockResponse,
148148
formatCactiTransactionsBlockResponse,
149149
} from "./get-block/cacti-block-formatters";
150+
150151
import { GetBlockEndpointV1 } from "./get-block/get-block-endpoint-v1";
151152
import { GetChainInfoEndpointV1 } from "./get-chain-info/get-chain-info-endpoint-v1";
152153
import { querySystemChainCode } from "./common/query-system-chain-code";
@@ -158,10 +159,17 @@ import {
158159
} from "./common/utils";
159160
import { findAndReplaceFabricLoggingSpec } from "./common/find-and-replace-fabric-logging-spec";
160161
import { deployContractGoSourceImplFabricV256 } from "./deploy-contract-go-source/deploy-contract-go-source-impl-fabric-v2-5-6";
162+
import { Observable, ReplaySubject } from "rxjs";
161163

162164
const { loadFromConfig } = require("fabric-network/lib/impl/ccp/networkconfig");
163165
assertFabricFunctionIsAvailable(loadFromConfig, "loadFromConfig");
164166

167+
export interface IRunTxReqWithTxId {
168+
request: RunTransactionRequest;
169+
transactionId: string;
170+
timestamp: Date;
171+
}
172+
165173
/**
166174
* Constant value holding the default $GOPATH in the Fabric CLI container as
167175
* observed on fabric deployments that are produced by the official examples
@@ -229,6 +237,7 @@ export class PluginLedgerConnectorFabric
229237
private readonly certStore: CertDatastore;
230238
private readonly sshDebugOn: boolean;
231239
private runningWatchBlocksMonitors = new Set<WatchBlocksV1Endpoint>();
240+
private txSubject: ReplaySubject<IRunTxReqWithTxId> = new ReplaySubject();
232241

233242
public get className(): string {
234243
return PluginLedgerConnectorFabric.CLASS_NAME;
@@ -295,18 +304,26 @@ export class PluginLedgerConnectorFabric
295304
);
296305
}
297306

307+
298308
this.sshDebugOn = opts.sshDebugOn === true;
299309
if (this.opts.sshConfig) {
300310
this.sshConfig = this.opts.sshConfig;
311+
312+
if (this.sshDebugOn) {
313+
this.sshConfig = this.enableSshDebugLogs(this.sshConfig);
314+
}
301315
} else if (this.opts.sshConfigB64) {
302316
const sshConfigBuffer = Buffer.from(this.opts.sshConfigB64, "base64");
303317
const sshConfigString = sshConfigBuffer.toString("utf-8");
304318
this.sshConfig = JSON.parse(sshConfigString);
319+
320+
if (this.sshDebugOn) {
321+
this.sshConfig = this.enableSshDebugLogs(this.sshConfig);
322+
}
305323
} else {
306-
throw new Error("Cannot instantiate Fabric connector without SSH config");
307-
}
308-
if (this.sshDebugOn) {
309-
this.sshConfig = this.enableSshDebugLogs(this.sshConfig);
324+
// throw new Error("Cannot instantiate Fabric connector without SSH config");
325+
this.sshConfig = {}
326+
console.log("The check for sshConfig has been temporarily removed")
310327
}
311328

312329
this.signCallback = opts.signCallback;
@@ -339,6 +356,10 @@ export class PluginLedgerConnectorFabric
339356
return `@hyperledger/cactus-plugin-ledger-connector-fabric`;
340357
}
341358

359+
public getTxSubjectObservable(): Observable<IRunTxReqWithTxId> {
360+
return this.txSubject.asObservable();
361+
}
362+
342363
public async onPluginInit(): Promise<unknown> {
343364
return;
344365
}
@@ -1178,6 +1199,7 @@ export class PluginLedgerConnectorFabric
11781199
): Promise<RunTransactionResponse> {
11791200
const fnTag = `${this.className}#transact()`;
11801201
this.log.debug("%s ENTER", fnTag);
1202+
11811203
const {
11821204
channelName,
11831205
contractName,
@@ -1247,6 +1269,7 @@ export class PluginLedgerConnectorFabric
12471269
const transactionProposal = await contract.createTransaction(fnName);
12481270
transactionProposal.setEndorsingPeers(endorsingTargets);
12491271
out = await transactionProposal.setTransient(transientMap).submit();
1272+
transactionId = transactionProposal.getTransactionId();
12501273
break;
12511274
}
12521275
default: {
@@ -1255,6 +1278,17 @@ export class PluginLedgerConnectorFabric
12551278
}
12561279
}
12571280

1281+
// create IRunTxReqWithTxId for transaction monitoring
1282+
const receiptData: IRunTxReqWithTxId = {
1283+
request: req,
1284+
transactionId: transactionId == "" ? uuidv4() : transactionId,
1285+
timestamp: new Date(),
1286+
};
1287+
this.log.debug(
1288+
`IRunTxReqWithTxId created with ID: ${receiptData.transactionId}`,
1289+
);
1290+
this.txSubject.next(receiptData);
1291+
12581292
const res: RunTransactionResponse = {
12591293
functionOutput: this.convertToTransactionResponseType(
12601294
out,

packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/public-api.ts

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export {
99
PluginLedgerConnectorFabric,
1010
IPluginLedgerConnectorFabricOptions,
1111
SignPayloadCallback,
12+
IRunTxReqWithTxId,
1213
} from "./plugin-ledger-connector-fabric";
1314

1415
import { IPluginFactoryOptions } from "@hyperledger/cactus-core-api";

0 commit comments

Comments
 (0)