Fine-Grained Access Control 라이브러리를 사용한 Walkthough 예

이 항목에서는 이 라이브러리 및 체인 코드를 사용할 수 있는 방법에 대한 몇 가지 예를 제공합니다. 부트스트랩 엔티티를 만들기 위해 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

)

}

그러면 초기 부트스트랩 ACL 이후 부트스트랩 그룹 .GroupsAllowAdmins ACL이 추가됩니다. 따라서 Frank Thomas가 .Groups에 대한 작업을 계속 수행할 수 있습니다. 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가 자신의 인증서를 마지막 인수로 전달했다면 적절한 권한이 없으므로 호출이 실패합니다. 이 호출은 그룹의 초기 멤버가 jill.muller@example.com 및 ivan.novak@example.com이거나 속성(ABAC) role=admin인 모든 사용자를 포함하는 "AdminGrp"이라는 새 그룹을 생성합니다.

새 리소스 생성

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 액세스 제어 목록에 의해 제한됩니다.

리소스에 대한 액세스 확인

체인코드에서 이 새 리소스를 사용하면 다음과 같이 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 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
    …

    }

}