Fine-Grained Access Control Marbles Sample
The marbles chaincode application lets you create assets (marbles) with unique attributes (name, size, color and owner) and trade these assets with fellow participants in a blockchain network.
This sample application includes a variety of functions to let you examine how to work with access control lists and groups to restrict functions to certain users.
- Overview of the Sample
- Pre-requisites and Setup
- Implement the Fine-Grained Access Control Marble Sample
- Testing the Access Control
- Sample Files Reference
Overview of the Sample
The test scenario included in the sample contains the following restrictions in order to manage assets:
- Bulk transfer of red marbles is only allowed by identities having the
"redMarblesTransferPermission"
Fabric attribute. - Bulk transfer of blue marbles is only allowed by identities having the
"blueMarblesTransferPermission"
Fabric attribute. - Deletion of marbles is only allowed to identities with
"deleteMarblePermission"
Fabric attribute.
These restrictions are enforced by implementing the following library methods in the fgMarbles_chaincode.go
chaincode:
- Create a fine-grained ACL group named
bulkMarblesTransferGroup
. This group will define all the identities which can transfer marbles based on color (bulk transfers):createGroup(stub, []string{" bulkMarblesTransferGroup", "List of Identities allowed to Transfer Marbles in Bulk", "%ATTR%redMarblesTransferPermission=true, %ATTR%blueMarblesTransferPermission=true", ".ACLs"})
- Create a fine-grained ACL named
redMarblesAcl
which provides bulk transfer of red marbles access tobulkMarblesTransferGroup
:createACL(stub, []string{"redMarblesAcl", "ACL to control who can transfer red marbles in bulk", "redMarblesTransferPermission", "%GRP%bulkMarblesTransferGroup", "true", ".ACLs"})
- Create a fine-grained ACL named
blueMarblesAcl
which provides bulk transfer of blue marbles access tobulkMarblesTransferGroup
:createACL(stub, []string{"blueMarblesAcl", "ACL to control who can transfer blue marbles in bulk", "blueMarblesTransferPermission", "%GRP%bulkMarblesTransferGroup", "true", ".ACLs"})
- Create a fine-grained ACL named
deleteMarbleAcl
to restrict marble deletion based on"canDeleteMarble=true"
Fabric attribute:createACL(stub, []string{"deleteMarbleAcl", "ACL to control who can Delete a Marble", "deleteMarblePermission", "%ATTR%deleteMarblePermission=true", "true", ".ACLs"})
- Create a fine-grained ACL resource named
marble
, operations on which are controlled using the various ACLs we created:createResource(stub, []string{"marble", "System marble resource", "deleteMarbleAcl,blueMarblesAcl,redMarblesAcl,.ACLs"})
Pre-requisites and Setup
To run the fine-grained access control version of the marbles sample, complete these steps:
- Download the fine-grained access control version of the marbles
sample. On the Developer Tools tab, open the
Samples pane, and then click the download link
under Marbles with Fine-Grained ACLs. Extract this
package, which contains ZIP files of the marbles sample
(
fgACL_MarbleSampleCC.zip
), Node.js files to run the sample (fgACL-NodeJSCode.zip
), and the fine-grained access control library (Fine-GrainedAccessControlLibrary.zip
). - Generate the chaincode package that will be deployed to
Blockchain Platform:
- Extract the contents of the
fgACL_MarbleSampleCC.zip
file to thefgACL_MarbleSampleCC
directory. The contents of thefgACL_MarbleSampleCC
directory will be thefgACL_Operations.go
,fgGroups_Operations.go
,fgMarbles_chaincode.go
,fgResource_Operations.go
, andgo.mod
files and theoracle.com
directory. - From the command line, go to the
fgACL_MarbleSampleCC
directory, and runGO111MODULE=on go mod vendor
. This command downloads the required dependencies and adds them to thevendor
directory. - Compress all the contents (the four Go files, the
go.mod
file, and thevendor
andoracle.com
directories) of thefgACL_MarbleSampleCC
directory in ZIP format. Your chaincode is ready to be deployed to Blockchain Platform.
- Extract the contents of the
- Install and deploy the updated sample chaincode package
(
fgACL_MarbleSampleCC.zip
) as described in Use Quick Deployment. - On the Developer Tools tab, open the Application Development pane, and then follow the instructions to download the Node.js SDK.
- On the Developer Tools tab, open the
Application Development pane, and then click
Download the development package.
- Extract the development package into the same folder with the Node.js files downloaded with the sample.
- In the
network.yaml
file, look for thecertificateAuthorities
entry and itsregistrar
entry. The administrator's password is masked (converted to***
) in thenetwork.yaml
when downloaded. It should be replaced with the administrator's clear text password when running this sample.
- Register a new identity with your Blockchain Platform
instance:
- Create a new user in IDCS (referred to as
<NewIdentity>
in the following steps) in the IDCS mapped to your tenancy. - Give this user the
CA_User
application role for your instance.
- Create a new user in IDCS (referred to as
Implement the Fine-Grained Access Control Marble Sample
Complete the following steps to enroll your new user and implement the ACL restrictions using the provided Node.js scripts.
- Enroll the new user:
node registerEnrollUser.js <NewIdentity> <Password>
- Initialization: Initialize the access control lists.
node invokeQueryCC.js <NewIdentity> <Password> <ChannelName> <ChaincodeName> ACLInitialization
- Create the access control lists, groups, and resources: This creates the ACL resources described in the overview.
node invokeQueryCC.js <NewIdentity> <Password> <ChannelName> <ChaincodeName> createFineGrainedAclSampleResources
- Create your test marble resources: This creates several test marble assets - blue1 and blue2 owned by tom, red1 and red2 owned by jerry, and green1 and green2 owned by spike.
node invokeQueryCC.js <NewIdentity> <Password> <ChannelName> <ChaincodeName> createTestMarbles
Testing the Access Control
To test that our access control lists are allowing only the correct users to perform each function, run through some sample scenarios.
- Transfer a marble: Transfer marble
blue1
from tom to jerry. Because there are no restrictions on who can transfer a single marble, this should complete successfully.node invokeQueryCC.js <NewIdentity> <Password> <ChannelName> <ChaincodeName> transferMarble blue1 jerry
- Transfer a marble as the administrative user: Transfer marble
blue1
from jerry to spike. Because there are no restrictions on who can transfer a single marble, this should also complete successfully.node invokeQueryCC.js <AdminIdentity> <Password> <ChannelName> <ChaincodeName> transferMarble blue1 spike
- Get history: Query the history of the marble named
blue1
. It should return that it was transferred first to jerry then to spike.node invokeQueryCC.js <AdminIdentity> <Password> <ChannelName> <ChaincodeName> getHistoryForMarble blue1
- Transfer all red marbles: The
redMarblesAcl
ACL should allow this transfer because the newly registered identity has the required"redMarblesTransferPermission=true"
Fabric attribute, so the two red marbles should be transferred to tom.node invokeQueryCC.js <NewIdentity> <Password> <ChannelName> <ChaincodeName> transferMarblesBasedOnColor red tom
- Transfer all red marbles as the administrative user: The administrative identity doesn't have the
"redMarblesTransferPermission=true"
Fabric attribute, so theredMarblesAcl
ACL should block this transfer.node invokeQueryCC.js <AdminIdentity> <Password> <ChannelName> <ChaincodeName> transferMarblesBasedOnColor red jerry
- Transfer all green marbles: By default, only explicitly defined access is allowed. Because there isn't an ACL which allows for bulk transfer of green marbles, this should fail.
node invokeQueryCC.js <NewIdentity> <Password> <ChannelName> <ChaincodeName> transferMarblesBasedOnColor green tom
- Delete a marble: The
deleteMarbleAcl
ACL allows this deletion because the newly registered identity has the required"deleteMarblePermission=true"
Fabric attribute.node invokeQueryCC.js <NewIdentity> <Password> <ChannelName> <ChaincodeName> delete green1
- Delete a marble as the administrative user: The
deleteMarbleAcl
ACL should prevent this deletion because the administrative identity doesn't have the required"deleteMarblePermission=true"
Fabric attribute.node invokeQueryCC.js < AdminIdentity > <Password> <ChannelName> <ChaincodeName> delete green2
Sample Files Reference
These tables list the methods available in the chaincode and application files included with the sample.
fgMarbles_chaincode.go
Function | Description |
---|---|
initMarble |
Create a new marble |
transferMarble |
Transfer a marble from one owner to another based on name |
createTestMarbles |
Calls initMarble to create new sample marbles for testing purposes
|
createFineGrainedAclSampleResources |
Creates the fine-grained access control list (ACL), groups, and resources required by our test scenario |
transferMarblesBasedOnColor |
Transfers multiple marbles of a certain color to another owner |
delete |
Delete a marble |
readMarble |
Returns all attributes of a marble based on name |
getHistoryForMarble |
Returns a history of values for a marble |
fgACL_Operations.go
Methods | Parameters | Description |
---|---|---|
getACL |
|
Get a named ACL or read all ACLs. The user invoking the method must have READ access to the named ACL. |
createACL |
|
To create a new ACL, the user invoking the method needs to have CREATE access to the bootstrap resource named ". ACLs" . Duplicate named ACLs are not allowed
|
deleteACL |
|
The user invoking the method must have DELETE access to the named ACL. |
updateACL |
|
The user invoking the method must have UPDATE access to the named resource, and the named ACL must exist. |
addAfterACL |
|
The user invoking the method must have UPDATE access to the named resource, and the named ACL must exist. |
addBeforeACL |
|
The user invoking the method must have UPDATE access to the named resource, and the named ACL must exist. |
addPatternToACL |
|
The user invoking the method must have UPDATE access to the named resource, and the named ACL must exist. |
removePatternFromACL |
|
The user invoking the method must have UPDATE access to the named resource, and the named ACL must exist. |
updateDescription |
|
The user invoking the method must have UPDATE access to the named resource, and the named ACL must exist. |
removeBindACL |
|
The user invoking the method must have UPDATE access to the named resource, and the named ACL must exist. |
addAccess |
|
The user invoking the method must have UPDATE access to the named resource, and the named ACL must exist. |
removeAccess |
|
The user invoking the method must have UPDATE access to the named resource, and the named ACL must exist. |
ACLInitialization |
|
This function is used to initialize the fine-grained ACL support. |
fgGroups_Operations.go
Methods | Parameters | Description |
---|---|---|
getGroup |
|
If name= The user invoking the method must have READ access to this group. |
createGroup |
|
Returns The user invoking the method must have CREATE access to bootstrap group |
deleteGroup |
|
The user invoking the method must have DELETE access to this group. |
addAfterGroup |
|
The user invoking the method must have UPDATE access to this group. |
addBeforeGroup |
|
The user invoking the method must have UPDATE access to this group. |
updateDescriptionForGroup |
|
The user invoking the method must have UPDATE access to this group. |
removeBindAclFromGroup |
|
The user invoking the method must have UPDATE access to this group. |
addMembersToGroup |
|
The user invoking the method must have UPDATE access to this group. |
removeMembersFromGroup |
|
The user invoking the method must have UPDATE access to this group. |
fgResource_Operations.go
Methods | Parameters | Description |
---|---|---|
createResource |
|
The user invoking the method needs to have CREATE access to the bootstrap resource named ". Resources" . Duplicate named resources are not allowed.
|
getResource |
|
The user invoking the method must have READ access to the resource |
deleteResource |
|
The user invoking the method must have DELETE access to the named resource |
addAfterACLInResource |
|
The user invoking the method must have UPDATE access to this resource |
addBeforeACLInResource |
|
The user invoking the method must have UPDATE access to this resource |
updateDescriptionInResource |
|
The user invoking the method must have UPDATE access to this resource |
removeBindACLInResource |
|
The user invoking the method must have UPDATE access to this resource |
checkResourceAccess |
|
Checks whether the current user invoking the method has the specified access to the named resource. |