diff --git a/.gitignore b/.gitignore index 51858600..9ad5297a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ +.secrets/ .vscode/ .DS_Store \ No newline at end of file diff --git a/nodes/node_balancer/cmd/data.go b/nodes/node_balancer/cmd/data.go index 0a1d3e0a..b46c30d1 100644 --- a/nodes/node_balancer/cmd/data.go +++ b/nodes/node_balancer/cmd/data.go @@ -17,6 +17,10 @@ type NodeStatusResponse struct { CurrentBlock uint64 `json:"current_block"` } +type BugoutUserResponse struct { + ID string `json:"user_id"` +} + // Node - which one node client worked with // LastCallTs - timestamp from last call type Client struct { diff --git a/nodes/node_balancer/cmd/middleware.go b/nodes/node_balancer/cmd/middleware.go index 1bc69fda..b952936d 100644 --- a/nodes/node_balancer/cmd/middleware.go +++ b/nodes/node_balancer/cmd/middleware.go @@ -4,9 +4,15 @@ Server API middlewares. package cmd import ( + "encoding/json" + "fmt" + "io/ioutil" "log" "net" "net/http" + "strings" + + "github.com/bugout-dev/moonstream/nodes/node_balancer/configs" humbug "github.com/bugout-dev/humbug/go/pkg" ) @@ -40,3 +46,65 @@ func logMiddleware(next http.Handler) http.Handler { } }) } + +// Bugout authentication +func authMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + authHeaders := r.Header["Authorization"] + authHeadersLen := len(authHeaders) + if authHeadersLen == 0 { + http.Error(w, "Authorization header not found", http.StatusForbidden) + return + } + if authHeadersLen > 1 { + http.Error(w, "Too many authorization headers provided", http.StatusBadRequest) + return + } + authHeader := authHeaders[0] + + // Extract Bearer token + headerSlice := strings.Split(authHeader, " ") + if len(headerSlice) != 2 { + http.Error(w, "Unacceptable token format provided", http.StatusBadRequest) + return + } + if headerSlice[0] != "Bearer" { + http.Error(w, "Unacceptable token format provided", http.StatusBadRequest) + return + } + + // Check token is active + client := http.Client{Timeout: configs.BUGOUT_AUTH_CALL_TIMEOUT} + authReq, err := http.NewRequest("GET", fmt.Sprintf("%s/user", configs.BUGOUT_AUTH_URL), nil) + if err != nil { + http.Error(w, "Unable to construct authorization request", http.StatusInternalServerError) + return + } + authReq.Header.Set("Authorization", authHeader) + resp, err := client.Do(authReq) + if err != nil { + http.Error(w, "Unable to reach authorization server", http.StatusInternalServerError) + return + } + defer resp.Body.Close() + + // Parse response from authorization server + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + http.Error(w, "Unable to read respose from authorization server", http.StatusInternalServerError) + return + } + var userResponse BugoutUserResponse + err = json.Unmarshal(body, &userResponse) + if err != nil { + http.Error(w, "Unable to parse respose from authorization server", http.StatusInternalServerError) + return + } + if userResponse.ID == "" { + http.Error(w, "Wrong authorization header", http.StatusForbidden) + return + } + + next.ServeHTTP(w, r) + }) +} diff --git a/nodes/node_balancer/cmd/server.go b/nodes/node_balancer/cmd/server.go index be57b3ec..85e883cb 100644 --- a/nodes/node_balancer/cmd/server.go +++ b/nodes/node_balancer/cmd/server.go @@ -157,8 +157,8 @@ func InitServer() { } serveMux := http.NewServeMux() + serveMux.Handle("/nb/", authMiddleware(http.HandlerFunc(lbHandler))) serveMux.HandleFunc("/ping", pingRoute) - serveMux.HandleFunc("/nb/", lbHandler) // Set common middlewares, from bottom to top commonHandler := logMiddleware(serveMux) diff --git a/nodes/node_balancer/configs/settings.go b/nodes/node_balancer/configs/settings.go index 5eb88113..3f6cb47e 100644 --- a/nodes/node_balancer/configs/settings.go +++ b/nodes/node_balancer/configs/settings.go @@ -10,6 +10,13 @@ import ( "time" ) +// Bugout config +var BUGOUT_AUTH_URL = os.Getenv("BUGOUT_AUTH_URL") +var BUGOUT_NODE_BALANCER_APPLICATION_ID = os.Getenv("BUGOUT_NODE_BALANCER_APPLICATION_ID") +var BUGOUT_INTERNAL_CRAWLERS_USER_ID = os.Getenv("BUGOUT_INTERNAL_CRAWLERS_USER_ID") +var BUGOUT_AUTH_CALL_TIMEOUT = time.Second * 1 + +// Node config type BlockchainConfig struct { Blockchain string IPs []string @@ -30,10 +37,8 @@ var ConfigList NodeConfigList var MOONSTREAM_NODE_ETHEREUM_A_IPC_ADDR = os.Getenv("MOONSTREAM_NODE_ETHEREUM_A_IPC_ADDR") var MOONSTREAM_NODE_ETHEREUM_B_IPC_ADDR = os.Getenv("MOONSTREAM_NODE_ETHEREUM_B_IPC_ADDR") -var MOONSTREAM_NODE_ETHEREUM_IPC_PORT = os.Getenv("MOONSTREAM_NODE_ETHEREUM_IPC_PORT") var MOONSTREAM_NODE_POLYGON_A_IPC_ADDR = os.Getenv("MOONSTREAM_NODE_POLYGON_A_IPC_ADDR") var MOONSTREAM_NODE_POLYGON_B_IPC_ADDR = os.Getenv("MOONSTREAM_NODE_POLYGON_B_IPC_ADDR") -var MOONSTREAM_NODE_POLYGON_IPC_PORT = os.Getenv("MOONSTREAM_NODE_POLYGON_IPC_PORT") var MOONSTREAM_NODES_SERVER_PORT = os.Getenv("MOONSTREAM_NODES_SERVER_PORT") var MOONSTREAM_CLIENT_ID_HEADER = os.Getenv("MOONSTREAM_CLIENT_ID_HEADER") @@ -56,8 +61,8 @@ func checkEnvVarSet() { MOONSTREAM_CLIENT_ID_HEADER = "x-moonstream-client-id" } - if MOONSTREAM_NODES_SERVER_PORT == "" || MOONSTREAM_NODE_ETHEREUM_IPC_PORT == "" || MOONSTREAM_NODE_POLYGON_IPC_PORT == "" { - log.Fatal("Some of environment variables not set") + if MOONSTREAM_NODES_SERVER_PORT == "" { + log.Fatal("MOONSTREAM_NODES_SERVER_PORT environment variable not set") } } @@ -70,12 +75,12 @@ func (nc *NodeConfigList) InitNodeConfigList() { blockchainConfigList = append(blockchainConfigList, BlockchainConfig{ Blockchain: "ethereum", IPs: []string{MOONSTREAM_NODE_ETHEREUM_A_IPC_ADDR, MOONSTREAM_NODE_ETHEREUM_B_IPC_ADDR}, - Port: MOONSTREAM_NODE_ETHEREUM_IPC_PORT, + Port: "8545", }) blockchainConfigList = append(blockchainConfigList, BlockchainConfig{ Blockchain: "polygon", IPs: []string{MOONSTREAM_NODE_POLYGON_A_IPC_ADDR, MOONSTREAM_NODE_POLYGON_B_IPC_ADDR}, - Port: MOONSTREAM_NODE_POLYGON_IPC_PORT, + Port: "8545", }) // Parse node addr, ip and blockchain diff --git a/nodes/node_balancer/sample.env b/nodes/node_balancer/sample.env index 97b56c8d..f186fd33 100644 --- a/nodes/node_balancer/sample.env +++ b/nodes/node_balancer/sample.env @@ -1,15 +1,14 @@ # Required environment variables for load balancer +export BUGOUT_AUTH_URL="https://auth.bugout.dev" +export BUGOUT_NODE_BALANCER_APPLICATION_ID="" +export BUGOUT_INTERNAL_CRAWLERS_USER_ID="" export MOONSTREAM_NODES_SERVER_PORT="" export HUMBUG_REPORTER_NODE_BALANCER_TOKEN="" # Ethereum nodes depends variables -export MOONSTREAM_NODE_ETHEREUM_IPC_PORT="" - export MOONSTREAM_NODE_ETHEREUM_A_IPC_ADDR="" export MOONSTREAM_NODE_ETHEREUM_B_IPC_ADDR="" # Polygon nodes depends variables -export MOONSTREAM_NODE_POLYGON_IPC_PORT="" - export MOONSTREAM_NODE_POLYGON_A_IPC_ADDR="" export MOONSTREAM_NODE_POLYGON_B_IPC_ADDR=""