Skip to content

Commit 6d7cc83

Browse files
Bill LeoutsakosBill Leoutsakos
authored andcommitted
fix(netsuite): isolate cached credentials
1 parent a352079 commit 6d7cc83

3 files changed

Lines changed: 24 additions & 3 deletions

File tree

‎apps/sim/blocks/blocks/netsuite.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* @vitest-environment node
33
*/
44
import { describe, expect, it } from 'vitest'
5-
import { NETSUITE_TOOL_IDS, NetSuiteBlock, NetSuiteBlockMeta } from './netsuite'
5+
import { NETSUITE_TOOL_IDS, NetSuiteBlock, NetSuiteBlockMeta } from '@/blocks/blocks/netsuite'
66

77
function getSubBlock(id: string) {
88
const subBlock = NetSuiteBlock.subBlocks.find((candidate) => candidate.id === id)

‎apps/sim/tools/netsuite/utils.test.ts‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ import {
1616

1717
const { privateKey, publicKey } = generateKeyPairSync('rsa', { modulusLength: 2048 })
1818
const PRIVATE_KEY = privateKey.export({ type: 'pkcs8', format: 'pem' }).toString()
19+
const { privateKey: alternatePrivateKey } = generateKeyPairSync('rsa', { modulusLength: 2048 })
20+
const ALTERNATE_PRIVATE_KEY = alternatePrivateKey
21+
.export({ type: 'pkcs8', format: 'pem' })
22+
.toString()
1923
const AUTH: NetSuiteAuthParams = {
2024
accountId: '1234567_SB1',
2125
clientId: 'client-id',
@@ -129,6 +133,15 @@ describe('NetSuite shared executor', () => {
129133
expect(expiring.calls.filter((call) => call.url === TOKEN_URL)).toHaveLength(2)
130134
})
131135

136+
it('isolates cached tokens by private-key identity', async () => {
137+
const { calls } = installFetch([jsonResponse({}), jsonResponse({})], 3600)
138+
139+
await executeServerTime()
140+
await executeServerTime({ ...AUTH, privateKey: ALTERNATE_PRIVATE_KEY })
141+
142+
expect(calls.filter((call) => call.url === TOKEN_URL)).toHaveLength(2)
143+
})
144+
132145
it('bounds the cache and evicts the least-recently-inserted identity', async () => {
133146
const { calls } = installFetch([], 3600)
134147
for (let index = 0; index <= 100; index += 1) {

‎apps/sim/tools/netsuite/utils.ts‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { createPrivateKey } from 'node:crypto'
1+
import { createHash, createPrivateKey } from 'node:crypto'
22
import { getErrorMessage } from '@sim/utils/errors'
33
import { SignJWT } from 'jose'
44
import {
@@ -469,7 +469,15 @@ function setCachedToken(cacheKey: string, accessToken: string, expiresAt: number
469469
}
470470

471471
function getCacheKey(accountHost: string, auth: NetSuiteAuthParams): string {
472-
return JSON.stringify([accountHost, auth.clientId.trim(), auth.certificateId.trim()])
472+
const privateKeyFingerprint = createHash('sha256')
473+
.update(auth.privateKey.trim())
474+
.digest('base64url')
475+
return JSON.stringify([
476+
accountHost,
477+
auth.clientId.trim(),
478+
auth.certificateId.trim(),
479+
privateKeyFingerprint,
480+
])
473481
}
474482

475483
function parseJobId(location: string): string | undefined {

0 commit comments

Comments
 (0)