cli to work with nodebalancer users access

pull/559/head
kompotkot 2022-03-17 14:41:03 +00:00
rodzic ae3dfa1449
commit abd570b6a0
5 zmienionych plików z 294 dodań i 45 usunięć

Wyświetl plik

@ -11,10 +11,36 @@ go build -o nodebalancer
# Work with nodebalancer
## clients
## add-access
Add new access for user:
```bash
nodebalancer clients | jq .
nodebalancer add-access \
--user-id "<user_uuid>" \
--access-id "<access_uuid>" \
--name "Access name" \
--description "Description of access" \
--extended-methods false \
--blockchain--access true
```
## delete-access
Delete user access:
```bash
nodebalancer delete-access \
--user-id "<user_uuid>" \
--access-id "<access_uuid>"
```
If `access-id` not specified, all user accesses will be deleted.
## users
```bash
nodebalancer users | jq .
```
This command will return a list of bugout resources of registered users to access node balancer with their `crawlers/app/project` (in our project we will call it `crawlers`).

Wyświetl plik

@ -1,6 +1,7 @@
package cmd
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
@ -59,10 +60,12 @@ func InitBugoutClient() {
// Get Bugout user
func (bc *BugoutClient) GetUser(token string) (BugoutUserResponse, error) {
var userResponse BugoutUserResponse
url := fmt.Sprintf("%s/user", configs.BUGOUT_AUTH_URL)
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return BugoutUserResponse{}, err
return userResponse, err
}
req.Header = http.Header{
@ -70,27 +73,109 @@ func (bc *BugoutClient) GetUser(token string) (BugoutUserResponse, error) {
}
resp, err := bc.Client.Do(req)
if err != nil {
return BugoutUserResponse{}, err
return userResponse, err
}
defer resp.Body.Close()
// Parse response
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return BugoutUserResponse{}, err
return userResponse, err
}
var userResponse BugoutUserResponse
err = json.Unmarshal(body, &userResponse)
if err != nil {
return BugoutUserResponse{}, err
return userResponse, err
}
return userResponse, nil
}
// Get user accesses from Bugout resources
func (bc *BugoutClient) GetUserAccesses(token, userID, accessID string) ([]UserAccess, error) {
var userAccesses []UserAccess
// Find Bugout user
func (bc *BugoutClient) FindUser(token, userID string) (BugoutUserResponse, error) {
var userResponse BugoutUserResponse
url := fmt.Sprintf("%s/user/find?user_id=%s", configs.BUGOUT_AUTH_URL, userID)
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return userResponse, err
}
req.Header = http.Header{
"Authorization": []string{fmt.Sprintf("Bearer %s", token)},
}
resp, err := bc.Client.Do(req)
if err != nil {
return userResponse, err
}
defer resp.Body.Close()
// Parse response
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return userResponse, err
}
err = json.Unmarshal(body, &userResponse)
if err != nil {
return userResponse, err
}
return userResponse, nil
}
func (bc *BugoutClient) AddUserAccess(token string, proposedUserAccess UserAccess) (UserAccess, error) {
var userAccess UserAccess
// Check user exists
user, err := bc.FindUser(token, proposedUserAccess.UserID)
if err != nil {
return userAccess, err
}
if user == (BugoutUserResponse{}) {
return userAccess, fmt.Errorf("User with id %s not found", proposedUserAccess.UserID)
}
resource := map[string]interface{}{
"application_id": configs.NB_APPLICATION_ID,
"resource_data": proposedUserAccess,
}
resourceJson, err := json.Marshal(resource)
if err != nil {
return userAccess, err
}
url := fmt.Sprintf("%s/resources", configs.BUGOUT_AUTH_URL)
req, err := http.NewRequest("POST", url, bytes.NewBuffer(resourceJson))
if err != nil {
return userAccess, err
}
req.Header = http.Header{
"Authorization": []string{fmt.Sprintf("Bearer %s", token)},
"Content-Type": []string{"application/json"},
}
resp, err := bc.Client.Do(req)
if err != nil {
return userAccess, err
}
defer resp.Body.Close()
// Parse response
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return userAccess, err
}
var resourceResponse BugoutResourceResponse
err = json.Unmarshal(body, &resourceResponse)
if err != nil {
return userAccess, err
}
userAccess = resourceResponse.ResourceData
return userAccess, nil
}
// Get Bugout resource
func (bc *BugoutClient) GetResources(token, userID, accessID string) (BugoutResourcesResponse, error) {
var resourcesResponse BugoutResourcesResponse
url := fmt.Sprintf("%s/resources?application_id=%s", configs.BUGOUT_AUTH_URL, configs.NB_APPLICATION_ID)
if userID != "" {
@ -101,31 +186,56 @@ func (bc *BugoutClient) GetUserAccesses(token, userID, accessID string) ([]UserA
}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return userAccesses, err
return resourcesResponse, err
}
req.Header = http.Header{
"Authorization": []string{fmt.Sprintf("Bearer %s", token)},
}
resp, err := bc.Client.Do(req)
if err != nil {
return userAccesses, err
return resourcesResponse, err
}
defer resp.Body.Close()
// Parse response
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return userAccesses, err
return resourcesResponse, err
}
var resourcesResponse BugoutResourcesResponse
err = json.Unmarshal(body, &resourcesResponse)
if err != nil {
return userAccesses, err
return resourcesResponse, err
}
for _, resourceData := range resourcesResponse.Resources {
userAccesses = append(userAccesses, resourceData.ResourceData)
}
return userAccesses, nil
return resourcesResponse, nil
}
func (bc *BugoutClient) DeleteResource(token, resourceID string) (BugoutResourceResponse, error) {
var resourceResponse BugoutResourceResponse
url := fmt.Sprintf("%s/resources/%s", configs.BUGOUT_AUTH_URL, resourceID)
req, err := http.NewRequest("DELETE", url, nil)
if err != nil {
return resourceResponse, err
}
req.Header = http.Header{
"Authorization": []string{fmt.Sprintf("Bearer %s", token)},
}
resp, err := bc.Client.Do(req)
if err != nil {
return resourceResponse, err
}
defer resp.Body.Close()
// Parse response
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return resourceResponse, err
}
err = json.Unmarshal(body, &resourceResponse)
if err != nil {
return resourceResponse, err
}
return resourceResponse, nil
}

