diff --git a/client/lib.go b/client/lib.go index ed2884bab40a29d4d12e0c29835539ef644405a5..487f708307ceeecd7c04d71511adb31902b497a1 100644 --- a/client/lib.go +++ b/client/lib.go @@ -1,4 +1,4 @@ -// Implements a very simple wrapper for GoShimmer's HTTP API . +// Implements a very simple wrapper for GoShimmer's web API . package goshimmer import ( @@ -6,16 +6,18 @@ import ( "encoding/json" "errors" "fmt" + "io" "io/ioutil" "net/http" webapi_broadcastData "github.com/iotaledger/goshimmer/plugins/webapi/broadcastData" - webapi_findTransactions "github.com/iotaledger/goshimmer/plugins/webapi/findTransactions" + webapi_findTransactionHashes "github.com/iotaledger/goshimmer/plugins/webapi/findTransactionHashes" webapi_getNeighbors "github.com/iotaledger/goshimmer/plugins/webapi/getNeighbors" - webapi_getTransactions "github.com/iotaledger/goshimmer/plugins/webapi/getTransactions" - webapi_getTrytes "github.com/iotaledger/goshimmer/plugins/webapi/getTrytes" + webapi_getTransactionObjectsByHash "github.com/iotaledger/goshimmer/plugins/webapi/getTransactionObjectsByHash" + webapi_getTransactionTrytesByHash "github.com/iotaledger/goshimmer/plugins/webapi/getTransactionTrytesByHash" webapi_gtta "github.com/iotaledger/goshimmer/plugins/webapi/gtta" webapi_spammer "github.com/iotaledger/goshimmer/plugins/webapi/spammer" + webapi_auth "github.com/iotaledger/goshimmer/plugins/webauth" "github.com/iotaledger/iota.go/consts" "github.com/iotaledger/iota.go/guards" "github.com/iotaledger/iota.go/trinary" @@ -25,17 +27,19 @@ var ( ErrBadRequest = errors.New("bad request") ErrInternalServerError = errors.New("internal server error") ErrNotFound = errors.New("not found") + ErrUnauthorized = errors.New("unauthorized") ErrUnknownError = errors.New("unknown error") ) const ( - routeBroadcastData = "broadcastData" - routeGetTrytes = "getTrytes" - routeGetTransactions = "getTransactions" - routeFindTransactions = "findTransactions" - routeGetNeighbors = "getNeighbors" - routeGetTransactionsToApprove = "getTransactionsToApprove" - routeSpammer = "spammer" + routeBroadcastData = "broadcastData" + routeGetTransactionTrytesByHash = "getTransactionTrytesByHash" + routeGetTransactionObjectsByHash = "getTransactionObjectsByHash" + routeFindTransactionsHashes = "findTransactionHashes" + routeGetNeighbors = "getNeighbors" + routeGetTransactionsToApprove = "getTransactionsToApprove" + routeSpammer = "spammer" + routeLogin = "login" contentTypeJSON = "application/json" ) @@ -47,9 +51,11 @@ func NewGoShimmerAPI(node string, httpClient ...http.Client) *GoShimmerAPI { return &GoShimmerAPI{node: node} } +// GoShimmerAPI is an API wrapper over the web API of GoShimmer. type GoShimmerAPI struct { httpClient http.Client node string + jwt string } type errorresponse struct { @@ -79,152 +85,168 @@ func interpretBody(res *http.Response, decodeTo interface{}) error { return fmt.Errorf("%w: %s", ErrNotFound, errRes.Error) case http.StatusBadRequest: return fmt.Errorf("%w: %s", ErrBadRequest, errRes.Error) + case http.StatusUnauthorized: + return fmt.Errorf("%w: %s", ErrUnauthorized, errRes.Error) } return fmt.Errorf("%w: %s", ErrUnknownError, errRes.Error) } -func (api *GoShimmerAPI) BroadcastData(targetAddress trinary.Trytes, data string) (trinary.Hash, error) { - if !guards.IsHash(targetAddress) { - return "", fmt.Errorf("%w: invalid address: %s", consts.ErrInvalidHash, targetAddress) +func (api *GoShimmerAPI) do(method string, route string, reqObj interface{}, resObj interface{}) error { + // marshal request object + var data []byte + if reqObj != nil { + var err error + data, err = json.Marshal(reqObj) + if err != nil { + return err + } } - reqBytes, err := json.Marshal(&webapi_broadcastData.Request{Address: targetAddress, Data: data}) + // construct request + req, err := http.NewRequest(method, fmt.Sprintf("%s/%s", api.node, route), func() io.Reader { + if data == nil { + return nil + } + return bytes.NewReader(data) + }()) if err != nil { - return "", err + return err } - res, err := api.httpClient.Post(fmt.Sprintf("%s/%s", api.node, routeBroadcastData), contentTypeJSON, bytes.NewReader(reqBytes)) - if err != nil { - return "", err + // add authorization header with JWT + if len(api.jwt) > 0 { + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", api.jwt)) } - resObj := &webapi_broadcastData.Response{} - if err := interpretBody(res, resObj); err != nil { - return "", err + // make the request + res, err := api.httpClient.Do(req) + if err != nil { + return err } - return resObj.Hash, nil -} + if resObj == nil { + return nil + } -func (api *GoShimmerAPI) GetTrytes(txHashes trinary.Hashes) ([]trinary.Trytes, error) { - for _, hash := range txHashes { - if !guards.IsTrytes(hash) { - return nil, fmt.Errorf("%w: invalid hash: %s", consts.ErrInvalidHash, hash) - } + // write response into response object + if err := interpretBody(res, resObj); err != nil { + return err } + return nil +} - reqBytes, err := json.Marshal(&webapi_getTrytes.Request{Hashes: txHashes}) - if err != nil { - return nil, err +// Login authorizes this API instance against the web API. +// You must call this function before any before any other call, if the web-auth plugin is enabled. +func (api *GoShimmerAPI) Login(username string, password string) error { + res := &webapi_auth.Response{} + if err := api.do(http.MethodPost, routeLogin, + &webapi_auth.Request{Username: username, Password: password}, res); err != nil { + return err } + api.jwt = res.Token + return nil +} - res, err := api.httpClient.Post(fmt.Sprintf("%s/%s", api.node, routeGetTrytes), contentTypeJSON, bytes.NewReader(reqBytes)) - if err != nil { - return nil, err +// BroadcastData sends the given data by creating a zero value transaction in the backend targeting the given address. +func (api *GoShimmerAPI) BroadcastData(targetAddress trinary.Trytes, data string) (trinary.Hash, error) { + if !guards.IsHash(targetAddress) { + return "", fmt.Errorf("%w: invalid address: %s", consts.ErrInvalidHash, targetAddress) } - resObj := &webapi_getTrytes.Response{} - if err := interpretBody(res, resObj); err != nil { - return nil, err + res := &webapi_broadcastData.Response{} + if err := api.do(http.MethodPost, routeBroadcastData, + &webapi_broadcastData.Request{Address: targetAddress, Data: data}, res); err != nil { + return "", err } - return resObj.Trytes, nil + return res.Hash, nil } -func (api *GoShimmerAPI) GetTransactions(txHashes trinary.Hashes) ([]webapi_getTransactions.Transaction, error) { +// GetTransactionTrytesByHash gets the corresponding transaction trytes given the transaction hashes. +func (api *GoShimmerAPI) GetTransactionTrytesByHash(txHashes trinary.Hashes) ([]trinary.Trytes, error) { for _, hash := range txHashes { if !guards.IsTrytes(hash) { return nil, fmt.Errorf("%w: invalid hash: %s", consts.ErrInvalidHash, hash) } } - reqBytes, err := json.Marshal(&webapi_getTransactions.Request{Hashes: txHashes}) - if err != nil { - return nil, err - } - - res, err := api.httpClient.Post(fmt.Sprintf("%s/%s", api.node, routeGetTransactions), contentTypeJSON, bytes.NewReader(reqBytes)) - if err != nil { - return nil, err - } - - resObj := &webapi_getTransactions.Response{} - if err := interpretBody(res, resObj); err != nil { + res := &webapi_getTransactionTrytesByHash.Response{} + if err := api.do(http.MethodPost, routeGetTransactionTrytesByHash, + &webapi_getTransactionTrytesByHash.Request{Hashes: txHashes}, res); err != nil { return nil, err } - return resObj.Transactions, nil + return res.Trytes, nil } -func (api *GoShimmerAPI) FindTransactions(query *webapi_findTransactions.Request) ([]trinary.Hashes, error) { - for _, hash := range query.Addresses { +// GetTransactionObjectsByHash gets the transaction objects given the transaction hashes. +func (api *GoShimmerAPI) GetTransactionObjectsByHash(txHashes trinary.Hashes) ([]webapi_getTransactionObjectsByHash.Transaction, error) { + for _, hash := range txHashes { if !guards.IsTrytes(hash) { return nil, fmt.Errorf("%w: invalid hash: %s", consts.ErrInvalidHash, hash) } } - reqBytes, err := json.Marshal(&query) - if err != nil { + res := &webapi_getTransactionObjectsByHash.Response{} + if err := api.do(http.MethodPost, routeGetTransactionObjectsByHash, + &webapi_getTransactionObjectsByHash.Request{Hashes: txHashes}, res); err != nil { return nil, err } - res, err := api.httpClient.Post(fmt.Sprintf("%s/%s", api.node, routeFindTransactions), contentTypeJSON, bytes.NewReader(reqBytes)) - if err != nil { - return nil, err - } - - resObj := &webapi_findTransactions.Response{} - if err := interpretBody(res, resObj); err != nil { - return nil, err - } - - return resObj.Transactions, nil + return res.Transactions, nil } -func (api *GoShimmerAPI) GetNeighbors() (*webapi_getNeighbors.Response, error) { - res, err := api.httpClient.Get(fmt.Sprintf("%s/%s", api.node, routeGetNeighbors)) - if err != nil { - return nil, err +// FindTransactionHashes finds the given transaction hashes given the query. +func (api *GoShimmerAPI) FindTransactionHashes(query *webapi_findTransactionHashes.Request) ([]trinary.Hashes, error) { + for _, hash := range query.Addresses { + if !guards.IsTrytes(hash) { + return nil, fmt.Errorf("%w: invalid hash: %s", consts.ErrInvalidHash, hash) + } } - resObj := &webapi_getNeighbors.Response{} - if err := interpretBody(res, resObj); err != nil { + res := &webapi_findTransactionHashes.Response{} + if err := api.do(http.MethodPost, routeFindTransactionsHashes, query, res); err != nil { return nil, err } - return resObj, nil + return res.Transactions, nil } -func (api *GoShimmerAPI) GetTips() (*webapi_gtta.Response, error) { - res, err := api.httpClient.Get(fmt.Sprintf("%s/%s", api.node, routeGetTransactionsToApprove)) - if err != nil { +// GetNeighbors gets the chosen/accepted neighbors. +// If knownPeers is set, also all known peers to the node are returned additionally. +func (api *GoShimmerAPI) GetNeighbors(knownPeers bool) (*webapi_getNeighbors.Response, error) { + res := &webapi_getNeighbors.Response{} + if err := api.do(http.MethodGet, func() string { + if !knownPeers { + return routeGetNeighbors + } + return fmt.Sprintf("%s?known=1", routeGetNeighbors) + }(), nil, res); err != nil { return nil, err } + return res, nil +} - resObj := &webapi_gtta.Response{} - if err := interpretBody(res, resObj); err != nil { +// GetTips executes the tip-selection on the node to retrieve tips to approve. +func (api *GoShimmerAPI) GetTransactionsToApprove() (*webapi_gtta.Response, error) { + res := &webapi_gtta.Response{} + if err := api.do(http.MethodGet, routeGetTransactionsToApprove, nil, res); err != nil { return nil, err } - - return resObj, nil + return res, nil } +// ToggleSpammer toggles the node internal spammer. func (api *GoShimmerAPI) ToggleSpammer(enable bool) (*webapi_spammer.Response, error) { - res, err := api.httpClient.Get(fmt.Sprintf("%s/%s?cmd=%s", api.node, routeSpammer, func() string { + res := &webapi_spammer.Response{} + if err := api.do(http.MethodGet, func() string { if enable { - return "start" + return fmt.Sprintf("%s?cmd=start", routeSpammer) } - return "stop" - }())) - if err != nil { - return nil, err - } - - resObj := &webapi_spammer.Response{} - if err := interpretBody(res, resObj); err != nil { + return fmt.Sprintf("%s?cmd=stop", routeSpammer) + }(), nil, res); err != nil { return nil, err } - - return resObj, nil + return res, nil } diff --git a/config.json b/config.json index e28d03a94750597368472df20ab897f0f9739a89..9b8fe5db33408029aa287792424d4b1997d395b5 100644 --- a/config.json +++ b/config.json @@ -8,7 +8,7 @@ "entrynodes": [ "V8LYtWWcPYYDTTXLeIEFjJEuWlsjDiI0+Pq/Cx9ai6g=@116.202.49.178:14626" ], - "port":14626 + "port": 14626 }, "database": { "directory": "mainnetdb" @@ -16,6 +16,14 @@ "gossip": { "port": 14666 }, + "webapi": { + "bindAddress": "0.0.0.0:8080", + "auth": { + "username": "goshimmer", + "password": "goshimmer", + "privateKey": "uUUavNbdr32jE9CqnSMCKt4HMu9AZ2K4rKekUSPx9jk83eyeM7xewv5CqUKYMC9" + } + }, "graph": { "webrootPath": "./IOTAtangle/webroot", "socketioPath": "./socket.io-client/dist/socket.io.js", diff --git a/main.go b/main.go index f7d202d11a105af72d69955a5a3b88e03a91c95a..c3f4249478f7fcb1c247f41fe0ebe9a87bab43c3 100644 --- a/main.go +++ b/main.go @@ -20,13 +20,13 @@ import ( "github.com/iotaledger/goshimmer/plugins/ui" "github.com/iotaledger/goshimmer/plugins/webapi" webapi_broadcastData "github.com/iotaledger/goshimmer/plugins/webapi/broadcastData" - webapi_findTransactions "github.com/iotaledger/goshimmer/plugins/webapi/findTransactions" + webapi_findTransactionHashes "github.com/iotaledger/goshimmer/plugins/webapi/findTransactionHashes" webapi_getNeighbors "github.com/iotaledger/goshimmer/plugins/webapi/getNeighbors" - webapi_getTransactions "github.com/iotaledger/goshimmer/plugins/webapi/getTransactions" - webapi_getTrytes "github.com/iotaledger/goshimmer/plugins/webapi/getTrytes" + webapi_getTransactionObjectsByHash "github.com/iotaledger/goshimmer/plugins/webapi/getTransactionObjectsByHash" + webapi_getTransactionTrytesByHash "github.com/iotaledger/goshimmer/plugins/webapi/getTransactionTrytesByHash" webapi_gtta "github.com/iotaledger/goshimmer/plugins/webapi/gtta" webapi_spammer "github.com/iotaledger/goshimmer/plugins/webapi/spammer" - "github.com/iotaledger/goshimmer/plugins/webauth" + webapi_auth "github.com/iotaledger/goshimmer/plugins/webauth" "github.com/iotaledger/goshimmer/plugins/zeromq" "github.com/iotaledger/hive.go/node" ) @@ -54,17 +54,17 @@ func main() { statusscreen_tps.PLUGIN, webapi.PLUGIN, + webapi_auth.PLUGIN, webapi_gtta.PLUGIN, webapi_spammer.PLUGIN, webapi_broadcastData.PLUGIN, - webapi_getTrytes.PLUGIN, - webapi_getTransactions.PLUGIN, - webapi_findTransactions.PLUGIN, + webapi_getTransactionTrytesByHash.PLUGIN, + webapi_getTransactionObjectsByHash.PLUGIN, + webapi_findTransactionHashes.PLUGIN, webapi_getNeighbors.PLUGIN, webapi_spammer.PLUGIN, ui.PLUGIN, - webauth.PLUGIN, graph.PLUGIN, ), diff --git a/plugins/webapi/findTransactions/plugin.go b/plugins/webapi/findTransactionHashes/plugin.go similarity index 80% rename from plugins/webapi/findTransactions/plugin.go rename to plugins/webapi/findTransactionHashes/plugin.go index ff9b406ad2af9af2d8f64b39e09fcf5970df146e..07a626d9fc7bbecea5b6a23e0f7d4f88849c6da9 100644 --- a/plugins/webapi/findTransactions/plugin.go +++ b/plugins/webapi/findTransactionHashes/plugin.go @@ -1,4 +1,4 @@ -package findTransactions +package findTransactionHashes import ( "net/http" @@ -11,19 +11,19 @@ import ( "github.com/labstack/echo" ) -var PLUGIN = node.NewPlugin("WebAPI findTransactions Endpoint", node.Enabled, configure) +var PLUGIN = node.NewPlugin("WebAPI findTransactionHashes Endpoint", node.Enabled, configure) var log *logger.Logger func configure(plugin *node.Plugin) { - log = logger.NewLogger("API-findTransactions") - webapi.Server.POST("findTransactions", findTransactions) + log = logger.NewLogger("API-findTransactionHashes") + webapi.Server.POST("findTransactionHashes", findTransactionHashes) } -// findTransactions returns the array of transaction hashes for the +// findTransactionHashes returns the array of transaction hashes for the // given addresses (in the same order as the parameters). // If a node doesn't have any transaction hash for a given address in its ledger, // the value at the index of that address is empty. -func findTransactions(c echo.Context) error { +func findTransactionHashes(c echo.Context) error { var request Request if err := c.Bind(&request); err != nil { diff --git a/plugins/webapi/getTransactions/plugin.go b/plugins/webapi/getTransactionObjectsByHash/plugin.go similarity index 87% rename from plugins/webapi/getTransactions/plugin.go rename to plugins/webapi/getTransactionObjectsByHash/plugin.go index 70c231328b29c32e619e3c2b5927fac6c85c4557..221def3cdba855e876fdbaad72cb475dc38a6c1f 100644 --- a/plugins/webapi/getTransactions/plugin.go +++ b/plugins/webapi/getTransactionObjectsByHash/plugin.go @@ -1,4 +1,4 @@ -package getTransactions +package getTransactionObjectsByHash import ( "net/http" @@ -11,19 +11,19 @@ import ( "github.com/labstack/echo" ) -var PLUGIN = node.NewPlugin("WebAPI getTransaction Endpoint", node.Enabled, configure) +var PLUGIN = node.NewPlugin("WebAPI getTransactionObjectsByHash Endpoint", node.Enabled, configure) var log *logger.Logger func configure(plugin *node.Plugin) { - log = logger.NewLogger("API-getTransactions") - webapi.Server.POST("getTransactions", getTransactions) + log = logger.NewLogger("API-getTransactionObjectsByHash") + webapi.Server.POST("getTransactionObjectsByHash", getTransactionObjectsByHash) } -// getTransactions returns the array of transactions for the +// getTransactionObjectsByHash returns the array of transactions for the // given transaction hashes (in the same order as the parameters). // If a node doesn't have the transaction for a given transaction hash in its ledger, // the value at the index of that transaction hash is empty. -func getTransactions(c echo.Context) error { +func getTransactionObjectsByHash(c echo.Context) error { var request Request result := []Transaction{} diff --git a/plugins/webapi/getTrytes/plugin.go b/plugins/webapi/getTransactionTrytesByHash/plugin.go similarity index 79% rename from plugins/webapi/getTrytes/plugin.go rename to plugins/webapi/getTransactionTrytesByHash/plugin.go index b29b83fa76cb59a7dcf21093190dd75053eab477..b4bb36136d59cca735b790ed677f306e8e3d175c 100644 --- a/plugins/webapi/getTrytes/plugin.go +++ b/plugins/webapi/getTransactionTrytesByHash/plugin.go @@ -1,4 +1,4 @@ -package getTrytes +package getTransactionTrytesByHash import ( "net/http" @@ -11,19 +11,19 @@ import ( "github.com/labstack/echo" ) -var PLUGIN = node.NewPlugin("WebAPI getTrytes Endpoint", node.Enabled, configure) +var PLUGIN = node.NewPlugin("WebAPI getTransactionTrytesByHash Endpoint", node.Enabled, configure) var log *logger.Logger func configure(plugin *node.Plugin) { - log = logger.NewLogger("API-getTrytes") - webapi.Server.GET("getTrytes", getTrytes) + log = logger.NewLogger("API-getTransactionTrytesByHash") + webapi.Server.GET("getTransactionTrytesByHash", getTransactionTrytesByHash) } -// getTrytes returns the array of transaction trytes for the +// getTransactionTrytesByHash returns the array of transaction trytes for the // given transaction hashes (in the same order as the parameters). // If a node doesn't have the trytes for a given transaction hash in its ledger, // the value at the index of that transaction hash is empty. -func getTrytes(c echo.Context) error { +func getTransactionTrytesByHash(c echo.Context) error { var request Request result := []trinary.Trytes{} diff --git a/plugins/webapi/parameters.go b/plugins/webapi/parameters.go new file mode 100644 index 0000000000000000000000000000000000000000..e5703ce31f628451739d2b38df4a368a4f39ccc4 --- /dev/null +++ b/plugins/webapi/parameters.go @@ -0,0 +1,13 @@ +package webapi + +import ( + flag "github.com/spf13/pflag" +) + +const ( + BIND_ADDRESS = "webapi.bindAddress" +) + +func init() { + flag.String(BIND_ADDRESS, "0.0.0.0:8080", "the bind address for the web API") +} diff --git a/plugins/webapi/plugin.go b/plugins/webapi/plugin.go index c7bd41f334d257aadd74973b31d22e899208ed6f..79365c8727fa71c9c031c3228c5af22e505567c9 100644 --- a/plugins/webapi/plugin.go +++ b/plugins/webapi/plugin.go @@ -4,6 +4,7 @@ import ( "context" "time" + "github.com/iotaledger/goshimmer/packages/parameter" "github.com/iotaledger/goshimmer/packages/shutdown" "github.com/iotaledger/hive.go/daemon" "github.com/iotaledger/hive.go/logger" @@ -30,7 +31,7 @@ func run(plugin *node.Plugin) { log.Info("Starting Web Server ... done") go func() { - if err := Server.Start(":8080"); err != nil { + if err := Server.Start(parameter.NodeConfig.GetString(BIND_ADDRESS)); err != nil { log.Info("Stopping Web Server ... done") } }() diff --git a/plugins/webauth/parameters.go b/plugins/webauth/parameters.go new file mode 100644 index 0000000000000000000000000000000000000000..5084ce564029b3dc5e7d4ffc2ed8380e8fd1e3c9 --- /dev/null +++ b/plugins/webauth/parameters.go @@ -0,0 +1,17 @@ +package webauth + +import ( + flag "github.com/spf13/pflag" +) + +const ( + WEBAPI_AUTH_USERNAME = "webapi.auth.username" + WEBAPI_AUTH_PASSWORD = "webapi.auth.password" + WEBAPI_AUTH_PRIVATE_KEY = "webapi.auth.privateKey" +) + +func init() { + flag.String(WEBAPI_AUTH_USERNAME, "goshimmer", "username for the webapi") + flag.String(WEBAPI_AUTH_PASSWORD, "goshimmer", "password for the webapi") + flag.String(WEBAPI_AUTH_PRIVATE_KEY, "", "private key used to sign the JWTs") +} diff --git a/plugins/webauth/webauth.go b/plugins/webauth/webauth.go index aa7ba5b340e3cb0c232b97ccf0cf970fd11ab965..21e943fa9f10518118227f65c3e584c622df1af8 100644 --- a/plugins/webauth/webauth.go +++ b/plugins/webauth/webauth.go @@ -2,13 +2,12 @@ package webauth import ( "net/http" - "os" "strings" "time" - "github.com/iotaledger/goshimmer/packages/shutdown" + "github.com/iotaledger/goshimmer/packages/parameter" "github.com/iotaledger/goshimmer/plugins/webapi" - "github.com/iotaledger/hive.go/daemon" + "github.com/iotaledger/hive.go/logger" "github.com/iotaledger/hive.go/node" "github.com/labstack/echo" "github.com/labstack/echo/middleware" @@ -16,59 +15,60 @@ import ( "github.com/dgrijalva/jwt-go" ) -var secret = "secret" +var PLUGIN = node.NewPlugin("WebAPI Auth", node.Disabled, configure) +var log *logger.Logger +var privateKey string func configure(plugin *node.Plugin) { - - jwtKey := os.Getenv("JWT_KEY") - if jwtKey != "" { - secret = jwtKey + log = logger.NewLogger("WebAPI Auth") + privateKey = parameter.NodeConfig.GetString(WEBAPI_AUTH_PRIVATE_KEY) + if len(privateKey) == 0 { + panic("") } webapi.Server.Use(middleware.JWTWithConfig(middleware.JWTConfig{ - SigningKey: []byte(secret), - TokenLookup: "query:token", + SigningKey: []byte(privateKey), Skipper: func(c echo.Context) bool { - // if strings.HasPrefix(c.Request().Host, "localhost") { - // return true - // } if strings.HasPrefix(c.Path(), "/ui") || c.Path() == "/login" { return true } return false }, })) + + webapi.Server.POST("/login", Handler) + log.Info("WebAPI is now secured through JWT authentication") +} + +type Request struct { + Username string `json:"username"` + Password string `json:"password"` } -func run(plugin *node.Plugin) { - daemon.BackgroundWorker("webauth", func(shutdownSignal <-chan struct{}) { - webapi.Server.GET("login", func(c echo.Context) error { - username := c.FormValue("username") - password := c.FormValue("password") - uiUser := os.Getenv("UI_USER") - uiPass := os.Getenv("UI_PASS") +type Response struct { + Token string `json:"token"` +} - // Throws unauthorized error - if username != uiUser || password != uiPass { - return echo.ErrUnauthorized - } +func Handler(c echo.Context) error { + login := &Request{} + if err := c.Bind(login); err != nil { + return echo.ErrBadRequest + } - token := jwt.New(jwt.SigningMethodHS256) - claims := token.Claims.(jwt.MapClaims) - claims["name"] = username - claims["exp"] = time.Now().Add(time.Hour * 24 * 7).Unix() + if login.Username != parameter.NodeConfig.GetString(WEBAPI_AUTH_USERNAME) || + login.Password != parameter.NodeConfig.GetString(WEBAPI_AUTH_PASSWORD) { + return echo.ErrUnauthorized + } - t, err := token.SignedString([]byte(secret)) - if err != nil { - return err - } + token := jwt.New(jwt.SigningMethodHS256) + claims := token.Claims.(jwt.MapClaims) + claims["name"] = login.Username + claims["exp"] = time.Now().Add(time.Hour * 24 * 7).Unix() - return c.JSON(http.StatusOK, map[string]string{ - "token": t, - }) - }) - }, shutdown.ShutdownPriorityWebAPI) -} + t, err := token.SignedString([]byte(privateKey)) + if err != nil { + return err + } -// PLUGIN plugs the UI into the main program -var PLUGIN = node.NewPlugin("webauth", node.Disabled, configure, run) + return c.JSON(http.StatusOK, &Response{Token: t}) +} diff --git a/tools/relay-checker/main.go b/tools/relay-checker/main.go index 189babf7ea79072579c5872a5209a9853989109a..80484582995ce68a19d20e28862ff95e5783c130 100644 --- a/tools/relay-checker/main.go +++ b/tools/relay-checker/main.go @@ -5,23 +5,21 @@ import ( "time" client "github.com/iotaledger/goshimmer/client" - "github.com/iotaledger/goshimmer/packages/errors" "github.com/iotaledger/iota.go/trinary" ) func testBroadcastData(api *client.GoShimmerAPI) (trinary.Hash, error) { txnHash, err := api.BroadcastData(txnAddr, txnData) if err != nil { - return "", errors.Wrapf(err, "Broadcast failed") + return "", fmt.Errorf("broadcast failed: %w", err) } return txnHash, nil } func testTargetGetTransactions(api *client.GoShimmerAPI, txnHash trinary.Hash) error { // query target node for broadcasted data - _, err := api.GetTransactions([]trinary.Hash{txnHash}) - if err != nil { - return errors.Wrapf(err, "Query target failed") + if _, err := api.GetTransactionObjectsByHash([]trinary.Hash{txnHash}); err != nil { + return fmt.Errorf("querying the target node failed: %w", err) } return nil } @@ -30,11 +28,10 @@ func testNodesGetTransactions(txnHash trinary.Hash) error { // query nodes node for broadcasted data for _, n := range nodes { nodesApi := client.NewGoShimmerAPI(n) - _, err := nodesApi.GetTransactions([]trinary.Hash{txnHash}) - if err != nil { - return errors.Wrapf(err, "Query %s failed", n) + if _, err := nodesApi.GetTransactionObjectsByHash([]trinary.Hash{txnHash}); err != nil { + return fmt.Errorf("querying node %s failed: %w", n, err) } - fmt.Printf("txn found in %s\n", n) + fmt.Printf("txn found in node %s\n", n) } return nil }