diff --git a/README.md b/README.md index 0d4cb557..58cc2a3c 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,7 @@ This will remove all docker images created by the server during the build proces These api are protected preventing general public to wiping out debug data to authenticate use `/authenticate/:passphrase`. `passphrase` is set in `config.ts` config file or within the system env variable. -GET `/log/api-stats` this endpint emit the rpc interface call counts and avg tps along with a few a other information. This endpoint support query by time range. i.e `/log/api-stats?start={x}&end={x}`. The parameter value can be either `yyyy-mm-dd` or unix epoch in millisecond. (NOTE standard unix epoch is in seconds which does not work, it has to be in millisecond accuracy). Not setting any timestamp parameter will returns paginated json of all the entry in db. +GET `/log/api-stats` this endpoint emits the rpc interface call counts and avg tps along with a few a other information. This endpoint support query by time range. i.e `/log/api-stats?start={x}&end={x}`. The parameter value can be either `yyyy-mm-dd` or unix epoch in millisecond. (NOTE standard unix epoch is in seconds which does not work, it has to be in millisecond accuracy). Not setting any timestamp parameter will returns paginated json of all the entry in db. GET `/log/txs` this endpoint return the txs it has been made through rpc server. This endpoint support dynmaic pagination. i.e `/log/txs?max=30&page=9`. Default values are `1000` for `max` and `0` for page. @@ -117,15 +117,21 @@ GET `/log/status` this endpint return status of logging such as date of recordin GET `/log/startTxCapture` this endpoint set the config value to true which control whether to capture incoming txs and store in database. -GET `/log/stopRPCCapture` this endpoint set the config value to false which control whether to capture incoming rpc interface call stat and store in database +GET `/log/stopRPCCapture` this endpoint set the config value to false which control whether to capture incoming rpc interface call stat and store in database. GET `/log/startRPCCapture` this endpoint set the config value to true which control whether to capture rpc interface call stat and store in database. -GET `/log/stopTxCapture` this endpoint set the config value to false which control whether to capture incoming txs and store in database +GET `/log/stopTxCapture` this endpoint set the config value to false which control whether to capture incoming txs and store in database. -GET `/cleanStatTable` this endpoint trigger purging of table that store interface stats +GET `/log/cleanStatTable` this endpoint trigger purging of table that store interface stats. -GET `/cleanTxTable` this endpoint trigger purging of table that store transaction logging +GET `/log/cleanTxTable` this endpoint trigger purging of table that store transaction logging. + +GET `/counts` this endpoint emits the nestedCounters report as an array. + +GET `/counts-reset` this endpoint resets the internal nestedCounters object. + +GET `/api/subsribe` this endpoint changes the subscribed validator node to the ip and port specified in the `ip` and `port` query parameters. # Health Check diff --git a/src/config.ts b/src/config.ts index b1ac6d7f..75c91494 100644 --- a/src/config.ts +++ b/src/config.ts @@ -55,8 +55,6 @@ type Config = { statLog: boolean statLogIntervalSec: number statLogLimit: number - passphrase: string - secret_key: string blockCacheSettings: { lastNBlocksSize: number @@ -166,8 +164,6 @@ export const CONFIG: Config = { statLog: false, statLogIntervalSec: 10, statLogLimit: 10000, - passphrase: process.env.PASSPHRASE || 'sha4d3um', // this is to protect debug routes - secret_key: process.env.SECRET_KEY || 'YsDGSMYHkSBMGD6B4EmD?mFTWG2Wka-Z9b!Jc/CLkrM8eLsBe5abBaTSGeq?6g?P', // this is the private key that rpc server will used to sign jwt token adaptiveRejection: true, filterDeadNodesFromArchiver: false, verbose: false, diff --git a/src/middlewares/authorize.ts b/src/middlewares/authorize.ts deleted file mode 100644 index 01bf62e5..00000000 --- a/src/middlewares/authorize.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { CONFIG } from '../config' -import * as jwt from 'jsonwebtoken' -import { NextFunction, Request, Response } from 'express' - -const authorize = (req: Request, res: Response, next: NextFunction): void => { - const token = req.headers['authorization'] || req.cookies.access_token - - if (!token) { - res.status(401).send({ message: 'No token provided' }) - return - } - - jwt.verify(token, CONFIG.secret_key, (err: Error | null) => { - if (err) { - res.status(401).send({ message: 'unauthorized' }) - return // Ends execution here if there's an error - } - next() // Passes control to the next middleware if there's no error - }) -} - -export default authorize diff --git a/src/middlewares/debugMiddleware.ts b/src/middlewares/debugMiddleware.ts index b93ec3c7..0a73d58d 100644 --- a/src/middlewares/debugMiddleware.ts +++ b/src/middlewares/debugMiddleware.ts @@ -65,18 +65,7 @@ export function handleDebugAuth(_req: any, res: any, next: any, authLevel: any) message: 'FORBIDDEN!', }) } - } else { - // /* prettier-ignore */ if (logFlags.verbose) console.log('Signature is not correct') } - } else { - // if (logFlags.verbose) { - // const parsedCounter = parseInt(sigObj.count) - // if (Number.isNaN(parsedCounter)) { - // console.log('Counter is not a number') - // } else { - // console.log('Counter is not larger than last counter', parsedCounter, lastCounter) - // } - // } } } } diff --git a/src/routes/authenticate.ts b/src/routes/authenticate.ts deleted file mode 100644 index 5266d85f..00000000 --- a/src/routes/authenticate.ts +++ /dev/null @@ -1,31 +0,0 @@ -import * as jwt from 'jsonwebtoken' -import express from 'express' -export const router = express.Router() -import { CONFIG } from '../config' -import { Request, Response } from 'express' - -router.route('/:passphrase').get(async function (req: Request, res: Response) { - const { passphrase } = req.params - const payload = { user: 'shardeum-dev' } - if (passphrase === CONFIG.passphrase) { - // token don't expire, usually this is bad practice - // for the case being implementing refresh token is overkill - // stolen token worst case scenario our debug data ended up being not useful. - const token = jwt.sign(payload, CONFIG.secret_key) - res.cookie('access_token', token, { - httpOnly: false, - maxAge: 1000 * 60 * 60 * 700, // ~ a month - }) - return res.send({ token: token, message: 'authenticated and authorized for debug api calls' }).status(200) - } - return res.send({ message: 'wrong passphrase' }).status(400) -}) - -router.route('/token-check/:token').get(async function (req: Request, res: Response) { - const { token } = req.params - - jwt.verify(token, CONFIG.secret_key, (err: Error | null) => { - if (err) return res.status(401).send({ valid: false }) - return res.send({ valid: true }).status(200) - }) -}) diff --git a/src/routes/log.ts b/src/routes/log.ts index 27dcc74f..5b329800 100644 --- a/src/routes/log.ts +++ b/src/routes/log.ts @@ -339,7 +339,7 @@ router.route('/cleanTxTable').get(async function (req: Request, res: Response) { }) router.route('/startTxCapture').get(async function (req: Request, res: Response) { - if (CONFIG.recordTxStatus) return res.json({ message: 'Tx recording already enabled' }).status(304) + if (CONFIG.recordTxStatus) return res.json({ message: 'Tx recording already enabled' }).status(204) debug_info.txRecordingStartTime = Date.now() debug_info.txRecordingEndTime = 0 CONFIG.recordTxStatus = true @@ -347,7 +347,7 @@ router.route('/startTxCapture').get(async function (req: Request, res: Response) res.json({ message: 'Transaction status recording enabled' }).status(200) }) router.route('/stopTxCapture').get(async function (req: Request, res: Response) { - if (!CONFIG.recordTxStatus) return res.json({ message: 'Tx recording already stopped' }).status(304) + if (!CONFIG.recordTxStatus) return res.json({ message: 'Tx recording already stopped' }).status(204) debug_info.txRecordingEndTime = Date.now() CONFIG.recordTxStatus = false res.send({ message: 'Transaction status recording disabled' }).status(200) @@ -355,7 +355,7 @@ router.route('/stopTxCapture').get(async function (req: Request, res: Response) router.route('/startRPCCapture').get(async function (req: Request, res: Response) { if (CONFIG.statLog) { - return res.json({ message: 'Interface stats are recording already' }).status(304) + return res.json({ message: 'Interface stats are recording already' }).status(204) } debug_info.interfaceRecordingStartTime = Date.now() debug_info.interfaceRecordingEndTime = 0 @@ -365,7 +365,7 @@ router.route('/startRPCCapture').get(async function (req: Request, res: Response }) router.route('/stopRPCCapture').get(async function (req: Request, res: Response) { if (!CONFIG.statLog) { - return res.json({ message: 'Interface stats recording already stopped' }).status(304) + return res.json({ message: 'Interface stats recording already stopped' }).status(204) } debug_info.interfaceRecordingEndTime = Date.now() CONFIG.statLog = false @@ -373,7 +373,7 @@ router.route('/stopRPCCapture').get(async function (req: Request, res: Response) }) router.route('/countRPCCapture').get(async function (req: Request, res: Response) { if (!CONFIG.statLog) { - return res.json({ message: 'Interface stats recording disabled' }).status(304) + return res.json({ message: 'Interface stats recording disabled' }).status(204) } res.json(getInterfaceStatCounts()).status(200) }) diff --git a/src/server.ts b/src/server.ts index 4040b022..89f345a7 100644 --- a/src/server.ts +++ b/src/server.ts @@ -6,7 +6,6 @@ import * as WebSocket from 'ws' import cookieParser from 'cookie-parser' import { methods, saveTxStatus } from './api' import { debug_info, setupLogEvents } from './logger' -import authorize from './middlewares/authorize' import injectIP from './middlewares/injectIP' import { setupDatabase } from './storage/sqliteStorage' import { @@ -21,7 +20,6 @@ import { updateEdgeNodeConfig, } from './utils' import { router as logRoute } from './routes/log' -import { router as authenticate } from './routes/authenticate' import { healthCheckRouter } from './routes/healthCheck' import { Request, Response } from 'express' import { CONFIG, CONFIG as config } from './config' @@ -104,24 +102,20 @@ if (config.dashboard.enabled && config.dashboard.dist_path) { // app.set('views', clientDirectory); } -app.get('/api/subscribe', authorize, (req: Request, res: Response) => { +app.get('/api/subscribe', handleDebugAuth, (req: Request, res: Response) => { nestedCountersInstance.countEvent('api', 'subscribe') const query = req.query - if (!query || !req.ip || !query.port) { + if (!query || !query.ip || !query.port) { console.log('Invalid ip or port') return res.end('Invalid ip or port') } - const ip = req.ip || '127.0.0.1' - const port = req.connection.localPort || 9001 - const success = changeNode(ip, port, true) - if (!success) { - res.end(`Ip not in the nodelist ${ip}:${port}, node subscription rejected`) - return - } + const ip = query.ip.toString() || '127.0.0.1' + const port = parseInt(query.port.toString()) || 9001 + changeNode(ip, port) res.end(`Successfully changed to ${ip}:${port}`) }) -app.get('/counts', authorize, (req: Request, res: Response) => { +app.get('/counts', handleDebugAuth, (req: Request, res: Response) => { nestedCountersInstance.countEvent('api', 'counts') const arrayReport = nestedCountersInstance.arrayitizeAndSort(nestedCountersInstance.eventCounters) if (req.headers.accept === 'application/json') { @@ -139,7 +133,7 @@ app.get('/counts', authorize, (req: Request, res: Response) => { } }) -app.get('/counts-reset', authorize, (req: Request, res: Response) => { +app.get('/counts-reset', handleDebugAuth, (req: Request, res: Response) => { nestedCountersInstance.eventCounters = new Map() res.write(`counts reset ${Date.now()}`) res.end() @@ -193,7 +187,6 @@ app.use(async (req: Request, res: Response, next: NextFunction) => { }) app.use('/log', handleDebugAuth, logRoute) -app.use('/authenticate', authenticate) app.use('/', healthCheckRouter) app.use(injectIP) // reject subscription methods from http diff --git a/use_test_key.patch b/use_test_key.patch new file mode 100644 index 00000000..dab7cf15 --- /dev/null +++ b/use_test_key.patch @@ -0,0 +1,13 @@ +diff --git a/src/config.ts b/src/config.ts +index b1ac6d7..27d70ea 100644 +--- a/src/config.ts ++++ b/src/config.ts +@@ -203,5 +203,7 @@ export const CONFIG: Config = { + }, + enableBlockCache: false, + useRoundRobinConsensorSelection: true, +- devPublicKeys: {} ++ devPublicKeys: { ++ '774491f80f47fedb119bb861601490f42bc3ea3b57fc63906c0d08e6d777a592': 3, ++ } + }