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 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 후 부트스트랩 그룹 .GroupsAllowAdmins ACL이 추가됩니다. 따라서 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

...
}

이 호출은 명시적 ID(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 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
    …

    }

}