ファイングレイン・アクセス・コントロールのライブラリを使用したサンプルでの手順説明
このトピックでは、このライブラリとチェーンコードの使用例をいくつか示します。いずれも、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 admins 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 Thomasに権限を付与している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の明示的なID (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 admins
}
**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
アクセス制御リストで制限されています。
リソースへのアクセスのチェック
この新しいリソースをチェーンコードで使用すると、管理者が、Marbleチェーンコードのinvoke()
メソッドを次のように変更した場合にのみ、Marbleを転送できるようになります:
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 new 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
…
}
}