ファイングレイン・アクセス・コントロールのライブラリを使用したサンプルでの手順説明
このトピックでは、ライブラリとチェーンコードの使用方法の例をいくつか示します。いずれも、これらの例では、ブートストラップ・エンティティを作成するために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
)
}
これにより、ブートストラップ・グループ.Groups
の最初のブートストラップACLの後ろに、AllowAdmins
ACLが追加されます。これにより、Frank権限を付与するACLがリストの最初にあるため、Frank Thomasは引き続き.Groups
グループに対する操作を完了できます。これで、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操作を実行できるため、このコールは成功します。Jim Silva (組織単位example.com
にもグループAdminGrp
(まだ存在していない)にも属していない)が、自分の証明書を最後の引数として渡した場合、適切な権限がないためコールが失敗します。上のコールでは、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
…
}
}