github.com/RobustRoundRobin/quorum@v20.10.0+incompatible/permission/permission.go (about) 1 package permission 2 3 import ( 4 "crypto/ecdsa" 5 "encoding/json" 6 "fmt" 7 "io/ioutil" 8 "math/big" 9 "os" 10 "path/filepath" 11 "reflect" 12 "sync" 13 "time" 14 15 "github.com/ethereum/go-ethereum/accounts/abi/bind" 16 "github.com/ethereum/go-ethereum/common" 17 "github.com/ethereum/go-ethereum/core" 18 "github.com/ethereum/go-ethereum/core/types" 19 "github.com/ethereum/go-ethereum/eth" 20 "github.com/ethereum/go-ethereum/ethclient" 21 "github.com/ethereum/go-ethereum/event" 22 "github.com/ethereum/go-ethereum/log" 23 "github.com/ethereum/go-ethereum/node" 24 "github.com/ethereum/go-ethereum/p2p" 25 "github.com/ethereum/go-ethereum/p2p/enode" 26 "github.com/ethereum/go-ethereum/params" 27 pbind "github.com/ethereum/go-ethereum/permission/bind" 28 "github.com/ethereum/go-ethereum/raft" 29 "github.com/ethereum/go-ethereum/rpc" 30 ) 31 32 type NodeOperation uint8 33 34 const ( 35 NodeAdd NodeOperation = iota 36 NodeDelete 37 ) 38 39 type PermissionCtrl struct { 40 node *node.Node 41 ethClnt bind.ContractBackend 42 eth *eth.Ethereum 43 key *ecdsa.PrivateKey 44 dataDir string 45 permUpgr *pbind.PermUpgr 46 permInterf *pbind.PermInterface 47 permNode *pbind.NodeManager 48 permAcct *pbind.AcctManager 49 permRole *pbind.RoleManager 50 permOrg *pbind.OrgManager 51 permConfig *types.PermissionConfig 52 53 startWaitGroup *sync.WaitGroup // waitgroup to make sure all dependencies are ready before we start the service 54 stopFeed event.Feed // broadcasting stopEvent when service is being stopped 55 errorChan chan error // channel to capture error when starting aysnc 56 57 mux sync.Mutex 58 } 59 60 // to signal all watches when service is stopped 61 type stopEvent struct { 62 } 63 64 // function reads the permissions config file passed and populates the 65 // config structure accordingly 66 func ParsePermissionConfig(dir string) (types.PermissionConfig, error) { 67 fullPath := filepath.Join(dir, params.PERMISSION_MODEL_CONFIG) 68 f, err := os.Open(fullPath) 69 if err != nil { 70 log.Error("can't open file", "file", fullPath, "error", err) 71 return types.PermissionConfig{}, err 72 } 73 defer func() { 74 _ = f.Close() 75 }() 76 77 var permConfig types.PermissionConfig 78 blob, err := ioutil.ReadFile(fullPath) 79 if err != nil { 80 log.Error("error reading file", "err", err, "file", fullPath) 81 } 82 83 err = json.Unmarshal(blob, &permConfig) 84 if err != nil { 85 log.Error("error unmarshalling the file", "err", err, "file", fullPath) 86 } 87 88 if len(permConfig.Accounts) == 0 { 89 return types.PermissionConfig{}, fmt.Errorf("no accounts given in %s. Network cannot boot up", params.PERMISSION_MODEL_CONFIG) 90 } 91 if permConfig.SubOrgDepth.Cmp(big.NewInt(0)) == 0 || permConfig.SubOrgBreadth.Cmp(big.NewInt(0)) == 0 { 92 return types.PermissionConfig{}, fmt.Errorf("sub org breadth depth not passed in %s. Network cannot boot up", params.PERMISSION_MODEL_CONFIG) 93 } 94 if permConfig.IsEmpty() { 95 return types.PermissionConfig{}, fmt.Errorf("missing contract addresses in %s", params.PERMISSION_MODEL_CONFIG) 96 } 97 98 return permConfig, nil 99 } 100 101 // Create a service instance for permissioning 102 // 103 // Permission Service depends on the following: 104 // 1. EthService to be ready 105 // 2. Downloader to sync up blocks 106 // 3. InProc RPC server to be ready 107 func NewQuorumPermissionCtrl(stack *node.Node, pconfig *types.PermissionConfig) (*PermissionCtrl, error) { 108 wg := &sync.WaitGroup{} 109 wg.Add(1) 110 p := &PermissionCtrl{ 111 node: stack, 112 key: stack.GetNodeKey(), 113 dataDir: stack.DataDir(), 114 permConfig: pconfig, 115 startWaitGroup: wg, 116 errorChan: make(chan error), 117 } 118 119 stopChan, stopSubscription := p.subscribeStopEvent() 120 inProcRPCServerSub := stack.EventMux().Subscribe(rpc.InProcServerReadyEvent{}) 121 log.Debug("permission service: waiting for InProcRPC Server") 122 123 go func(_wg *sync.WaitGroup) { 124 defer func(start time.Time) { 125 log.Debug("permission service: InProcRPC server is ready", "took", time.Since(start)) 126 stopSubscription.Unsubscribe() 127 inProcRPCServerSub.Unsubscribe() 128 _wg.Done() 129 }(time.Now()) 130 select { 131 case <-inProcRPCServerSub.Chan(): 132 case <-stopChan: 133 } 134 }(wg) // wait for inproc RPC to be ready 135 return p, nil 136 } 137 138 func (p *PermissionCtrl) bindContract(contractInstance interface{}, bindFunc func() (interface{}, error)) error { 139 element := reflect.ValueOf(contractInstance).Elem() 140 instance, err := bindFunc() 141 if err != nil { 142 return err 143 } 144 element.Set(reflect.ValueOf(instance)) 145 return nil 146 } 147 148 // This is to make sure all contract instances are ready and initialized 149 // 150 // Required to be call after standard service start lifecycle 151 func (p *PermissionCtrl) AfterStart() error { 152 log.Debug("permission service: binding contracts") 153 err := <-p.errorChan // capture any error happened during asyncStart. Also wait here if asyncStart is not yet finish 154 if err != nil { 155 return err 156 } 157 if err := p.bindContract(&p.permUpgr, func() (interface{}, error) { return pbind.NewPermUpgr(p.permConfig.UpgrdAddress, p.ethClnt) }); err != nil { 158 return err 159 } 160 if err := p.bindContract(&p.permInterf, func() (interface{}, error) { return pbind.NewPermInterface(p.permConfig.InterfAddress, p.ethClnt) }); err != nil { 161 return err 162 } 163 if err := p.bindContract(&p.permAcct, func() (interface{}, error) { return pbind.NewAcctManager(p.permConfig.AccountAddress, p.ethClnt) }); err != nil { 164 return err 165 } 166 if err := p.bindContract(&p.permNode, func() (interface{}, error) { return pbind.NewNodeManager(p.permConfig.NodeAddress, p.ethClnt) }); err != nil { 167 return err 168 } 169 if err := p.bindContract(&p.permRole, func() (interface{}, error) { return pbind.NewRoleManager(p.permConfig.RoleAddress, p.ethClnt) }); err != nil { 170 return err 171 } 172 if err := p.bindContract(&p.permOrg, func() (interface{}, error) { return pbind.NewOrgManager(p.permConfig.OrgAddress, p.ethClnt) }); err != nil { 173 return err 174 } 175 176 // populate the initial list of permissioned nodes and account accesses 177 if err := p.populateInitPermissions(params.DEFAULT_ORGCACHE_SIZE, params.DEFAULT_ROLECACHE_SIZE, 178 params.DEFAULT_NODECACHE_SIZE, params.DEFAULT_ACCOUNTCACHE_SIZE); err != nil { 179 return fmt.Errorf("populateInitPermissions failed: %v", err) 180 } 181 182 // set the default access to ReadOnly 183 types.SetDefaults(p.permConfig.NwAdminRole, p.permConfig.OrgAdminRole) 184 185 for _, f := range []func() error{ 186 p.monitorQIP714Block, // monitor block number to activate new permissions controls 187 p.manageOrgPermissions, // monitor org management related events 188 p.manageNodePermissions, // monitor org level node management events 189 p.manageRolePermissions, // monitor org level role management events 190 p.manageAccountPermissions, // monitor org level account management events 191 } { 192 if err := f(); err != nil { 193 return err 194 } 195 } 196 197 log.Info("permission service: is now ready") 198 199 return nil 200 } 201 202 // start service asynchronously due to dependencies 203 func (p *PermissionCtrl) asyncStart() { 204 var ethereum *eth.Ethereum 205 // will be blocked here until node is up 206 if err := p.node.Service(ðereum); err != nil { 207 p.errorChan <- fmt.Errorf("dependent ethereum service not started") 208 return 209 } 210 defer func() { 211 p.errorChan <- nil 212 }() 213 // for cases where the node is joining an existing network, permission service 214 // can be brought up only after block syncing is complete. This function 215 // waits for block syncing before the starting permissions 216 p.startWaitGroup.Add(1) 217 go func(_wg *sync.WaitGroup) { 218 log.Debug("permission service: waiting for downloader") 219 stopChan, stopSubscription := p.subscribeStopEvent() 220 pollingTicker := time.NewTicker(10 * time.Millisecond) 221 defer func(start time.Time) { 222 log.Debug("permission service: downloader completed", "took", time.Since(start)) 223 stopSubscription.Unsubscribe() 224 pollingTicker.Stop() 225 _wg.Done() 226 }(time.Now()) 227 for { 228 select { 229 case <-pollingTicker.C: 230 if types.GetSyncStatus() && !ethereum.Downloader().Synchronising() { 231 return 232 } 233 case <-stopChan: 234 return 235 } 236 } 237 }(p.startWaitGroup) // wait for downloader to sync if any 238 239 log.Debug("permission service: waiting for all dependencies to be ready") 240 p.startWaitGroup.Wait() 241 client, err := p.node.Attach() 242 if err != nil { 243 p.errorChan <- fmt.Errorf("unable to create rpc client: %v", err) 244 return 245 } 246 p.ethClnt = ethclient.NewClient(client) 247 p.eth = ethereum 248 } 249 250 func (p *PermissionCtrl) Start(srvr *p2p.Server) error { 251 log.Debug("permission service: starting") 252 go func() { 253 log.Debug("permission service: starting async") 254 p.asyncStart() 255 }() 256 return nil 257 } 258 259 func (p *PermissionCtrl) APIs() []rpc.API { 260 return []rpc.API{ 261 { 262 Namespace: "quorumPermission", 263 Version: "1.0", 264 Service: NewQuorumControlsAPI(p), 265 Public: true, 266 }, 267 } 268 } 269 270 func (p *PermissionCtrl) Protocols() []p2p.Protocol { 271 return []p2p.Protocol{} 272 } 273 274 func (p *PermissionCtrl) Stop() error { 275 log.Info("permission service: stopping") 276 p.stopFeed.Send(stopEvent{}) 277 log.Info("permission service: stopped") 278 return nil 279 } 280 281 // monitors QIP714Block and set default access 282 func (p *PermissionCtrl) monitorQIP714Block() error { 283 // if QIP714block is not given, set the default access 284 // to readonly 285 if p.eth.BlockChain().Config().QIP714Block == nil { 286 types.SetDefaultAccess() 287 return nil 288 } 289 //QIP714block is given, monitor block count 290 go func() { 291 chainHeadCh := make(chan core.ChainHeadEvent, 1) 292 headSub := p.eth.BlockChain().SubscribeChainHeadEvent(chainHeadCh) 293 defer headSub.Unsubscribe() 294 stopChan, stopSubscription := p.subscribeStopEvent() 295 defer stopSubscription.Unsubscribe() 296 for { 297 select { 298 case head := <-chainHeadCh: 299 if p.eth.BlockChain().Config().IsQIP714(head.Block.Number()) { 300 types.SetDefaultAccess() 301 return 302 } 303 case <-stopChan: 304 return 305 } 306 } 307 }() 308 return nil 309 } 310 311 // monitors org management related events happening via smart contracts 312 // and updates cache accordingly 313 func (p *PermissionCtrl) manageOrgPermissions() error { 314 chPendingApproval := make(chan *pbind.OrgManagerOrgPendingApproval, 1) 315 chOrgApproved := make(chan *pbind.OrgManagerOrgApproved, 1) 316 chOrgSuspended := make(chan *pbind.OrgManagerOrgSuspended, 1) 317 chOrgReactivated := make(chan *pbind.OrgManagerOrgSuspensionRevoked, 1) 318 319 opts := &bind.WatchOpts{} 320 var blockNumber uint64 = 1 321 opts.Start = &blockNumber 322 323 if _, err := p.permOrg.OrgManagerFilterer.WatchOrgPendingApproval(opts, chPendingApproval); err != nil { 324 return fmt.Errorf("failed WatchNodePendingApproval: %v", err) 325 } 326 327 if _, err := p.permOrg.OrgManagerFilterer.WatchOrgApproved(opts, chOrgApproved); err != nil { 328 return fmt.Errorf("failed WatchNodePendingApproval: %v", err) 329 } 330 331 if _, err := p.permOrg.OrgManagerFilterer.WatchOrgSuspended(opts, chOrgSuspended); err != nil { 332 return fmt.Errorf("failed WatchNodePendingApproval: %v", err) 333 } 334 335 if _, err := p.permOrg.OrgManagerFilterer.WatchOrgSuspensionRevoked(opts, chOrgReactivated); err != nil { 336 return fmt.Errorf("failed WatchNodePendingApproval: %v", err) 337 } 338 339 go func() { 340 stopChan, stopSubscription := p.subscribeStopEvent() 341 defer stopSubscription.Unsubscribe() 342 for { 343 select { 344 case evtPendingApproval := <-chPendingApproval: 345 types.OrgInfoMap.UpsertOrg(evtPendingApproval.OrgId, evtPendingApproval.PorgId, evtPendingApproval.UltParent, evtPendingApproval.Level, types.OrgStatus(evtPendingApproval.Status.Uint64())) 346 347 case evtOrgApproved := <-chOrgApproved: 348 types.OrgInfoMap.UpsertOrg(evtOrgApproved.OrgId, evtOrgApproved.PorgId, evtOrgApproved.UltParent, evtOrgApproved.Level, types.OrgApproved) 349 350 case evtOrgSuspended := <-chOrgSuspended: 351 types.OrgInfoMap.UpsertOrg(evtOrgSuspended.OrgId, evtOrgSuspended.PorgId, evtOrgSuspended.UltParent, evtOrgSuspended.Level, types.OrgSuspended) 352 353 case evtOrgReactivated := <-chOrgReactivated: 354 types.OrgInfoMap.UpsertOrg(evtOrgReactivated.OrgId, evtOrgReactivated.PorgId, evtOrgReactivated.UltParent, evtOrgReactivated.Level, types.OrgApproved) 355 case <-stopChan: 356 log.Info("quit org contract watch") 357 return 358 } 359 } 360 }() 361 return nil 362 } 363 364 func (p *PermissionCtrl) subscribeStopEvent() (chan stopEvent, event.Subscription) { 365 c := make(chan stopEvent) 366 s := p.stopFeed.Subscribe(c) 367 return c, s 368 } 369 370 // Monitors node management events and updates cache accordingly 371 func (p *PermissionCtrl) manageNodePermissions() error { 372 chNodeApproved := make(chan *pbind.NodeManagerNodeApproved, 1) 373 chNodeProposed := make(chan *pbind.NodeManagerNodeProposed, 1) 374 chNodeDeactivated := make(chan *pbind.NodeManagerNodeDeactivated, 1) 375 chNodeActivated := make(chan *pbind.NodeManagerNodeActivated, 1) 376 chNodeBlacklisted := make(chan *pbind.NodeManagerNodeBlacklisted) 377 chNodeRecoveryInit := make(chan *pbind.NodeManagerNodeRecoveryInitiated, 1) 378 chNodeRecoveryDone := make(chan *pbind.NodeManagerNodeRecoveryCompleted, 1) 379 380 opts := &bind.WatchOpts{} 381 var blockNumber uint64 = 1 382 opts.Start = &blockNumber 383 384 if _, err := p.permNode.NodeManagerFilterer.WatchNodeApproved(opts, chNodeApproved); err != nil { 385 return fmt.Errorf("failed WatchNodeApproved: %v", err) 386 } 387 388 if _, err := p.permNode.NodeManagerFilterer.WatchNodeProposed(opts, chNodeProposed); err != nil { 389 return fmt.Errorf("failed WatchNodeProposed: %v", err) 390 } 391 392 if _, err := p.permNode.NodeManagerFilterer.WatchNodeDeactivated(opts, chNodeDeactivated); err != nil { 393 return fmt.Errorf("failed NodeDeactivated: %v", err) 394 } 395 if _, err := p.permNode.NodeManagerFilterer.WatchNodeActivated(opts, chNodeActivated); err != nil { 396 return fmt.Errorf("failed WatchNodeActivated: %v", err) 397 } 398 399 if _, err := p.permNode.NodeManagerFilterer.WatchNodeBlacklisted(opts, chNodeBlacklisted); err != nil { 400 return fmt.Errorf("failed NodeBlacklisting: %v", err) 401 } 402 403 if _, err := p.permNode.NodeManagerFilterer.WatchNodeRecoveryInitiated(opts, chNodeRecoveryInit); err != nil { 404 return fmt.Errorf("failed NodeRecoveryInitiated: %v", err) 405 } 406 407 if _, err := p.permNode.NodeManagerFilterer.WatchNodeRecoveryCompleted(opts, chNodeRecoveryDone); err != nil { 408 return fmt.Errorf("failed NodeRecoveryCompleted: %v", err) 409 } 410 411 go func() { 412 stopChan, stopSubscription := p.subscribeStopEvent() 413 defer stopSubscription.Unsubscribe() 414 for { 415 select { 416 case evtNodeApproved := <-chNodeApproved: 417 p.updatePermissionedNodes(evtNodeApproved.EnodeId, NodeAdd) 418 types.NodeInfoMap.UpsertNode(evtNodeApproved.OrgId, evtNodeApproved.EnodeId, types.NodeApproved) 419 420 case evtNodeProposed := <-chNodeProposed: 421 types.NodeInfoMap.UpsertNode(evtNodeProposed.OrgId, evtNodeProposed.EnodeId, types.NodePendingApproval) 422 423 case evtNodeDeactivated := <-chNodeDeactivated: 424 p.updatePermissionedNodes(evtNodeDeactivated.EnodeId, NodeDelete) 425 types.NodeInfoMap.UpsertNode(evtNodeDeactivated.OrgId, evtNodeDeactivated.EnodeId, types.NodeDeactivated) 426 427 case evtNodeActivated := <-chNodeActivated: 428 p.updatePermissionedNodes(evtNodeActivated.EnodeId, NodeAdd) 429 types.NodeInfoMap.UpsertNode(evtNodeActivated.OrgId, evtNodeActivated.EnodeId, types.NodeApproved) 430 431 case evtNodeBlacklisted := <-chNodeBlacklisted: 432 types.NodeInfoMap.UpsertNode(evtNodeBlacklisted.OrgId, evtNodeBlacklisted.EnodeId, types.NodeBlackListed) 433 p.updateDisallowedNodes(evtNodeBlacklisted.EnodeId, NodeAdd) 434 p.updatePermissionedNodes(evtNodeBlacklisted.EnodeId, NodeDelete) 435 436 case evtNodeRecoveryInit := <-chNodeRecoveryInit: 437 types.NodeInfoMap.UpsertNode(evtNodeRecoveryInit.OrgId, evtNodeRecoveryInit.EnodeId, types.NodeRecoveryInitiated) 438 439 case evtNodeRecoveryDone := <-chNodeRecoveryDone: 440 types.NodeInfoMap.UpsertNode(evtNodeRecoveryDone.OrgId, evtNodeRecoveryDone.EnodeId, types.NodeApproved) 441 p.updateDisallowedNodes(evtNodeRecoveryDone.EnodeId, NodeDelete) 442 p.updatePermissionedNodes(evtNodeRecoveryDone.EnodeId, NodeAdd) 443 444 case <-stopChan: 445 log.Info("quit node contract watch") 446 return 447 } 448 } 449 }() 450 return nil 451 } 452 453 // adds or deletes and entry from a given file 454 func (p *PermissionCtrl) updateFile(fileName, enodeId string, operation NodeOperation, createFile bool) { 455 // Load the nodes from the config file 456 var nodeList []string 457 index := 0 458 // if createFile is false means the file is already existing. read the file 459 if !createFile { 460 blob, err := ioutil.ReadFile(fileName) 461 if err != nil && !createFile { 462 log.Error("Failed to access the file", "fileName", fileName, "err", err) 463 return 464 } 465 466 if err := json.Unmarshal(blob, &nodeList); err != nil { 467 log.Error("Failed to load nodes list from file", "fileName", fileName, "err", err) 468 return 469 } 470 471 // logic to update the permissioned-nodes.json file based on action 472 473 recExists := false 474 for i, eid := range nodeList { 475 if eid == enodeId { 476 index = i 477 recExists = true 478 break 479 } 480 } 481 if (operation == NodeAdd && recExists) || (operation == NodeDelete && !recExists) { 482 return 483 } 484 } 485 if operation == NodeAdd { 486 nodeList = append(nodeList, enodeId) 487 } else { 488 nodeList = append(nodeList[:index], nodeList[index+1:]...) 489 } 490 blob, _ := json.Marshal(nodeList) 491 492 p.mux.Lock() 493 defer p.mux.Unlock() 494 495 if err := ioutil.WriteFile(fileName, blob, 0644); err != nil { 496 log.Error("Error writing new node info to file", "fileName", fileName, "err", err) 497 } 498 } 499 500 // updates node information in the permissioned-nodes.json file based on node 501 // management activities in smart contract 502 func (p *PermissionCtrl) updatePermissionedNodes(enodeId string, operation NodeOperation) { 503 log.Debug("updatePermissionedNodes", "DataDir", p.dataDir, "file", params.PERMISSIONED_CONFIG) 504 505 path := filepath.Join(p.dataDir, params.PERMISSIONED_CONFIG) 506 if _, err := os.Stat(path); err != nil { 507 log.Error("Read Error for permissioned-nodes.json file. This is because 'permissioned' flag is specified but no permissioned-nodes.json file is present", "err", err) 508 return 509 } 510 511 p.updateFile(path, enodeId, operation, false) 512 if operation == NodeDelete { 513 p.disconnectNode(enodeId) 514 } 515 } 516 517 //this function populates the black listed node information into the disallowed-nodes.json file 518 func (p *PermissionCtrl) updateDisallowedNodes(url string, operation NodeOperation) { 519 log.Debug("updateDisallowedNodes", "DataDir", p.dataDir, "file", params.BLACKLIST_CONFIG) 520 521 fileExists := true 522 path := filepath.Join(p.dataDir, params.BLACKLIST_CONFIG) 523 // Check if the file is existing. If the file is not existing create the file 524 if _, err := os.Stat(path); err != nil { 525 log.Error("Read Error for disallowed-nodes.json file", "err", err) 526 if _, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, 0644); err != nil { 527 log.Error("Failed to create disallowed-nodes.json file", "err", err) 528 return 529 } 530 fileExists = false 531 } 532 533 if fileExists { 534 p.updateFile(path, url, operation, false) 535 } else { 536 p.updateFile(path, url, operation, true) 537 } 538 } 539 540 // Monitors account access related events and updates the cache accordingly 541 func (p *PermissionCtrl) manageAccountPermissions() error { 542 chAccessModified := make(chan *pbind.AcctManagerAccountAccessModified) 543 chAccessRevoked := make(chan *pbind.AcctManagerAccountAccessRevoked) 544 chStatusChanged := make(chan *pbind.AcctManagerAccountStatusChanged) 545 546 opts := &bind.WatchOpts{} 547 var blockNumber uint64 = 1 548 opts.Start = &blockNumber 549 550 if _, err := p.permAcct.AcctManagerFilterer.WatchAccountAccessModified(opts, chAccessModified); err != nil { 551 return fmt.Errorf("failed AccountAccessModified: %v", err) 552 } 553 554 if _, err := p.permAcct.AcctManagerFilterer.WatchAccountAccessRevoked(opts, chAccessRevoked); err != nil { 555 return fmt.Errorf("failed AccountAccessRevoked: %v", err) 556 } 557 558 if _, err := p.permAcct.AcctManagerFilterer.WatchAccountStatusChanged(opts, chStatusChanged); err != nil { 559 return fmt.Errorf("failed AccountStatusChanged: %v", err) 560 } 561 562 go func() { 563 stopChan, stopSubscription := p.subscribeStopEvent() 564 defer stopSubscription.Unsubscribe() 565 for { 566 select { 567 case evtAccessModified := <-chAccessModified: 568 types.AcctInfoMap.UpsertAccount(evtAccessModified.OrgId, evtAccessModified.RoleId, evtAccessModified.Account, evtAccessModified.OrgAdmin, types.AcctStatus(int(evtAccessModified.Status.Uint64()))) 569 570 case evtAccessRevoked := <-chAccessRevoked: 571 types.AcctInfoMap.UpsertAccount(evtAccessRevoked.OrgId, evtAccessRevoked.RoleId, evtAccessRevoked.Account, evtAccessRevoked.OrgAdmin, types.AcctActive) 572 573 case evtStatusChanged := <-chStatusChanged: 574 if ac, err := types.AcctInfoMap.GetAccount(evtStatusChanged.Account); ac != nil { 575 types.AcctInfoMap.UpsertAccount(evtStatusChanged.OrgId, ac.RoleId, evtStatusChanged.Account, ac.IsOrgAdmin, types.AcctStatus(int(evtStatusChanged.Status.Uint64()))) 576 } else { 577 log.Info("error fetching account information", "err", err) 578 } 579 case <-stopChan: 580 log.Info("quit account contract watch") 581 return 582 } 583 } 584 }() 585 return nil 586 } 587 588 // Disconnect the node from the network 589 func (p *PermissionCtrl) disconnectNode(enodeId string) { 590 if p.eth.BlockChain().Config().Istanbul == nil && p.eth.BlockChain().Config().Clique == nil { 591 var raftService *raft.RaftService 592 if err := p.node.Service(&raftService); err == nil { 593 raftApi := raft.NewPublicRaftAPI(raftService) 594 595 //get the raftId for the given enodeId 596 raftId, err := raftApi.GetRaftId(enodeId) 597 if err == nil { 598 raftApi.RemovePeer(raftId) 599 } else { 600 log.Error("failed to get raft id", "err", err, "enodeId", enodeId) 601 } 602 } 603 } else { 604 // Istanbul or clique - disconnect the peer 605 server := p.node.Server() 606 if server != nil { 607 node, err := enode.ParseV4(enodeId) 608 if err == nil { 609 server.RemovePeer(node) 610 } else { 611 log.Error("failed parse node id", "err", err, "enodeId", enodeId) 612 } 613 } 614 } 615 616 } 617 618 func (p *PermissionCtrl) instantiateCache(orgCacheSize, roleCacheSize, nodeCacheSize, accountCacheSize int) { 619 // instantiate the cache objects for permissions 620 types.OrgInfoMap = types.NewOrgCache(orgCacheSize) 621 types.OrgInfoMap.PopulateCacheFunc(p.populateOrgToCache) 622 623 types.RoleInfoMap = types.NewRoleCache(roleCacheSize) 624 types.RoleInfoMap.PopulateCacheFunc(p.populateRoleToCache) 625 626 types.NodeInfoMap = types.NewNodeCache(nodeCacheSize) 627 types.NodeInfoMap.PopulateCacheFunc(p.populateNodeCache) 628 types.NodeInfoMap.PopulateValidateFunc(p.populateNodeCacheAndValidate) 629 630 types.AcctInfoMap = types.NewAcctCache(accountCacheSize) 631 types.AcctInfoMap.PopulateCacheFunc(p.populateAccountToCache) 632 } 633 634 // Thus function checks if the initial network boot up status and if no 635 // populates permissions model with details from permission-config.json 636 func (p *PermissionCtrl) populateInitPermissions(orgCacheSize, roleCacheSize, nodeCacheSize, accountCacheSize int) error { 637 auth := bind.NewKeyedTransactor(p.key) 638 permInterfSession := &pbind.PermInterfaceSession{ 639 Contract: p.permInterf, 640 CallOpts: bind.CallOpts{ 641 Pending: true, 642 }, 643 TransactOpts: bind.TransactOpts{ 644 From: auth.From, 645 Signer: auth.Signer, 646 GasLimit: 47000000, 647 GasPrice: big.NewInt(0), 648 }, 649 } 650 651 p.instantiateCache(orgCacheSize, roleCacheSize, nodeCacheSize, accountCacheSize) 652 653 networkInitialized, err := permInterfSession.GetNetworkBootStatus() 654 if err != nil { 655 // handle the scenario of no contract code. 656 log.Warn("Failed to retrieve network boot status ", "err", err) 657 return err 658 } 659 660 if !networkInitialized { 661 if err := p.bootupNetwork(permInterfSession); err != nil { 662 return err 663 } 664 } else { 665 //populate orgs, nodes, roles and accounts from contract 666 for _, f := range []func(auth *bind.TransactOpts) error{ 667 p.populateOrgsFromContract, 668 p.populateNodesFromContract, 669 p.populateRolesFromContract, 670 p.populateAccountsFromContract, 671 } { 672 if err := f(auth); err != nil { 673 return err 674 } 675 } 676 } 677 return nil 678 } 679 680 // initialize the permissions model and populate initial values 681 func (p *PermissionCtrl) bootupNetwork(permInterfSession *pbind.PermInterfaceSession) error { 682 if _, err := permInterfSession.SetPolicy(p.permConfig.NwAdminOrg, p.permConfig.NwAdminRole, p.permConfig.OrgAdminRole); err != nil { 683 log.Error("bootupNetwork SetPolicy failed", "err", err) 684 return err 685 } 686 if _, err := permInterfSession.Init(p.permConfig.SubOrgBreadth, p.permConfig.SubOrgDepth); err != nil { 687 log.Error("bootupNetwork init failed", "err", err) 688 return err 689 } 690 691 types.OrgInfoMap.UpsertOrg(p.permConfig.NwAdminOrg, "", p.permConfig.NwAdminOrg, big.NewInt(1), types.OrgApproved) 692 types.RoleInfoMap.UpsertRole(p.permConfig.NwAdminOrg, p.permConfig.NwAdminRole, true, true, types.FullAccess, true) 693 // populate the initial node list from static-nodes.json 694 if err := p.populateStaticNodesToContract(permInterfSession); err != nil { 695 return err 696 } 697 // populate initial account access to full access 698 if err := p.populateInitAccountAccess(permInterfSession); err != nil { 699 return err 700 } 701 702 // update network status to boot completed 703 if err := p.updateNetworkStatus(permInterfSession); err != nil { 704 log.Error("failed to updated network boot status", "error", err) 705 return err 706 } 707 return nil 708 } 709 710 // populates the account access details from contract into cache 711 func (p *PermissionCtrl) populateAccountsFromContract(auth *bind.TransactOpts) error { 712 //populate accounts 713 permAcctSession := &pbind.AcctManagerSession{ 714 Contract: p.permAcct, 715 CallOpts: bind.CallOpts{ 716 Pending: true, 717 }, 718 } 719 720 if numberOfRoles, err := permAcctSession.GetNumberOfAccounts(); err == nil { 721 iOrgNum := numberOfRoles.Uint64() 722 for k := uint64(0); k < iOrgNum; k++ { 723 if addr, org, role, status, orgAdmin, err := permAcctSession.GetAccountDetailsFromIndex(big.NewInt(int64(k))); err == nil { 724 types.AcctInfoMap.UpsertAccount(org, role, addr, orgAdmin, types.AcctStatus(int(status.Int64()))) 725 } 726 } 727 } else { 728 return err 729 } 730 return nil 731 } 732 733 // populates the role details from contract into cache 734 func (p *PermissionCtrl) populateRolesFromContract(auth *bind.TransactOpts) error { 735 //populate roles 736 permRoleSession := &pbind.RoleManagerSession{ 737 Contract: p.permRole, 738 CallOpts: bind.CallOpts{ 739 Pending: true, 740 }, 741 } 742 if numberOfRoles, err := permRoleSession.GetNumberOfRoles(); err == nil { 743 iOrgNum := numberOfRoles.Uint64() 744 for k := uint64(0); k < iOrgNum; k++ { 745 if roleStruct, err := permRoleSession.GetRoleDetailsFromIndex(big.NewInt(int64(k))); err == nil { 746 types.RoleInfoMap.UpsertRole(roleStruct.OrgId, roleStruct.RoleId, roleStruct.Voter, roleStruct.Admin, types.AccessType(int(roleStruct.AccessType.Int64())), roleStruct.Active) 747 } 748 } 749 750 } else { 751 return err 752 } 753 return nil 754 } 755 756 // populates the node details from contract into cache 757 func (p *PermissionCtrl) populateNodesFromContract(auth *bind.TransactOpts) error { 758 //populate nodes 759 permNodeSession := &pbind.NodeManagerSession{ 760 Contract: p.permNode, 761 CallOpts: bind.CallOpts{ 762 Pending: true, 763 }, 764 } 765 if numberOfNodes, err := permNodeSession.GetNumberOfNodes(); err == nil { 766 iOrgNum := numberOfNodes.Uint64() 767 for k := uint64(0); k < iOrgNum; k++ { 768 if nodeStruct, err := permNodeSession.GetNodeDetailsFromIndex(big.NewInt(int64(k))); err == nil { 769 types.NodeInfoMap.UpsertNode(nodeStruct.OrgId, nodeStruct.EnodeId, types.NodeStatus(int(nodeStruct.NodeStatus.Int64()))) 770 } 771 } 772 } else { 773 return err 774 } 775 return nil 776 } 777 778 // populates the org details from contract into cache 779 func (p *PermissionCtrl) populateOrgsFromContract(auth *bind.TransactOpts) error { 780 //populate orgs 781 permOrgSession := &pbind.OrgManagerSession{ 782 Contract: p.permOrg, 783 CallOpts: bind.CallOpts{ 784 Pending: true, 785 }, 786 } 787 if numberOfOrgs, err := permOrgSession.GetNumberOfOrgs(); err == nil { 788 iOrgNum := numberOfOrgs.Uint64() 789 for k := uint64(0); k < iOrgNum; k++ { 790 if orgId, porgId, ultParent, level, status, err := permOrgSession.GetOrgInfo(big.NewInt(int64(k))); err == nil { 791 types.OrgInfoMap.UpsertOrg(orgId, porgId, ultParent, level, types.OrgStatus(int(status.Int64()))) 792 } 793 } 794 } else { 795 return err 796 } 797 return nil 798 } 799 800 // Reads the node list from static-nodes.json and populates into the contract 801 func (p *PermissionCtrl) populateStaticNodesToContract(permissionsSession *pbind.PermInterfaceSession) error { 802 nodes := p.node.Server().Config.StaticNodes 803 for _, node := range nodes { 804 _, err := permissionsSession.AddAdminNode(node.String()) 805 if err != nil { 806 log.Warn("Failed to propose node", "err", err, "enode", node.EnodeID()) 807 return err 808 } 809 types.NodeInfoMap.UpsertNode(p.permConfig.NwAdminOrg, node.String(), 2) 810 } 811 return nil 812 } 813 814 // Invokes the initAccounts function of smart contract to set the initial 815 // set of accounts access to full access 816 func (p *PermissionCtrl) populateInitAccountAccess(permissionsSession *pbind.PermInterfaceSession) error { 817 for _, a := range p.permConfig.Accounts { 818 _, er := permissionsSession.AddAdminAccount(a) 819 if er != nil { 820 log.Warn("Error adding permission initial account list", "err", er, "account", a) 821 return er 822 } 823 types.AcctInfoMap.UpsertAccount(p.permConfig.NwAdminOrg, p.permConfig.NwAdminRole, a, true, 2) 824 } 825 return nil 826 } 827 828 // updates network boot status to true 829 func (p *PermissionCtrl) updateNetworkStatus(permissionsSession *pbind.PermInterfaceSession) error { 830 _, err := permissionsSession.UpdateNetworkBootStatus() 831 if err != nil { 832 log.Warn("Failed to udpate network boot status ", "err", err) 833 return err 834 } 835 return nil 836 } 837 838 // monitors role management related events and updated cache 839 func (p *PermissionCtrl) manageRolePermissions() error { 840 chRoleCreated := make(chan *pbind.RoleManagerRoleCreated, 1) 841 chRoleRevoked := make(chan *pbind.RoleManagerRoleRevoked, 1) 842 843 opts := &bind.WatchOpts{} 844 var blockNumber uint64 = 1 845 opts.Start = &blockNumber 846 847 if _, err := p.permRole.RoleManagerFilterer.WatchRoleCreated(opts, chRoleCreated); err != nil { 848 return fmt.Errorf("failed WatchRoleCreated: %v", err) 849 } 850 851 if _, err := p.permRole.RoleManagerFilterer.WatchRoleRevoked(opts, chRoleRevoked); err != nil { 852 return fmt.Errorf("failed WatchRoleRemoved: %v", err) 853 } 854 855 go func() { 856 stopChan, stopSubscription := p.subscribeStopEvent() 857 defer stopSubscription.Unsubscribe() 858 for { 859 select { 860 case evtRoleCreated := <-chRoleCreated: 861 types.RoleInfoMap.UpsertRole(evtRoleCreated.OrgId, evtRoleCreated.RoleId, evtRoleCreated.IsVoter, evtRoleCreated.IsAdmin, types.AccessType(int(evtRoleCreated.BaseAccess.Uint64())), true) 862 863 case evtRoleRevoked := <-chRoleRevoked: 864 if r, _ := types.RoleInfoMap.GetRole(evtRoleRevoked.OrgId, evtRoleRevoked.RoleId); r != nil { 865 types.RoleInfoMap.UpsertRole(evtRoleRevoked.OrgId, evtRoleRevoked.RoleId, r.IsVoter, r.IsAdmin, r.Access, false) 866 } else { 867 log.Error("Revoke role - cache is missing role", "org", evtRoleRevoked.OrgId, "role", evtRoleRevoked.RoleId) 868 } 869 case <-stopChan: 870 log.Info("quit role contract watch") 871 return 872 } 873 } 874 }() 875 return nil 876 } 877 878 // getter to get an account record from the contract 879 func (p *PermissionCtrl) populateAccountToCache(acctId common.Address) (*types.AccountInfo, error) { 880 permAcctInterface := &pbind.AcctManagerSession{ 881 Contract: p.permAcct, 882 CallOpts: bind.CallOpts{ 883 Pending: true, 884 }, 885 } 886 account, orgId, roleId, status, isAdmin, err := permAcctInterface.GetAccountDetails(acctId) 887 if err != nil { 888 return nil, err 889 } 890 891 if status.Int64() == 0 { 892 return nil, types.ErrAccountNotThere 893 } 894 return &types.AccountInfo{AcctId: account, OrgId: orgId, RoleId: roleId, Status: types.AcctStatus(status.Int64()), IsOrgAdmin: isAdmin}, nil 895 } 896 897 // getter to get a org record from the contract 898 func (p *PermissionCtrl) populateOrgToCache(orgId string) (*types.OrgInfo, error) { 899 permOrgInterface := &pbind.OrgManagerSession{ 900 Contract: p.permOrg, 901 CallOpts: bind.CallOpts{ 902 Pending: true, 903 }, 904 } 905 org, parentOrgId, ultimateParentId, orgLevel, orgStatus, err := permOrgInterface.GetOrgDetails(orgId) 906 if err != nil { 907 return nil, err 908 } 909 if orgStatus.Int64() == 0 { 910 return nil, types.ErrOrgDoesNotExists 911 } 912 orgInfo := types.OrgInfo{OrgId: org, ParentOrgId: parentOrgId, UltimateParent: ultimateParentId, Status: types.OrgStatus(orgStatus.Int64()), Level: orgLevel} 913 // now need to build the list of sub orgs for this org 914 subOrgIndexes, err := permOrgInterface.GetSubOrgIndexes(orgId) 915 if err != nil { 916 return nil, err 917 } 918 919 if len(subOrgIndexes) == 0 { 920 return &orgInfo, nil 921 } 922 923 // range through the sub org indexes and get the org ids to populate the suborg list 924 for _, s := range subOrgIndexes { 925 subOrgId, _, _, _, _, err := permOrgInterface.GetOrgInfo(s) 926 927 if err != nil { 928 return nil, err 929 } 930 orgInfo.SubOrgList = append(orgInfo.SubOrgList, orgId+"."+subOrgId) 931 932 } 933 return &orgInfo, nil 934 } 935 936 // getter to get a role record from the contract 937 func (p *PermissionCtrl) populateRoleToCache(roleKey *types.RoleKey) (*types.RoleInfo, error) { 938 permRoleInterface := &pbind.RoleManagerSession{ 939 Contract: p.permRole, 940 CallOpts: bind.CallOpts{ 941 Pending: true, 942 }, 943 } 944 roleDetails, err := permRoleInterface.GetRoleDetails(roleKey.RoleId, roleKey.OrgId) 945 946 if err != nil { 947 return nil, err 948 } 949 950 if roleDetails.OrgId == "" { 951 return nil, types.ErrInvalidRole 952 } 953 return &types.RoleInfo{OrgId: roleDetails.OrgId, RoleId: roleDetails.RoleId, IsVoter: roleDetails.Voter, IsAdmin: roleDetails.Admin, Access: types.AccessType(roleDetails.AccessType.Int64()), Active: roleDetails.Active}, nil 954 } 955 956 // getter to get a role record from the contract 957 func (p *PermissionCtrl) populateNodeCache(url string) (*types.NodeInfo, error) { 958 permNodeInterface := &pbind.NodeManagerSession{ 959 Contract: p.permNode, 960 CallOpts: bind.CallOpts{ 961 Pending: true, 962 }, 963 } 964 nodeDetails, err := permNodeInterface.GetNodeDetails(url) 965 if err != nil { 966 return nil, err 967 } 968 969 if nodeDetails.NodeStatus.Int64() == 0 { 970 return nil, types.ErrNodeDoesNotExists 971 } 972 return &types.NodeInfo{OrgId: nodeDetails.OrgId, Url: nodeDetails.EnodeId, Status: types.NodeStatus(nodeDetails.NodeStatus.Int64())}, nil 973 } 974 975 // getter to get a node record from the contract 976 func (p *PermissionCtrl) populateNodeCacheAndValidate(hexNodeId, ultimateParentId string) bool { 977 permNodeInterface := &pbind.NodeManagerSession{ 978 Contract: p.permNode, 979 CallOpts: bind.CallOpts{ 980 Pending: true, 981 }, 982 } 983 txnAllowed := false 984 passedEnode, _ := enode.ParseV4(hexNodeId) 985 if numberOfNodes, err := permNodeInterface.GetNumberOfNodes(); err == nil { 986 numNodes := numberOfNodes.Uint64() 987 for k := uint64(0); k < numNodes; k++ { 988 if nodeStruct, err := permNodeInterface.GetNodeDetailsFromIndex(big.NewInt(int64(k))); err == nil { 989 if orgRec, err := types.OrgInfoMap.GetOrg(nodeStruct.OrgId); err != nil { 990 if orgRec.UltimateParent == ultimateParentId { 991 recEnode, _ := enode.ParseV4(nodeStruct.EnodeId) 992 if recEnode.ID() == passedEnode.ID() { 993 txnAllowed = true 994 types.NodeInfoMap.UpsertNode(nodeStruct.OrgId, nodeStruct.EnodeId, types.NodeStatus(int(nodeStruct.NodeStatus.Int64()))) 995 } 996 } 997 } 998 } 999 } 1000 } 1001 return txnAllowed 1002 }