permissions: converted permissions to a service registered in line with other services at node level

This commit is contained in:
vsmk98 2019-07-24 14:00:49 +08:00
commit 53d580fb6c
9 changed files with 219 additions and 208 deletions

View File

@ -20,6 +20,9 @@ import (
"bufio" "bufio"
"errors" "errors"
"fmt" "fmt"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/permission"
"io" "io"
"os" "os"
"reflect" "reflect"
@ -167,6 +170,10 @@ func makeFullNode(ctx *cli.Context) *node.Node {
utils.RegisterDashboardService(stack, &cfg.Dashboard, gitCommit) utils.RegisterDashboardService(stack, &cfg.Dashboard, gitCommit)
} }
if utils.IsPermissionEnabled(ctx) {
RegisterPermissionService(ctx, stack)
}
// Whisper must be explicitly enabled by specifying at least 1 whisper flag or in dev mode // Whisper must be explicitly enabled by specifying at least 1 whisper flag or in dev mode
shhEnabled := enableWhisper(ctx) shhEnabled := enableWhisper(ctx)
shhAutoEnabled := !ctx.GlobalIsSet(utils.WhisperEnabledFlag.Name) && ctx.GlobalIsSet(utils.DeveloperFlag.Name) shhAutoEnabled := !ctx.GlobalIsSet(utils.WhisperEnabledFlag.Name) && ctx.GlobalIsSet(utils.DeveloperFlag.Name)
@ -190,6 +197,28 @@ func makeFullNode(ctx *cli.Context) *node.Node {
return stack return stack
} }
func RegisterPermissionService(ctx *cli.Context, stack *node.Node) {
if err := stack.Register(func(sctx *node.ServiceContext) (node.Service, error) {
dataDir := ctx.GlobalString(utils.DataDirFlag.Name)
var permissionConfig types.PermissionConfig
var err error
if permissionConfig, err = permission.ParsePermissionConifg(dataDir); err != nil {
utils.Fatalf("loading of permission-config.json failed", "error", err)
}
// start the permissions management service
pc, err := permission.NewQuorumPermissionCtrl(stack, &permissionConfig)
if err != nil {
utils.Fatalf("Failed to load the permission contracts as given in permissions-config.json %v", err)
}
log.Info("permission service created")
return pc, nil
}); err != nil {
utils.Fatalf("Failed to register the permission service: %v", err)
}
log.Info("permission service registered")
}
// dumpConfig is the dumpconfig command. // dumpConfig is the dumpconfig command.
func dumpConfig(ctx *cli.Context) error { func dumpConfig(ctx *cli.Context) error {
_, cfg := makeConfigNode(ctx) _, cfg := makeConfigNode(ctx)

View File

@ -343,14 +343,10 @@ func startNode(ctx *cli.Context, stack *node.Node) {
} }
}() }()
//START - QUORUM permission service //initialize permission as we can create eth client only after the node and RPC are started
go func() { if utils.IsPermissionEnabled(ctx) {
if ctx.GlobalBool(utils.EnableNodePermissionFlag.Name) { permission.StartPermissionService(stack)
if err := permission.StartQuorumPermissionService(ctx, stack); err != nil { }
utils.Fatalf("Failed to start permissions service %v", err)
}
}
}()
// Start auxiliary services if enabled // Start auxiliary services if enabled
if ctx.GlobalBool(utils.MiningEnabledFlag.Name) || ctx.GlobalBool(utils.DeveloperFlag.Name) { if ctx.GlobalBool(utils.MiningEnabledFlag.Name) || ctx.GlobalBool(utils.DeveloperFlag.Name) {

View File

@ -20,9 +20,11 @@ package utils
import ( import (
"compress/gzip" "compress/gzip"
"fmt" "fmt"
"gopkg.in/urfave/cli.v1"
"io" "io"
"os" "os"
"os/signal" "os/signal"
"path/filepath"
"runtime" "runtime"
"strings" "strings"
"syscall" "syscall"
@ -63,7 +65,21 @@ func Fatalf(format string, args ...interface{}) {
os.Exit(1) os.Exit(1)
} }
func IsPermissionEnabled(ctx *cli.Context) bool {
if ctx.GlobalBool(EnableNodePermissionFlag.Name) {
fileName := "permission-config.json"
fullPath := filepath.Join(ctx.GlobalString(DataDirFlag.Name), fileName)
if _, err := os.Stat(fullPath); err != nil {
log.Warn("permission-config.json file is missing. permission service will be disabled", "err", err)
return false
}
return true
}
return false
}
func StartNode(stack *node.Node) { func StartNode(stack *node.Node) {
if err := stack.Start(); err != nil { if err := stack.Start(); err != nil {
Fatalf("Error starting protocol stack: %v", err) Fatalf("Error starting protocol stack: %v", err)
} }

View File

@ -88,11 +88,6 @@ type OrgDetailInfo struct {
SubOrgList []string `json:"subOrgList"` SubOrgList []string `json:"subOrgList"`
} }
type OrgStruct struct {
OrgId string
Keys []string
}
// permission config for bootstrapping // permission config for bootstrapping
type PermissionConfig struct { type PermissionConfig struct {
UpgrdAddress common.Address UpgrdAddress common.Address
@ -178,8 +173,6 @@ var orgAdminRole string
const defaultMapLimit = 100 const defaultMapLimit = 100
//var OrgKeyMap, _ = lru.New(orgKeyMapLimit)
var OrgInfoMap = NewOrgCache() var OrgInfoMap = NewOrgCache()
var NodeInfoMap = NewNodeCache() var NodeInfoMap = NewNodeCache()
var RoleInfoMap = NewRoleCache() var RoleInfoMap = NewRoleCache()

Binary file not shown.

After

Width:  |  Height:  |  Size: 797 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 KiB

View File

@ -35,7 +35,6 @@ import (
istanbulBackend "github.com/ethereum/go-ethereum/consensus/istanbul/backend" istanbulBackend "github.com/ethereum/go-ethereum/consensus/istanbul/backend"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/bloombits" "github.com/ethereum/go-ethereum/core/bloombits"
"github.com/ethereum/go-ethereum/core/quorum"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
@ -335,12 +334,6 @@ func (s *Ethereum) APIs() []rpc.API {
Service: s.netRPCService, Service: s.netRPCService,
Public: true, Public: true,
}, },
{
Namespace: "quorumPermission",
Version: "1.0",
Service: quorum.NewQuorumControlsAPI(s.txPool, s.accountManager),
Public: true,
},
}...) }...)
return apis return apis
} }

