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 후 부트스트랩 그룹 .Groups
에 AllowAdmins
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
…
}
}