mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-22 09:35:10 +00:00
wip - add nodejs sample showing abac (attribute based access control)
This commit is contained in:
parent
ed81d7b9b1
commit
fd1dcf1b34
6 changed files with 217 additions and 3 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -9,3 +9,4 @@
|
||||||
/config
|
/config
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.project
|
.project
|
||||||
|
node_modules
|
||||||
|
|
|
||||||
145
chaincode/abac/node/abac.js
Normal file
145
chaincode/abac/node/abac.js
Normal file
|
|
@ -0,0 +1,145 @@
|
||||||
|
/*
|
||||||
|
# Copyright IBM Corp. All Rights Reserved.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
const shim = require('fabric-shim');
|
||||||
|
const util = require('util');
|
||||||
|
|
||||||
|
// this is exact same chaincode as balance-transfer app except that
|
||||||
|
// it adds ABAC (Attribute Based Access Control) to the Init method
|
||||||
|
var Chaincode = class {
|
||||||
|
|
||||||
|
// Initialize the chaincode
|
||||||
|
async Init(stub) {
|
||||||
|
console.info('========= abac Init =========');
|
||||||
|
let ret = stub.getFunctionAndParameters();
|
||||||
|
console.info(ret);
|
||||||
|
let cid = new shim.ClientIdentity(stub);
|
||||||
|
if (!cid.assertAttributeValue("abac.init", "true")) {
|
||||||
|
return shim.error("Insufficient privileges");
|
||||||
|
}
|
||||||
|
let args = ret.params;
|
||||||
|
// initialise only if 4 parameters passed.
|
||||||
|
if (args.length != 4) {
|
||||||
|
return shim.error('Incorrect number of arguments. Expecting 4');
|
||||||
|
}
|
||||||
|
|
||||||
|
let A = args[0];
|
||||||
|
let B = args[2];
|
||||||
|
let Aval = args[1];
|
||||||
|
let Bval = args[3];
|
||||||
|
|
||||||
|
if (typeof parseInt(Aval) !== 'number' || typeof parseInt(Bval) !== 'number') {
|
||||||
|
return shim.error('Expecting integer value for asset holding');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await stub.putState(A, Buffer.from(Aval));
|
||||||
|
try {
|
||||||
|
await stub.putState(B, Buffer.from(Bval));
|
||||||
|
return shim.success();
|
||||||
|
} catch (err) {
|
||||||
|
return shim.error(err);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
return shim.error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async Invoke(stub) {
|
||||||
|
let ret = stub.getFunctionAndParameters();
|
||||||
|
console.info(ret);
|
||||||
|
let method = this[ret.fcn];
|
||||||
|
if (!method) {
|
||||||
|
console.log('no method of name:' + ret.fcn + ' found');
|
||||||
|
return shim.success();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
let payload = await method(stub, ret.params);
|
||||||
|
return shim.success(payload);
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
return shim.error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transaction makes payment of X units from A to B
|
||||||
|
async invoke(stub, args) {
|
||||||
|
if (args.length != 3) {
|
||||||
|
throw new Error('Incorrect number of arguments. Expecting 3');
|
||||||
|
}
|
||||||
|
|
||||||
|
let A = args[0];
|
||||||
|
let B = args[1];
|
||||||
|
if (!A || !B) {
|
||||||
|
throw new Error('asset holding must not be empty');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the state from the ledger
|
||||||
|
let Avalbytes = await stub.getState(A);
|
||||||
|
if (!Avalbytes) {
|
||||||
|
throw new Error('Failed to get state of asset holder A');
|
||||||
|
}
|
||||||
|
let Aval = parseInt(Avalbytes.toString());
|
||||||
|
|
||||||
|
let Bvalbytes = await stub.getState(B);
|
||||||
|
if (!Bvalbytes) {
|
||||||
|
throw new Error('Failed to get state of asset holder B');
|
||||||
|
}
|
||||||
|
|
||||||
|
let Bval = parseInt(Bvalbytes.toString());
|
||||||
|
// Perform the execution
|
||||||
|
let amount = parseInt(args[2]);
|
||||||
|
if (typeof amount !== 'number') {
|
||||||
|
throw new Error('Expecting integer value for amount to be transaferred');
|
||||||
|
}
|
||||||
|
|
||||||
|
Aval = Aval - amount;
|
||||||
|
Bval = Bval + amount;
|
||||||
|
console.info(util.format('Aval = %d, Bval = %d\n', Aval, Bval));
|
||||||
|
|
||||||
|
// Write the states back to the ledger
|
||||||
|
await stub.putState(A, Buffer.from(Aval.toString()));
|
||||||
|
await stub.putState(B, Buffer.from(Bval.toString()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deletes an entity from state
|
||||||
|
async delete(stub, args) {
|
||||||
|
if (args.length != 1) {
|
||||||
|
throw new Error('Incorrect number of arguments. Expecting 1');
|
||||||
|
}
|
||||||
|
|
||||||
|
let A = args[0];
|
||||||
|
|
||||||
|
// Delete the key from the state in ledger
|
||||||
|
await stub.deleteState(A);
|
||||||
|
}
|
||||||
|
|
||||||
|
// query callback representing the query of a chaincode
|
||||||
|
async query(stub, args) {
|
||||||
|
if (args.length != 1) {
|
||||||
|
throw new Error('Incorrect number of arguments. Expecting name of the person to query')
|
||||||
|
}
|
||||||
|
|
||||||
|
let jsonResp = {};
|
||||||
|
let A = args[0];
|
||||||
|
|
||||||
|
// Get the state from the ledger
|
||||||
|
let Avalbytes = await stub.getState(A);
|
||||||
|
if (!Avalbytes) {
|
||||||
|
jsonResp.error = 'Failed to get state for ' + A;
|
||||||
|
throw new Error(JSON.stringify(jsonResp));
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonResp.name = A;
|
||||||
|
jsonResp.amount = Avalbytes.toString();
|
||||||
|
console.info('Query Response:');
|
||||||
|
console.info(jsonResp);
|
||||||
|
return Avalbytes;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
shim.start(new Chaincode());
|
||||||
15
chaincode/abac/node/package.json
Normal file
15
chaincode/abac/node/package.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"name": "abac",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "attribute based access control chaincode implemented in node.js",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.4.0",
|
||||||
|
"npm": ">=5.3.0"
|
||||||
|
},
|
||||||
|
"scripts": { "start" : "node abac.js" },
|
||||||
|
"engine-strict": true,
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"fabric-shim": "1.3.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -93,7 +93,7 @@ function writeRunFabric {
|
||||||
image: hyperledger/fabric-ca-tools
|
image: hyperledger/fabric-ca-tools
|
||||||
environment:
|
environment:
|
||||||
- GOPATH=/opt/gopath
|
- GOPATH=/opt/gopath
|
||||||
command: /bin/bash -c 'sleep 3;/scripts/run-fabric.sh 2>&1 | tee /$RUN_LOGFILE; sleep 99999'
|
command: /bin/bash -c 'sleep 3;/scripts/run-fabric.sh -l ${LANGUAGE} 2>&1 | tee /$RUN_LOGFILE; sleep 99999'
|
||||||
volumes:
|
volumes:
|
||||||
- ./scripts:/scripts
|
- ./scripts:/scripts
|
||||||
- ./$DATA:/$DATA
|
- ./$DATA:/$DATA
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,39 @@
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
source $(dirname "$0")/env.sh
|
source $(dirname "$0")/env.sh
|
||||||
|
LANGUAGE=golang
|
||||||
|
while getopts ":l:" opt; do
|
||||||
|
case "$opt" in
|
||||||
|
l)
|
||||||
|
LANGUAGE=$OPTARG
|
||||||
|
;;
|
||||||
|
: )
|
||||||
|
echo "Invalid option: $OPTARG requires an argument" 1>&2
|
||||||
|
exit 1;
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
if [ "$LANGUAGE" = "go" ]; then
|
||||||
|
LANGUAGE = "golang"
|
||||||
|
fi
|
||||||
|
if [[ "$LANGUAGE" != "node" && "$LANGUAGE" != "golang" ]]; then
|
||||||
|
echo "LANGUAGE = ${LANGUAGE} is not supported"
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
|
||||||
function main {
|
function main {
|
||||||
|
|
||||||
|
logr "LANGUAGE=${LANGUAGE}"
|
||||||
|
|
||||||
|
if [ "$LANGUAGE" = "golang" ]; then
|
||||||
|
CC_SRC_PATH="github.com/hyperledger/fabric-samples/chaincode/abac/go"
|
||||||
|
elif [ "$LANGUAGE" = "node" ]; then
|
||||||
|
CC_SRC_PATH="github.com/hyperledger/fabric-samples/chaincode/abac/node"
|
||||||
|
fi
|
||||||
|
|
||||||
|
logr "CC_SRC_PATH=${CC_SRC_PATH}"
|
||||||
|
|
||||||
|
|
||||||
done=false
|
done=false
|
||||||
|
|
||||||
# Wait for setup to complete and then wait another 10 seconds for the orderer and peers to start
|
# Wait for setup to complete and then wait another 10 seconds for the orderer and peers to start
|
||||||
|
|
@ -62,7 +92,7 @@ function main {
|
||||||
initPeerVars ${PORGS[1]} 1
|
initPeerVars ${PORGS[1]} 1
|
||||||
switchToAdminIdentity
|
switchToAdminIdentity
|
||||||
logr "Instantiating chaincode on $PEER_HOST ..."
|
logr "Instantiating chaincode on $PEER_HOST ..."
|
||||||
peer chaincode instantiate -C $CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "$POLICY" $ORDERER_CONN_ARGS
|
peer chaincode instantiate -C $CHANNEL_NAME -n mycc -v 1.0 -l ${LANGUAGE} -c '{"Args":["init","a","100","b","200"]}' -P "$POLICY" $ORDERER_CONN_ARGS
|
||||||
|
|
||||||
# Query chaincode from the 1st peer of the 1st org
|
# Query chaincode from the 1st peer of the 1st org
|
||||||
initPeerVars ${PORGS[0]} 1
|
initPeerVars ${PORGS[0]} 1
|
||||||
|
|
@ -215,7 +245,8 @@ function makePolicy {
|
||||||
function installChaincode {
|
function installChaincode {
|
||||||
switchToAdminIdentity
|
switchToAdminIdentity
|
||||||
logr "Installing chaincode on $PEER_HOST ..."
|
logr "Installing chaincode on $PEER_HOST ..."
|
||||||
peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric-samples/chaincode/abac/go
|
logr "peer chaincode install -n mycc -v 1.0 -l ${LANGUAGE} -p ${CC_SRC_PATH}"
|
||||||
|
peer chaincode install -n mycc -v 1.0 -l ${LANGUAGE} -p ${CC_SRC_PATH}
|
||||||
}
|
}
|
||||||
|
|
||||||
function fetchConfigBlock {
|
function fetchConfigBlock {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,28 @@
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
# use golang as the default language for chaincode
|
||||||
|
export LANGUAGE=golang
|
||||||
|
while getopts ":l:" opt; do
|
||||||
|
case "$opt" in
|
||||||
|
l)
|
||||||
|
LANGUAGE=$OPTARG
|
||||||
|
;;
|
||||||
|
: )
|
||||||
|
echo "Invalid option: $OPTARG requires an argument" 1>&2
|
||||||
|
exit 1;
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
if [ "$LANGUAGE" = "go" ]; then
|
||||||
|
LANGUAGE = "golang"
|
||||||
|
fi
|
||||||
|
if [[ "$LANGUAGE" != "node" && "$LANGUAGE" != "golang" ]]; then
|
||||||
|
echo "LANGUAGE = ${LANGUAGE} is not supported"
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
echo "start.sh: LANGUAGE = ${LANGUAGE}"
|
||||||
|
|
||||||
SDIR=$(dirname "$0")
|
SDIR=$(dirname "$0")
|
||||||
source ${SDIR}/scripts/env.sh
|
source ${SDIR}/scripts/env.sh
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue