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
redMarblesAclwhich 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
blueMarblesAclwhich 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
deleteMarbleAclto 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 page, open the Samples pane, and then click the download link under Marbles with Fine-Grained ACLs. Extract this package, which contains
.zipfiles 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 Oracle Blockchain Platform:
- Extract the contents of the
fgACL_MarbleSampleCC.zipfile to thefgACL_MarbleSampleCCdirectory. The contents of thefgACL_MarbleSampleCCdirectory will be thefgACL_Operations.go,fgGroups_Operations.go,fgMarbles_chaincode.go,fgResource_Operations.go, andgo.modfiles and theoracle.comdirectory. - From the command line, go to the
fgACL_MarbleSampleCCdirectory, and runGO111MODULE=on go mod vendor. This command downloads the required dependencies and adds them to thevendordirectory. - Compress all the contents (the four Go files, the
go.modfile, and thevendorandoracle.comdirectories) of thefgACL_MarbleSampleCCdirectory in ZIP format. Your chaincode is ready to be deployed to Oracle 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 page, open the Application Development pane, and then follow the instructions to download the Node.js SDK.
- On the Developer Tools page, 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.yamlfile, look for thecertificateAuthoritiesentry and itsregistrarentry. The administrator's password is masked (converted to***) in thenetwork.yamlwhen downloaded. Replace this password with the administrator's clear text password when running this sample.
- Register a new identity with your Oracle Blockchain Platform instance:
- Create a user in IDCS (referred to as
<NewIdentity>in the following steps) in the IDCS mapped to your tenancy. - Give this user the
CA_Userapplication role for your instance.
- Create a 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
blue1from tom to jerry. Because there are no restrictions on who can transfer a single marble, this completes successfully.node invokeQueryCC.js <NewIdentity> <Password> <ChannelName> <ChaincodeName> transferMarble blue1 jerry - Transfer a marble as the administrative user: Transfer marble
blue1from jerry to spike. Because there are no restrictions on who can transfer a single marble, this also completes successfully.node invokeQueryCC.js <AdminIdentity> <Password> <ChannelName> <ChaincodeName> transferMarble blue1 spike - Get history: Query the history of the marble named
blue1. It returns that it was transferred first to jerry then to spike.node invokeQueryCC.js <AdminIdentity> <Password> <ChannelName> <ChaincodeName> getHistoryForMarble blue1 - Transfer all red marbles: The
redMarblesAclACL allows this transfer because the newly registered identity has the required"redMarblesTransferPermission=true"Fabric attribute, so the two red marbles will 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 theredMarblesAclACL blocks 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 fails.
node invokeQueryCC.js <NewIdentity> <Password> <ChannelName> <ChaincodeName> transferMarblesBasedOnColor green tom - Delete a marble: The
deleteMarbleAclACL 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
deleteMarbleAclACL prevents 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 marble |
transferMarble |
Transfer a marble from one owner to another based on name |
createTestMarbles |
Calls initMarble to create 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 calling the method must have READ access to the named ACL. |
createACL |
|
To create an ACL, the user calling the method must have CREATE access to the bootstrap resource named ". ACLs". Duplicate named ACLs are not allowed
|
deleteACL |
|
The user calling the method must have DELETE access to the named ACL. |
updateACL |
|
The user calling the method must have UPDATE access to the named resource, and the named ACL must exist. |
addAfterACL |
|
The user calling the method must have UPDATE access to the named resource, and the named ACL must exist. |
addBeforeACL |
|
The user calling the method must have UPDATE access to the named resource, and the named ACL must exist. |
addPatternToACL |
|
The user calling the method must have UPDATE access to the named resource, and the named ACL must exist. |
removePatternFromACL |
|
The user calling the method must have UPDATE access to the named resource, and the named ACL must exist. |
updateDescription |
|
The user calling the method must have UPDATE access to the named resource, and the named ACL must exist. |
removeBindACL |
|
The user calling the method must have UPDATE access to the named resource, and the named ACL must exist. |
addAccess |
|
The user calling the method must have UPDATE access to the named resource, and the named ACL must exist. |
removeAccess |
|
The user calling 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 calling the method must have READ access to this group. |
createGroup |
|
Returns The user calling the method must have CREATE access to bootstrap group |
deleteGroup |
|
The user calling the method must have DELETE access to this group. |
addAfterGroup |
|
The user calling the method must have UPDATE access to this group. |
addBeforeGroup |
|
The user calling the method must have UPDATE access to this group. |
updateDescriptionForGroup |
|
The user calling the method must have UPDATE access to this group. |
removeBindAclFromGroup |
|
The user calling the method must have UPDATE access to this group. |
addMembersToGroup |
|
The user calling the method must have UPDATE access to this group. |
removeMembersFromGroup |
|
The user calling the method must have UPDATE access to this group. |
fgResource_Operations.go
| Methods | Parameters | Description |
|---|---|---|
createResource |
|
The user calling the method must have CREATE access to the bootstrap resource named ". Resources". Duplicate named resources are not allowed.
|
getResource |
|
The user calling the method must have READ access to the resource |
deleteResource |
|
The user calling the method must have DELETE access to the named resource |
addAfterACLInResource |
|
The user calling the method must have UPDATE access to this resource |
addBeforeACLInResource |
|
The user calling the method must have UPDATE access to this resource |
updateDescriptionInResource |
|
The user calling the method must have UPDATE access to this resource |
removeBindACLInResource |
|
The user calling the method must have UPDATE access to this resource |
checkResourceAccess |
|
Checks whether the current user calling the method has the specified access to the named resource. |