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