使用细粒度访问控制库时的示例
本主题提供了一些如何使用库和链代码的示例。这些示例都假定已调用 Init()
函数来创建引导实体,并且 Init()
和 invoke()
的调用方为 "%CN%frank.thomas@example.com"
。应用程序中的正常流是创建一些初始访问控制列表,这些列表将用于授予或拒绝对其他实体的访问权限。
初始化
调用 Initialization()
函数以在部署链代码时创建引导实体。例如:
import "chaincodeACL"
func (t \*SimpleChaincode) Init(nil, stub shim.ChaincodeStubInterface) pb.Response
{
err := chaincodeACL.Initialization(stub)
}
创建 ACL
import "chaincodeACL"
...
{
**ACLMgr** := chaincodeACL.NewACLManager(nil, stub) // Not specify identity, use caller's identity as default.
// Define a new ACL
**newACL** := chaincodeACL.ACL{
"AllowAdmins", // ACL name
"Allow administrators full access", // Description
[]string{"CREATE","READ","UPDATE","DELETE"}, // Accesses allowed or not
true, // Allowed
[]string{"%CN%bob.dole@example.com","%OU%example.com,"%GRP%admins"}, // Initial identity patterns
".ACLs.acl", // Start with bootstrap ACL
}
// Add this ACL with default identity (caller's identify here)
err := **ACLMgr**.Create( **newACL** , nil)
}
可以使用新 ACL 修改可以执行某些操作的人员。首先,将此新 ACL 添加到引导组 .Groups
以允许任何管理员创建组。
将 ACL 添加到组
import "chaincodeACL"
…
{
**groupMgr** := chaincodeACL.NewGroupManager(nil, stub) // Not specify identity, use caller's identity as default.
err := **groupMgr**.AddAfterACL(
".Groups", // Bootstrap group name
".Groups.ACL", // Which ACL to add after
"AllowAdmins", // The new ACL to add
nil // with default identity that's frank.thomas
)
}
这将在初始引导 ACL 之后将 AllowAdmins
ACL 添加到引导组 .Groups
。这样可以确保 Frank Thomas 仍然可以完成对 .Groups
组的操作,因为授予 Frank 权限的 ACL 在列表中排在第一位。现在,与 AllowAdmins
ACL 匹配的任何人都可以完成 CREATE、READ、UPDATE 或 DELETE 操作(现在可以创建组)。
创建组
管理员现在可以创建组。
import "chaincodeACL"
...
{
...
// Define a new group.
**newGroup** := chaincodeACL.Group{
"AdminGrp", // Name of the group
"Administrators of the app", // Description of the group
{"%CN%jill.muller@example.com","%CN%ivan.novak@example.com","%ATTR%role=admin"},
[]string{"AllowAdmins"}, // The ACL for the group
}
**groupMgr** := chaincodeACL.NewGroupManager(nil, stub) // Not specify identity, use caller's identity as default.
err := **groupMgr**.Create( **newGroup** , bob\_garcia\_certificate) // Using a specific certificate
...
}
此调用使用显式身份(Bob Garcia,通过使用其证书)尝试创建组。由于 Bob Garcia 与 AllowAdmins
ACL 中的模式匹配,并且该 ACL 的成员可以在引导组 .Groups
上执行 CREATE 操作,因此此调用将成功。如果不在组织单元 example.com
或组 AdminGrp
(仍不存在)中的 Jim Silva 的证书作为最后一个参数传递,则调用将失败,因为他没有适当的权限。此调用创建名为 "AdminGrp
" 的组,该组的初始成员为 jill.muller@example.com 和 ivan.novak@example.com,或者具有属性 (ABAC) role=admin 的任何成员。
创建资源
import "chaincodeACL"
...
{
...
**newResource** := **chaincodeACL**.Resource{
"transferMarble", // Name of resource to create
"The transferMarble chaincode function", // Description of the resource
[]string{"AllowAdmins"}, // Single ACL for now allowing administrators
}
**resourceMgr** := **chaincodeACL**.NewResourceManager(nil, stub) // Not specify identity, use caller's identity as default.
err := **resourceMgr**.Create(resourceMgr, nil) // Using caller's certificate
...
}
这将创建一个名为 transferMarble
的资源,应用程序可以使用该资源控制对 transferMarble
链代码函数的访问。访问当前受 AllowAdmins
访问控制列表的限制。
检查资源的访问权限
您可以通过修改 Marbles 链代码的 invoke()
方法,在链代码中使用此新资源仅允许管理者传输大理石,如下所示:
import "chaincodeACL"
…
func (t \*SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
**resourceMgr** := **chaincodeACL**.NewResourceManager(nil, stub) // Not specify identity, use caller's identity as default.
function, args := stub.GetFunctionAndParameters()
fmt.Println("invoke is running " + function) // Handle different functions
if function == "initMarble" { //create a marble
return t.initMarble(stub, args)}
else if function == " **transferMarble**" { //change owner of a specific marble
**allowed** , err : = **resourceMgr**. **CheckAccess** ("transferMarble", "UPDATE", nil)
if **allowed** == true {
return t.transferMarble(stub, args)
else {
return NOACCESS
}
} else if function == "transferMarblesBasedOnColor" { //transfer all marbles of a certain color
…
}
}