Wyświetl plik

@ -7,6 +7,8 @@ import (
"os"
"github.com/bugout-dev/moonstream/nodes/node_balancer/configs"
"github.com/google/uuid"
)
var (
@ -15,13 +17,23 @@ var (
// Command Line Interface state
type StateCLI struct {
serverCmd *flag.FlagSet
usersCmd *flag.FlagSet
versionCmd *flag.FlagSet
addAccessCmd *flag.FlagSet
deleteAccessCmd *flag.FlagSet
serverCmd *flag.FlagSet
usersCmd *flag.FlagSet
versionCmd *flag.FlagSet
// Common flags
helpFlag bool
// Add user access flags
userIDFlag string
accessIDFlag string
accessNameFlag string
accessDescriptionFlag string
blockchainAccessFlag bool
extendedMethodsFlag bool
// Server flags
listeningAddrFlag string
listeningPortFlag string
@ -30,50 +42,96 @@ type StateCLI struct {
}
func (s *StateCLI) usage() {
usage := fmt.Sprintf(`usage: nodebalancer [-h] {%[1]s,%[2]s,%[3]s} ...
fmt.Printf(`usage: nodebalancer [-h] {%[1]s,%[2]s,%[3]s,%[4]s,%[5]s} ...
Moonstream node balancer CLI
optional arguments:
-h, --help show this help message and exit
-h, --help show this help message and exit
subcommands:
{%[1]s,%[2]s,%[3]s}
`, s.serverCmd.Name(), s.usersCmd.Name(), s.versionCmd.Name())
fmt.Println(usage)
{%[1]s,%[2]s,%[3]s,%[4]s,%[5]s}
`, s.addAccessCmd.Name(), s.deleteAccessCmd.Name(), s.serverCmd.Name(), s.usersCmd.Name(), s.versionCmd.Name())
}
func (s *StateCLI) checkRequirements() {
if s.helpFlag {
switch {
case s.addAccessCmd.Parsed():
fmt.Println("add new user access token")
s.addAccessCmd.PrintDefaults()
os.Exit(0)
case s.deleteAccessCmd.Parsed():
fmt.Println("delete user access token")
s.deleteAccessCmd.PrintDefaults()
os.Exit(0)
case s.serverCmd.Parsed():
fmt.Println("start nodebalancer server")
s.serverCmd.PrintDefaults()
return
os.Exit(0)
case s.usersCmd.Parsed():
fmt.Println("list user access tokens")
s.usersCmd.PrintDefaults()
return
os.Exit(0)
case s.versionCmd.Parsed():
fmt.Println("show version")
s.versionCmd.PrintDefaults()
return
os.Exit(0)
default:
s.usage()
return
os.Exit(0)
}
}
switch {
case s.addAccessCmd.Parsed():
if s.userIDFlag == "" {
fmt.Println("User ID should be specified")
s.addAccessCmd.PrintDefaults()
os.Exit(1)
}
if s.accessIDFlag == "" {
s.accessIDFlag = uuid.New().String()
}
if s.accessNameFlag == "" {
fmt.Println("Access name should be specified")
s.addAccessCmd.PrintDefaults()
os.Exit(1)
}
case s.deleteAccessCmd.Parsed():
if s.userIDFlag == "" && s.accessIDFlag == "" {
fmt.Println("User or access ID flag should be specified")
s.deleteAccessCmd.PrintDefaults()
os.Exit(1)
}
}
}
func (s *StateCLI) populateCLI() {
// Subcommands setup
s.addAccessCmd = flag.NewFlagSet("add-access", flag.ExitOnError)
s.deleteAccessCmd = flag.NewFlagSet("delete-access", flag.ExitOnError)
s.serverCmd = flag.NewFlagSet("server", flag.ExitOnError)
s.usersCmd = flag.NewFlagSet("users", flag.ExitOnError)
s.versionCmd = flag.NewFlagSet("version", flag.ExitOnError)
// Common flag pointers
for _, fs := range []*flag.FlagSet{s.serverCmd, s.usersCmd, s.versionCmd} {
for _, fs := range []*flag.FlagSet{s.addAccessCmd, s.deleteAccessCmd, s.serverCmd, s.usersCmd, s.versionCmd} {
fs.BoolVar(&s.helpFlag, "help", false, "Show help message")
}
// Add, delete and list user access subcommand flag pointers
for _, fs := range []*flag.FlagSet{s.addAccessCmd, s.deleteAccessCmd, s.usersCmd} {
fs.StringVar(&s.userIDFlag, "user-id", "", "Bugout user ID")
fs.StringVar(&s.accessIDFlag, "access-id", "", "UUID for access identification")
}
// Add user access subcommand flag pointers
s.addAccessCmd.StringVar(&s.accessNameFlag, "name", "", "Name of access")
s.addAccessCmd.StringVar(&s.accessDescriptionFlag, "description", "", "Description of access")
s.addAccessCmd.BoolVar(&s.blockchainAccessFlag, "blockchain-access", false, "Provide if allow to access blockchain nodes")
s.addAccessCmd.BoolVar(&s.extendedMethodsFlag, "extended-methods", false, "Provide to be able to execute not whitelisted methods")
// Server subcommand flag pointers
s.serverCmd.StringVar(&s.listeningAddrFlag, "host", "127.0.0.1", "Server listening address")
s.serverCmd.StringVar(&s.listeningPortFlag, "port", "8544", "Server listening port")
@ -90,6 +148,57 @@ func CLI() {
// Parse subcommands and appropriate FlagSet
switch os.Args[1] {
case "add-access":
stateCLI.addAccessCmd.Parse(os.Args[2:])
stateCLI.checkRequirements()
proposedUserAccess := UserAccess{
UserID: stateCLI.userIDFlag,
AccessID: stateCLI.accessIDFlag,
Name: stateCLI.accessNameFlag,
Description: stateCLI.accessDescriptionFlag,
BlockchainAccess: stateCLI.blockchainAccessFlag,
ExtendedMethods: stateCLI.extendedMethodsFlag,
}
userAccess, err := bugoutClient.AddUserAccess(configs.NB_CONTROLLER_TOKEN, proposedUserAccess)
if err != nil {
fmt.Printf("Unable to create user access %v\n", err)
os.Exit(1)
}
userAccessJson, err := json.Marshal(userAccess)
if err != nil {
fmt.Printf("Unable to marshal user access struct %v\n", err)
os.Exit(1)
}
fmt.Println(string(userAccessJson))
case "delete-access":
stateCLI.deleteAccessCmd.Parse(os.Args[2:])
stateCLI.checkRequirements()
resources, err := bugoutClient.GetResources(configs.NB_CONTROLLER_TOKEN, stateCLI.userIDFlag, stateCLI.accessIDFlag)
if err != nil {
fmt.Printf("Unable to get Bugout resources %v\n", err)
os.Exit(1)
}
var userAccesses []UserAccess
for _, resource := range resources.Resources {
deletedResource, err := bugoutClient.DeleteResource(configs.NB_CONTROLLER_TOKEN, resource.ID)
if err != nil {
fmt.Printf("Unable to delete resource with id %s %v\n", resource.ID, err)
continue
}
userAccesses = append(userAccesses, deletedResource.ResourceData)
}
userAccessesJson, err := json.Marshal(userAccesses)
if err != nil {
fmt.Printf("Unable to marshal user access struct %v\n", err)
os.Exit(1)
}
fmt.Println(string(userAccessesJson))
case "server":
stateCLI.serverCmd.Parse(os.Args[2:])
stateCLI.checkRequirements()
@ -100,15 +209,20 @@ func CLI() {
stateCLI.usersCmd.Parse(os.Args[2:])
stateCLI.checkRequirements()
userAccesses, err := bugoutClient.GetUserAccesses(configs.NB_CONTROLLER_TOKEN, "", "")
resources, err := bugoutClient.GetResources(configs.NB_CONTROLLER_TOKEN, stateCLI.userIDFlag, stateCLI.accessIDFlag)
if err != nil {
fmt.Printf("Unable to get resources %v", err)
return
fmt.Printf("Unable to get Bugout resources %v\n", err)
os.Exit(1)
}
var userAccesses []UserAccess
for _, resourceData := range resources.Resources {
userAccesses = append(userAccesses, resourceData.ResourceData)
}
userAccessesJson, err := json.Marshal(userAccesses)
if err != nil {
fmt.Printf("Unable to marshal resources %v", err)
return
fmt.Printf("Unable to marshal user accesses struct %v\n", err)
os.Exit(1)
}
fmt.Println(string(userAccessesJson))

Wyświetl plik

@ -76,17 +76,16 @@ func accessMiddleware(next http.Handler) http.Handler {
currentUserAccess = controllerUserAccess
currentUserAccess.dataSource = dataSource
} else {
userAccesses, err := bugoutClient.GetUserAccesses(configs.NB_CONTROLLER_TOKEN, "", accessID)
resources, err := bugoutClient.GetResources(configs.NB_CONTROLLER_TOKEN, "", accessID)
if err != nil {
http.Error(w, "Unable to get user with provided access identifier", http.StatusForbidden)
return
}
if len(userAccesses) == 0 {
if len(resources.Resources) == 0 {
http.Error(w, "User with provided access identifier not found", http.StatusForbidden)
return
}
userAccess := userAccesses[0]
userAccess := resources.Resources[0].ResourceData
currentUserAccess = UserAccess{
UserID: userAccess.UserID,
AccessID: userAccess.AccessID,

Wyświetl plik

@ -111,11 +111,11 @@ func Server() {
// Record system information
reporter.Publish(humbug.SystemReport())
userAccesses, err := bugoutClient.GetUserAccesses(configs.NB_CONTROLLER_TOKEN, "", configs.NB_CONTROLLER_ACCESS_ID)
resources, err := bugoutClient.GetResources(configs.NB_CONTROLLER_TOKEN, "", configs.NB_CONTROLLER_ACCESS_ID)
if err != nil {
fmt.Printf("Unable to access Bugout authentication server %v", err)
}
userAccess := userAccesses[0]
userAccess := resources.Resources[0].ResourceData
controllerUserAccess = UserAccess{
UserID: userAccess.UserID,
AccessID: userAccess.AccessID,