ファイングレイン・アクセス・コントロールのライブラリを使用したサンプルでの手順説明

このトピックでは、このライブラリとチェーンコードの使用例をいくつか示します。いずれも、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
    …

    }

}