View File

@ -1,7 +1,6 @@
package quorum package permission
import ( import (
"crypto/ecdsa"
"errors" "errors"
"fmt" "fmt"
"math/big" "math/big"
@ -10,9 +9,7 @@ import (
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
@ -65,20 +62,9 @@ const (
Inactive Inactive
) )
type PermissionContracts struct {
PermInterf *pbind.PermInterface
}
// QuorumControlsAPI provides an API to access Quorum's node permission and org key management related services // QuorumControlsAPI provides an API to access Quorum's node permission and org key management related services
type QuorumControlsAPI struct { type QuorumControlsAPI struct {
txPool *core.TxPool permCtrl *PermissionCtrl
ethClnt *ethclient.Client
acntMgr *accounts.Manager
txOpt *bind.TransactOpts
key *ecdsa.PrivateKey
permEnabled bool
permConfig *types.PermissionConfig
permInterf *pbind.PermInterface
} }
// txArgs holds arguments required for execute functions // txArgs holds arguments required for execute functions
@ -152,25 +138,8 @@ var (
) )
// NewQuorumControlsAPI creates a new QuorumControlsAPI to access quorum services // NewQuorumControlsAPI creates a new QuorumControlsAPI to access quorum services
func NewQuorumControlsAPI(tp *core.TxPool, am *accounts.Manager) *QuorumControlsAPI { func NewQuorumControlsAPI(p *PermissionCtrl) *QuorumControlsAPI {
return &QuorumControlsAPI{tp, nil, am, nil, nil, false, nil, nil} return &QuorumControlsAPI{p}
}
//Init initializes QuorumControlsAPI with eth client, permission contract and org key management control
func (q *QuorumControlsAPI) Init(ethClnt *ethclient.Client, key *ecdsa.PrivateKey, apiName string, pconfig *types.PermissionConfig, pc *pbind.PermInterface) error {
// check if the interface contract is deployed or not. if not
// permissions apis will not work. return error
q.ethClnt = ethClnt
q.permConfig = pconfig
if _, err := pbind.NewPermInterface(q.permConfig.InterfAddress, q.ethClnt); err != nil {
return err
}
q.permEnabled = true
q.key = key
q.permInterf = pc
return nil
} }
func (q *QuorumControlsAPI) OrgList() []types.OrgInfo { func (q *QuorumControlsAPI) OrgList() []types.OrgInfo {
@ -215,9 +184,6 @@ func (q *QuorumControlsAPI) GetOrgDetails(orgId string) (types.OrgDetailInfo, er
} }
func (q *QuorumControlsAPI) initOp(txa ethapi.SendTxArgs) (*pbind.PermInterfaceSession, ExecStatus) { func (q *QuorumControlsAPI) initOp(txa ethapi.SendTxArgs) (*pbind.PermInterfaceSession, ExecStatus) {
if !q.permEnabled {
return nil, ErrPermissionDisabled
}
var err error var err error
var w accounts.Wallet var w accounts.Wallet
@ -511,7 +477,7 @@ func (q *QuorumControlsAPI) UpdateAccountStatus(orgId string, acct common.Addres
// check if the account is network admin // check if the account is network admin
func (q *QuorumControlsAPI) isNetworkAdmin(account common.Address) bool { func (q *QuorumControlsAPI) isNetworkAdmin(account common.Address) bool {
ac := types.AcctInfoMap.GetAccount(account) ac := types.AcctInfoMap.GetAccount(account)
return ac != nil && ac.RoleId == q.permConfig.NwAdminRole return ac != nil && ac.RoleId == q.permCtrl.permConfig.NwAdminRole
} }
func (q *QuorumControlsAPI) isOrgAdmin(account common.Address, orgId string) (ExecStatus, error) { func (q *QuorumControlsAPI) isOrgAdmin(account common.Address, orgId string) (ExecStatus, error) {
@ -626,7 +592,7 @@ func (q *QuorumControlsAPI) valAccountStatusChange(orgId string, account common.
return ErrAccountNotThere, errors.New("account not there") return ErrAccountNotThere, errors.New("account not there")
} }
if ac.IsOrgAdmin && (ac.RoleId == q.permConfig.NwAdminRole || ac.RoleId == q.permConfig.OrgAdminRole) && (op == 1 || op == 3) { if ac.IsOrgAdmin && (ac.RoleId == q.permCtrl.permConfig.NwAdminRole || ac.RoleId == q.permCtrl.permConfig.OrgAdminRole) && (op == 1 || op == 3) {
return ErrOpNotAllowed, errors.New("operation not allowed on org admin account") return ErrOpNotAllowed, errors.New("operation not allowed on org admin account")
} }
@ -656,7 +622,7 @@ func (q *QuorumControlsAPI) checkOrgAdminExists(orgId, roleId string, account co
if ac.OrgId != orgId { if ac.OrgId != orgId {
return ErrAccountInUse, errors.New("account part of another org") return ErrAccountInUse, errors.New("account part of another org")
} }
if roleId != "" && roleId == q.permConfig.OrgAdminRole && ac.IsOrgAdmin { if roleId != "" && roleId == q.permCtrl.permConfig.OrgAdminRole && ac.IsOrgAdmin {
return ErrAccountOrgAdmin, errors.New("account already org admin for the org") return ErrAccountOrgAdmin, errors.New("account already org admin for the org")
} }
} }
@ -666,11 +632,11 @@ func (q *QuorumControlsAPI) checkOrgAdminExists(orgId, roleId string, account co
func (q *QuorumControlsAPI) valSubOrgBreadthDepth(porgId string) (ExecStatus, error) { func (q *QuorumControlsAPI) valSubOrgBreadthDepth(porgId string) (ExecStatus, error) {
org := types.OrgInfoMap.GetOrg(porgId) org := types.OrgInfoMap.GetOrg(porgId)
if q.permConfig.SubOrgDepth.Cmp(org.Level) == 0 { if q.permCtrl.permConfig.SubOrgDepth.Cmp(org.Level) == 0 {
return ErrMaxDepth, errors.New("max depth for sub orgs reached") return ErrMaxDepth, errors.New("max depth for sub orgs reached")
} }
if q.permConfig.SubOrgBreadth.Cmp(big.NewInt(int64(len(org.SubOrgList)))) == 0 { if q.permCtrl.permConfig.SubOrgBreadth.Cmp(big.NewInt(int64(len(org.SubOrgList)))) == 0 {
return ErrMaxBreadth, errors.New("max breadth for sub orgs reached") return ErrMaxBreadth, errors.New("max breadth for sub orgs reached")
} }
@ -725,7 +691,7 @@ func (q *QuorumControlsAPI) valAddOrg(args txArgs, pinterf *pbind.PermInterfaceS
} }
// check if any previous op is pending approval for network admin // check if any previous op is pending approval for network admin
if q.checkPendingOp(q.permConfig.NwAdminOrg, pinterf) { if q.checkPendingOp(q.permCtrl.permConfig.NwAdminOrg, pinterf) {
return ErrPendingApprovals return ErrPendingApprovals
} }
// check if org already exists // check if org already exists
@ -751,7 +717,7 @@ func (q *QuorumControlsAPI) valApproveOrg(args txArgs, pinterf *pbind.PermInterf
return ErrNotNetworkAdmin return ErrNotNetworkAdmin
} }
// check if anything pending approval // check if anything pending approval
if !q.validatePendingOp(q.permConfig.NwAdminOrg, args.orgId, args.url, args.acctId, 1, pinterf) { if !q.validatePendingOp(q.permCtrl.permConfig.NwAdminOrg, args.orgId, args.url, args.acctId, 1, pinterf) {
return ErrNothingToApprove return ErrNothingToApprove
} }
return ExecSuccess return ExecSuccess
@ -796,7 +762,7 @@ func (q *QuorumControlsAPI) valUpdateOrgStatus(args txArgs, pinterf *pbind.PermI
} }
//check if passed org id is network admin org. update should not be allowed //check if passed org id is network admin org. update should not be allowed
if args.orgId == q.permConfig.NwAdminOrg { if args.orgId == q.permCtrl.permConfig.NwAdminOrg {
return ErrOpNotAllowed return ErrOpNotAllowed
} }
// check if status update can be performed. Org should be approved for suspension // check if status update can be performed. Org should be approved for suspension
@ -820,7 +786,7 @@ func (q *QuorumControlsAPI) valApproveOrgStatus(args txArgs, pinterf *pbind.Perm
} else { } else {
return ErrOpNotAllowed return ErrOpNotAllowed
} }
if !q.validatePendingOp(q.permConfig.NwAdminOrg, args.orgId, "", common.Address{}, pendingOp, pinterf) { if !q.validatePendingOp(q.permCtrl.permConfig.NwAdminOrg, args.orgId, "", common.Address{}, pendingOp, pinterf) {
return ErrNothingToApprove return ErrNothingToApprove
} }
return ExecSuccess return ExecSuccess
@ -860,7 +826,7 @@ func (q *QuorumControlsAPI) valAssignAdminRole(args txArgs, pinterf *pbind.PermI
return ErrInvalidInput return ErrInvalidInput
} }
// check if caller is network admin // check if caller is network admin
if args.roleId != q.permConfig.OrgAdminRole && args.roleId != q.permConfig.NwAdminRole { if args.roleId != q.permCtrl.permConfig.OrgAdminRole && args.roleId != q.permCtrl.permConfig.NwAdminRole {
return ErrOpNotAllowed return ErrOpNotAllowed
} }
@ -892,7 +858,7 @@ func (q *QuorumControlsAPI) valApproveAdminRole(args txArgs, pinterf *pbind.Perm
return ErrInvalidAccount return ErrInvalidAccount
} }
// validate pending op // validate pending op
if !q.validatePendingOp(q.permConfig.NwAdminOrg, ac.OrgId, "", args.acctId, 4, pinterf) { if !q.validatePendingOp(q.permCtrl.permConfig.NwAdminOrg, ac.OrgId, "", args.acctId, 4, pinterf) {
return ErrNothingToApprove return ErrNothingToApprove
} }
return ExecSuccess return ExecSuccess
@ -920,7 +886,7 @@ func (q *QuorumControlsAPI) valRemoveRole(args txArgs, pinterf *pbind.PermInterf
} }
// admin roles cannot be removed // admin roles cannot be removed
if args.roleId == q.permConfig.OrgAdminRole || args.roleId == q.permConfig.NwAdminRole { if args.roleId == q.permCtrl.permConfig.OrgAdminRole || args.roleId == q.permCtrl.permConfig.NwAdminRole {
return ErrAdminRoles return ErrAdminRoles
} }
@ -943,7 +909,7 @@ func (q *QuorumControlsAPI) valAssignRole(args txArgs, pinterf *pbind.PermInterf
if args.acctId == (common.Address{0}) { if args.acctId == (common.Address{0}) {
return ErrInvalidInput return ErrInvalidInput
} }
if args.roleId == q.permConfig.OrgAdminRole || args.roleId == q.permConfig.NwAdminRole { if args.roleId == q.permCtrl.permConfig.OrgAdminRole || args.roleId == q.permCtrl.permConfig.NwAdminRole {
return ErrInvalidRole return ErrInvalidRole
} }
// check if caller is network admin // check if caller is network admin
@ -980,7 +946,7 @@ func (q *QuorumControlsAPI) valUpdateAccountStatus(args txArgs, pinterf *pbind.P
// validateAccount validates the account and returns the wallet associated with that for signing the transaction // validateAccount validates the account and returns the wallet associated with that for signing the transaction
func (q *QuorumControlsAPI) validateAccount(from common.Address) (accounts.Wallet, error) { func (q *QuorumControlsAPI) validateAccount(from common.Address) (accounts.Wallet, error) {
acct := accounts.Account{Address: from} acct := accounts.Account{Address: from}
w, err := q.acntMgr.Find(acct) w, err := q.permCtrl.eth.AccountManager().Find(acct)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -990,7 +956,7 @@ func (q *QuorumControlsAPI) validateAccount(from common.Address) (accounts.Walle
func (q *QuorumControlsAPI) newPermInterfaceSession(w accounts.Wallet, txa ethapi.SendTxArgs) *pbind.PermInterfaceSession { func (q *QuorumControlsAPI) newPermInterfaceSession(w accounts.Wallet, txa ethapi.SendTxArgs) *pbind.PermInterfaceSession {
frmAcct, transactOpts, gasLimit, gasPrice, nonce := q.getTxParams(txa, w) frmAcct, transactOpts, gasLimit, gasPrice, nonce := q.getTxParams(txa, w)
ps := &pbind.PermInterfaceSession{ ps := &pbind.PermInterfaceSession{
Contract: q.permInterf, Contract: q.permCtrl.permInterf,
CallOpts: bind.CallOpts{ CallOpts: bind.CallOpts{
Pending: true, Pending: true,
}, },
@ -1021,7 +987,7 @@ func (q *QuorumControlsAPI) getTxParams(txa ethapi.SendTxArgs, w accounts.Wallet
if txa.Nonce != nil { if txa.Nonce != nil {
nonce = new(big.Int).SetUint64(uint64(*txa.Nonce)) nonce = new(big.Int).SetUint64(uint64(*txa.Nonce))
} else { } else {
nonce = new(big.Int).SetUint64(q.txPool.Nonce(frmAcct.Address)) nonce = new(big.Int).SetUint64(q.permCtrl.eth.TxPool().Nonce(frmAcct.Address))
} }
return frmAcct, transactOpts, gasLimit, gasPrice, nonce return frmAcct, transactOpts, gasLimit, gasPrice, nonce
} }

View File

@ -5,9 +5,8 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/core/quorum"
"github.com/ethereum/go-ethereum/raft" "github.com/ethereum/go-ethereum/raft"
"gopkg.in/urfave/cli.v1" "github.com/ethereum/go-ethereum/rpc"
"io/ioutil" "io/ioutil"
"math/big" "math/big"
"os" "os"
@ -55,74 +54,23 @@ type PermissionLocalConfig struct {
} }
type PermissionCtrl struct { type PermissionCtrl struct {
node *node.Node node *node.Node
ethClnt *ethclient.Client ethClnt *ethclient.Client
eth *eth.Ethereum eth *eth.Ethereum
permissionedMode bool key *ecdsa.PrivateKey
key *ecdsa.PrivateKey dataDir string
dataDir string permUpgr *pbind.PermUpgr
permUpgr *pbind.PermUpgr permInterf *pbind.PermInterface
permInterf *pbind.PermInterface permNode *pbind.NodeManager
permNode *pbind.NodeManager permAcct *pbind.AcctManager
permAcct *pbind.AcctManager permRole *pbind.RoleManager
permRole *pbind.RoleManager permOrg *pbind.OrgManager
permOrg *pbind.OrgManager permConfig *types.PermissionConfig
permConfig *types.PermissionConfig orgChan chan struct{}
mux sync.Mutex nodeChan chan struct{}
} roleChan chan struct{}
acctChan chan struct{}
func (p *PermissionCtrl) Interface() *pbind.PermInterface { mux sync.Mutex
return p.permInterf
}
// Starts the permission services. services will come up only when
// geth is brought up in --permissioned mode and permission-config.json is present
func StartQuorumPermissionService(ctx *cli.Context, stack *node.Node) error {
var quorumApis []string
dataDir := ctx.GlobalString(utils.DataDirFlag.Name)
var permissionConfig types.PermissionConfig
var err error
if permissionConfig, err = ParsePermissionConifg(dataDir); err != nil {
log.Error("loading of permission-config.json failed", "error", err)
return nil
}
// start the permissions management service
pc, err := NewQuorumPermissionCtrl(stack, ctx.GlobalBool(utils.EnableNodePermissionFlag.Name), &permissionConfig)
if err != nil {
return err
}
if err = pc.Start(); err == nil {
quorumApis = []string{"quorumPermission"}
} else {
return err
}
rpcClient, err := stack.Attach()
if err != nil {
return err
}
stateReader := ethclient.NewClient(rpcClient)
for _, apiName := range quorumApis {
v := stack.GetRPC(apiName)
if v == nil {
return errors.New("failed to start quorum permission api")
}
qapi := v.(*quorum.QuorumControlsAPI)
err = qapi.Init(stateReader, stack.GetNodeKey(), apiName, &permissionConfig, pc.Interface())
if err != nil {
log.Info("Failed to starts API", "apiName", apiName)
} else {
log.Info("API started", "apiName", apiName)
}
}
return nil
} }
// converts local permissions data to global permissions config // converts local permissions data to global permissions config
@ -198,74 +146,103 @@ func waitForSync(e *eth.Ethereum) {
} }
} }
// Creates the controls structure for permissions func StartPermissionService(stack *node.Node) {
func NewQuorumPermissionCtrl(stack *node.Node, permissionedMode bool, pconfig *types.PermissionConfig) (*PermissionCtrl, error) { //initialize permission as we can create eth client only after the node and RPC are started
// Create a new eth client to for interfacing with the contract var permissionService *PermissionCtrl
stateReader, e, err := CreateEthClient(stack) if err := stack.Service(&permissionService); err != nil {
waitForSync(e) utils.Fatalf("cannot access permissions service %v", err)
if err != nil {
log.Error("Unable to create ethereum client for permissions check", "err", err)
return nil, err
} }
if permissionService == nil {
if pconfig.IsEmpty() && permissionedMode { utils.Fatalf("permission service unavailable")
log.Error("permission-config.json is missing contract address")
return nil, errors.New("permission-config.json is missing contract address")
} }
pu, err := pbind.NewPermUpgr(pconfig.UpgrdAddress, stateReader) //initialize the service to create eth client and get ethereum service
if err != nil { if err := permissionService.InitializeService(); err != nil {
log.Error("Permissions not enabled for the network", "err", err) utils.Fatalf("permissions service initialization failed %v", err)
return nil, err
} }
// check if permissioning contract is there at address. If not return from here if err := permissionService.Start(stack.Server()); err != nil {
pm, err := pbind.NewPermInterface(pconfig.InterfAddress, stateReader) utils.Fatalf("permissions service start failed %v", err)
if err != nil {
log.Error("Permissions not enabled for the network", "err", err)
return nil, err
} }
pmAcct, err := pbind.NewAcctManager(pconfig.AccountAddress, stateReader)
if err != nil {
log.Error("Permissions not enabled for the network", "err", err)
return nil, err
}
pmNode, err := pbind.NewNodeManager(pconfig.NodeAddress, stateReader)
if err != nil {
log.Error("Permissions not enabled for the network", "err", err)
return nil, err
}
pmRole, err := pbind.NewRoleManager(pconfig.RoleAddress, stateReader)
if err != nil {
log.Error("Permissions not enabled for the network", "err", err)
return nil, err
}
pmOrg, err := pbind.NewOrgManager(pconfig.OrgAddress, stateReader)
if err != nil {
log.Error("Permissions not enabled for the network", "err", err)
return nil, err
}
return &PermissionCtrl{
node: stack,
ethClnt: stateReader,
eth: e,
permissionedMode: permissionedMode,
key: stack.GetNodeKey(),
dataDir: stack.DataDir(),
permUpgr: pu,
permInterf: pm,
permNode: pmNode,
permAcct: pmAcct,
permRole: pmRole,
permOrg: pmOrg,
permConfig: pconfig,
}, nil
} }
// Starts monitoring service for permissions events at contract level // Creates the controls structure for permissions
func (p *PermissionCtrl) Start() error { func NewQuorumPermissionCtrl(stack *node.Node, pconfig *types.PermissionConfig) (*PermissionCtrl, error) {
// Create a new ethclient to for interfacing with the contract
return &PermissionCtrl{stack, nil, nil, stack.GetNodeKey(), stack.DataDir(), nil, nil, nil, nil, nil, nil, pconfig, make(chan struct{}), make(chan struct{}), make(chan struct{}), make(chan struct{}), sync.Mutex{}}, nil
}
func (p *PermissionCtrl) InitializeService() error {
clnt, ethereum, err := CreateEthClient(p.node)
if err != nil {
log.Error("creating eth client failed")
return err
}
waitFor
Sync(ethereum)
if err != nil {
log.Error("Unable to create ethereum client for permissions check", "err", err)
return err
}
if p.permConfig.IsEmpty() {
log.Error("permission-config.json is missing contract address")
return errors.New("permission-config.json is missing contract address")
}
pu, err := pbind.NewPermUpgr(p.permConfig.UpgrdAddress, clnt)
if err != nil {
log.Error("Permissions not enabled for the network", "err", err)
return err
}
// check if permissioning contract is there at address. If not return from here
pm, err := pbind.NewPermInterface(p.permConfig.InterfAddress, clnt)
if err != nil {
log.Error("Permissions not enabled for the network", "err", err)
return err
}
pmAcct, err := pbind.NewAcctManager(p.permConfig.AccountAddress, clnt)
if err != nil {
log.Error("Permissions not enabled for the network", "err", err)
return err
}
pmNode, err := pbind.NewNodeManager(p.permConfig.NodeAddress, clnt)
if err != nil {
log.Error("Permissions not enabled for the network", "err", err)
return err
}
pmRole, err := pbind.NewRoleManager(p.permConfig.RoleAddress, clnt)
if err != nil {
log.Error("Permissions not enabled for the network", "err", err)
return err
}
pmOrg, err := pbind.NewOrgManager(p.permConfig.OrgAddress, clnt)
if err != nil {
log.Error("Permissions not enabled for the network", "err", err)
return err
}
p.permUpgr = pu
p.permInterf = pm
p.permAcct = pmAcct
p.permNode = pmNode
p.permRole = pmRole
p.permOrg = pmOrg
p.ethClnt = clnt
p.eth = ethereum
log.Info("permission service initalized")
return nil
}
// Starts the node permissioning and event monitoring for permissions
// smart contracts
func (p *PermissionCtrl) Start(srvr *p2p.Server) error {
if p.ethClnt == nil || p.eth == nil {
log.Info("permission service not initialized")
return nil
}
log.Info("permission service start...")
// Permissions initialization // Permissions initialization
if err := p.init(); err != nil { if err := p.init(); err != nil {
log.Error("Permissions init failed", "err", err) log.Error("Permissions init failed", "err", err)
@ -283,7 +260,36 @@ func (p *PermissionCtrl) Start() error {
// monitor org level account management events // monitor org level account management events
go p.manageAccountPermissions() go p.manageAccountPermissions()
log.Info("permission service started")
return nil
}
func (s *PermissionCtrl) APIs() []rpc.API {
log.Info("permission rpc API called")
return []rpc.API{
{
Namespace: "quorumPermission",
Version: "1.0",
Service: NewQuorumControlsAPI(s),
Public: true,
},
}
}
func (s *PermissionCtrl) Protocols() []p2p.Protocol {
return []p2p.Protocol{}
}
func (p *PermissionCtrl) Stop() error {
if p.eth == nil || p.ethClnt == nil {
return nil
}
log.Info("stopping permission service...")
p.roleChan <- struct{}{}
p.orgChan <- struct{}{}
p.acctChan <- struct{}{}
p.nodeChan <- struct{}{}
log.Info("stopped permission service")
return nil return nil
} }
@ -347,6 +353,9 @@ func (p *PermissionCtrl) manageOrgPermissions() {
case evtOrgReactivated = <-chOrgReactivated: case evtOrgReactivated = <-chOrgReactivated:
types.OrgInfoMap.UpsertOrg(evtOrgReactivated.OrgId, evtOrgReactivated.PorgId, evtOrgReactivated.UltParent, evtOrgReactivated.Level, types.OrgApproved) types.OrgInfoMap.UpsertOrg(evtOrgReactivated.OrgId, evtOrgReactivated.PorgId, evtOrgReactivated.UltParent, evtOrgReactivated.Level, types.OrgApproved)
case <-p.orgChan:
log.Info("quit org contract watch")
return
} }
} }
} }
@ -409,6 +418,9 @@ func (p *PermissionCtrl) manageNodePermissions() {
p.updatePermissionedNodes(evtNodeBlacklisted.EnodeId, NodeDelete) p.updatePermissionedNodes(evtNodeBlacklisted.EnodeId, NodeDelete)
p.updateDisallowedNodes(evtNodeBlacklisted.EnodeId) p.updateDisallowedNodes(evtNodeBlacklisted.EnodeId)
types.NodeInfoMap.UpsertNode(evtNodeBlacklisted.OrgId, evtNodeBlacklisted.EnodeId, types.NodeBlackListed) types.NodeInfoMap.UpsertNode(evtNodeBlacklisted.OrgId, evtNodeBlacklisted.EnodeId, types.NodeBlackListed)
case <-p.nodeChan:
log.Info("quit node contract watch")
return
} }
} }
} }
@ -547,6 +559,9 @@ func (p *PermissionCtrl) manageAccountPermissions() {
case evtStatusChanged = <-chStatusChanged: case evtStatusChanged = <-chStatusChanged:
ac := types.AcctInfoMap.GetAccount(evtStatusChanged.Account) ac := types.AcctInfoMap.GetAccount(evtStatusChanged.Account)
types.AcctInfoMap.UpsertAccount(evtStatusChanged.OrgId, ac.RoleId, evtStatusChanged.Account, ac.IsOrgAdmin, types.AcctStatus(int(evtStatusChanged.Status.Uint64()))) types.AcctInfoMap.UpsertAccount(evtStatusChanged.OrgId, ac.RoleId, evtStatusChanged.Account, ac.IsOrgAdmin, types.AcctStatus(int(evtStatusChanged.Status.Uint64())))
case <-p.acctChan:
log.Info("quit account contract watch")
return
} }
} }
} }
@ -829,6 +844,9 @@ func (p *PermissionCtrl) manageRolePermissions() {
} else { } else {
log.Error("Revoke role - cache is missing role", "org", evtRoleRevoked.OrgId, "role", evtRoleRevoked.RoleId) log.Error("Revoke role - cache is missing role", "org", evtRoleRevoked.OrgId, "role", evtRoleRevoked.RoleId)
} }
case <-p.roleChan:
log.Info("quit role contract watch")
return
} }
} }
} }