Skip to content
This repository was archived by the owner on Nov 24, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
dc56a5e
feat: relay security setup / health check
rem1niscence Sep 6, 2022
a996a25
feat: add relay security integration
rem1niscence Sep 6, 2022
b98b10e
fix: api fails without default value for security url
rem1niscence Sep 6, 2022
16eee0d
fix: add default value for tests in relay security
rem1niscence Sep 6, 2022
1780f17
infra: [temp] deploy relay security integration to staging
rem1niscence Sep 8, 2022
c906531
Merge pull request #947 from pokt-foundation/staging
rem1niscence Sep 15, 2022
1300395
Merge pull request #950 from pokt-foundation/staging
rem1niscence Sep 15, 2022
9851bf6
Merge pull request #956 from pokt-foundation/staging
rem1niscence Sep 18, 2022
04751ea
Merge pull request #960 from pokt-foundation/staging
rem1niscence Sep 22, 2022
7a2717f
Merge pull request #962 from pokt-foundation/staging
rem1niscence Sep 22, 2022
d114103
Merge pull request #968 from pokt-foundation/staging
rem1niscence Oct 10, 2022
b08ba6d
Merge pull request #972 from pokt-foundation/staging
rem1niscence Oct 14, 2022
0107c91
Merge pull request #980 from pokt-foundation/staging
crisog Oct 19, 2022
de576ce
Merge pull request #1000 from pokt-foundation/develop
crisog Nov 28, 2022
5d11b1a
Merge pull request #1003 from pokt-foundation/develop
rem1niscence Nov 30, 2022
192b560
Merge pull request #996 from pokt-foundation/staging
rem1niscence Nov 28, 2022
24d37e1
Merge pull request #1005 from pokt-foundation/staging
rem1niscence Nov 30, 2022
8083438
Merge pull request #1008 from pokt-foundation/develop
crisog Dec 8, 2022
b245da3
Merge pull request #1011 from pokt-foundation/staging
crisog Dec 8, 2022
b88cf1a
Merge pull request #1013 from pokt-foundation/develop
crisog Dec 8, 2022
df7ba99
Merge pull request #1014 from pokt-foundation/staging
crisog Dec 8, 2022
cf353c3
Merge branch 'master' into relay-security-integration
rem1niscence Dec 12, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,633 changes: 1,633 additions & 0 deletions result.txt

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions src/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import crypto from 'crypto'
import os from 'os'
import path from 'path'
import process from 'process'
import axios from 'axios'
import Redis from 'ioredis'
import pg from 'pg'
import { BootMixin } from '@loopback/boot'
Expand Down Expand Up @@ -71,6 +72,8 @@ export class PocketGatewayApplication extends BootMixin(ServiceMixin(RepositoryM
ALTRUIST_ONLY_CHAINS,
REDIS_LOCAL_TTL_FACTOR,
RATE_LIMITER_URL,
RELAY_SECURITY_URL,
RELAY_SECURITY_HEALTHCHECK_PATH,
RATE_LIMITER_TOKEN,
GATEWAY_HOST,
}: // eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand All @@ -90,6 +93,8 @@ export class PocketGatewayApplication extends BootMixin(ServiceMixin(RepositoryM
const altruistOnlyChains: string[] = (ALTRUIST_ONLY_CHAINS || '').replace(' ', '').split(',')
const ttlFactor = parseFloat(REDIS_LOCAL_TTL_FACTOR) || 1
const rateLimiterURL: string = RATE_LIMITER_URL || ''
const relaySecurityURL: string = RELAY_SECURITY_URL || ''
const relaySecurityHealthCheckPath = RELAY_SECURITY_HEALTHCHECK_PATH || ''
const rateLimiterToken: string = RATE_LIMITER_TOKEN || ''
const gatewayHost: string = GATEWAY_HOST || 'localhost'

Expand Down Expand Up @@ -194,6 +199,20 @@ export class PocketGatewayApplication extends BootMixin(ServiceMixin(RepositoryM
}
this.bind('influxWriteAPIs').to(influxWriteAPIs)

// HealthCheck relay security, first set to undefined until health check pass to avoid errors
this.bind('relaySecurityURL').to(undefined)
if (relaySecurityURL) {
try {
await axios({
method: 'GET',
url: `${relaySecurityURL}${relaySecurityHealthCheckPath}`,
})
this.bind('relaySecurityURL').to(relaySecurityURL)
} catch (error) {
logger.log('warn', 'Error on relay security health check: ' + error)
}
}

// Create a UID for this process
const parts = [os.hostname(), process.pid, +new Date()]
const hash = crypto.createHash('md5').update(parts.join(''))
Expand Down
2 changes: 2 additions & 0 deletions src/controllers/v1.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export class V1Controller {
@inject('altruistOnlyChains') private altruistOnlyChains: string[],
@inject('dispatchURL') private dispatchURL: string,
@inject('rateLimiterURL') private rateLimiterURL: string,
@inject('relaySecurityURL') private relaySecurityURL: string,
@inject('rateLimiterToken') private rateLimiterToken: string,
@inject('gatewayHost') private gatewayHost: string,
@repository(ApplicationsRepository)
Expand Down Expand Up @@ -116,6 +117,7 @@ export class V1Controller {
alwaysRedirectToAltruists: this.alwaysRedirectToAltruists,
altruistOnlyChains: this.altruistOnlyChains,
dispatchers: this.dispatchURL,
relaySecurityURL: this.relaySecurityURL,
request: this.request,
})
}
Expand Down
2 changes: 2 additions & 0 deletions src/observers/environment.observer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ export class EnvironmentObserver implements LifeCycleObserver {
'ALTRUIST_ONLY_CHAINS',
'REDIS_LOCAL_TTL_FACTOR',
'RATE_LIMITER_URL',
'RELAY_SECURITY_URL',
'RELAY_SECURITY_HEALTHCHECK_PATH',
'RATE_LIMITER_TOKEN',
]

Expand Down
31 changes: 30 additions & 1 deletion src/services/pocket-relayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { enforceEVMRestrictions } from '../utils/evm/restrictions'
import { getApplicationPublicKey } from '../utils/helpers'
import { parseJSONRPCError, parseMethod, parseRawData, parseRPCID } from '../utils/parsing'
import { filterCheckedNodes, isCheckPromiseResolved, loadBlockchain } from '../utils/relayer'
import { sendRelayForVerification } from '../utils/security/security'
import { CheckResult, RelayResponse, SendRelayOptions } from '../utils/types'
import { Cache } from './cache'
import { NodeSticker } from './node-sticker'
Expand Down Expand Up @@ -55,6 +56,7 @@ export class PocketRelayer {
alwaysRedirectToAltruists: boolean
altruistOnlyChains: string[]
dispatchers: string
relaySecurityURL: string
requestURL: string

constructor({
Expand All @@ -79,6 +81,7 @@ export class PocketRelayer {
alwaysRedirectToAltruists = false,
altruistOnlyChains = [],
dispatchers,
relaySecurityURL,
request,
}: {
host: string
Expand All @@ -102,6 +105,7 @@ export class PocketRelayer {
alwaysRedirectToAltruists?: boolean
altruistOnlyChains?: string[]
dispatchers?: string
relaySecurityURL?: string
request?: Request
}) {
this.host = host
Expand All @@ -125,6 +129,7 @@ export class PocketRelayer {
this.alwaysRedirectToAltruists = alwaysRedirectToAltruists
this.altruistOnlyChains = altruistOnlyChains
this.dispatchers = dispatchers
this.relaySecurityURL = relaySecurityURL
this.requestURL = `${request?.headers?.host}${request?.url}`
}

Expand Down Expand Up @@ -333,6 +338,31 @@ export class PocketRelayer {
serviceNode: relay.serviceNode.publicKey,
})
})
// Send relay for security check
if (this.relaySecurityURL) {
sendRelayForVerification(
this.relaySecurityURL,
{
applicationID,
blockchainID,
applicationPublicKey,
sessionKey: this.session.key,
nodePublicKey: relay.serviceNode.publicKey,
request: rawData.toString(),
response: relay.response,
altruist: blockchainAltruist + blockchainPath,
blockHeightRequest: blockchainSyncCheck.body,
syncCheckThreshold: blockchainSyncCheck?.allowance,
},
this.cache
).catch(function (error) {
logger.log('warn', 'error sending relay for verification: ' + error, {
requestID,
typeID: application.id,
serviceNode: relay.serviceNode.publicKey,
})
})
}

// Clear error log
// TODO: Implement servicerPubKey and uncomment
Expand Down Expand Up @@ -680,7 +710,6 @@ export class PocketRelayer {
let nodes: Node[] = session.nodes

this.session = session
// sessionKey = "blockchain and a hash of the all the nodes in this session, sorted by public key"
const { key } = session

this.session = session
Expand Down
63 changes: 63 additions & 0 deletions src/utils/security/security.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import axios from 'axios'
import { Cache } from '../../services/cache'
import { parseMethod, parseRawData } from '../parsing'

const routes = {
getMethods: '/relay/methods',
verifyRelay: '/relay/verify',
}
const methodsKey = 'relay-security-methods'

export type RelayCheck = {
applicationID: string
blockchainID: string
applicationPublicKey: string
sessionKey: string
nodePublicKey: string
request: string
response: string
altruist: string
blockHeightRequest: string
syncCheckThreshold: number
}

export async function sendRelayForVerification(relaySecurityURL: string, check: RelayCheck, cache: Cache) {
const methodsToVerify = await getMethodsToVerify(relaySecurityURL, cache)
const relayMethods = parseMethod(parseRawData(check.request)).split(',')

let send = false
for (const method of relayMethods) {
if (methodsToVerify.includes(method)) {
send = true
break
}
}

if (!send) {
return
}

axios({
method: 'POST',
url: `${relaySecurityURL}${routes.verifyRelay}`,
data: check,
}).catch(function (err) {
throw err
})
}

async function getMethodsToVerify(url: string, cache: Cache): Promise<string[]> {
const cachedMethods = await cache.get(methodsKey)

if (cachedMethods) {
return JSON.parse(cachedMethods)
}

const { data } = await axios({
method: 'GET',
url: `${url}${routes.getMethods}`,
})

await cache.set(methodsKey, JSON.stringify(data), 'EX', 600)
return data
}
1 change: 1 addition & 0 deletions tests/acceptance/test-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export const DUMMY_ENV = {
AWS_REGION: 'test',
BLOCKED_ADDRESSES_URL: 'https://blocked.addresses',
RATE_LIMITER_URL: 'https://rate.limiter',
RELAY_SECURITY_URL: '',
RATE_LIMITER_TOKEN: 'rate-limiter-token',
ALTRUIST_ONLY_CHAINS: '',
GATEWAY_HOST: 'localhost',
Expand Down