Skip to content

Commit

Permalink
Limit access to vault interface
Browse files Browse the repository at this point in the history
  • Loading branch information
appurva21 committed Sep 3, 2024
1 parent ae8fe4c commit ea7a903
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 18 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
unreleased:
fixed bugs:
- GH-1040 Only allow `set`, `get` and `unset` operations on `pm.vault`

5.1.1:
date: 2024-08-01
fixed bugs:
Expand Down
9 changes: 5 additions & 4 deletions lib/sandbox/execute.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const _ = require('lodash'),
PostmanAPI = require('./pmapi'),
PostmanCookieStore = require('./cookie-store'),
createPostmanRequire = require('./pm-require'),
{ Vault, VaultExternal } = require('./vault'),
{ isNonLegacySandbox, getNonLegacyCodeMarker } = require('./non-legacy-codemarkers'),

EXECUTION_RESULT_EVENT_BASE = 'execution.result.',
Expand Down Expand Up @@ -166,6 +167,7 @@ module.exports = function (bridge, glob) {

let waiting,
timers,
vault,
skippedExecution = false;

execution.return.async = false;
Expand All @@ -188,6 +190,7 @@ module.exports = function (bridge, glob) {
}

// remove listener of disconnection event
vault.dispose();
bridge.off(abortEventName);
bridge.off(responseEventName);
bridge.off(cookiesEventName);
Expand Down Expand Up @@ -254,10 +257,7 @@ module.exports = function (bridge, glob) {
disabledAPIs.push('require');
}

// @todo: throw helpful error message if script access to vault is disabled
if (!context.vaultSecrets) {
disabledAPIs.push('vault');
}
vault = new Vault(id, bridge, timers);

// send control to the function that executes the context and prepares the scope
executeContext(scope, code, execution,
Expand All @@ -283,6 +283,7 @@ module.exports = function (bridge, glob) {
},
dispatchAssertions,
new PostmanCookieStore(id, bridge, timers),
VaultExternal(vault.exec.bind(vault)),
createPostmanRequire(options.resolvedPackages, scope),
{ disabledAPIs })
),
Expand Down
2 changes: 1 addition & 1 deletion lib/sandbox/execution.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const _ = require('lodash'),
test: true
},

CONTEXT_VARIABLE_SCOPES = ['_variables', 'environment', 'collectionVariables', 'globals', 'vaultSecrets'],
CONTEXT_VARIABLE_SCOPES = ['_variables', 'environment', 'collectionVariables', 'globals'],

trackingOptions = { autoCompact: true };

Expand Down
15 changes: 11 additions & 4 deletions lib/sandbox/pmapi.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,12 @@ const _ = require('lodash'),
* @param {Function} onSkipRequest - callback to execute when pm.execution.skipRequest() called
* @param {Function} onAssertion - callback to execute when pm.expect() called
* @param {Object} cookieStore - cookie store
* @param {Vault} vault - vault
* @param {Function} requireFn - requireFn
* @param {Object} [options] - options
* @param {Array.<String>} [options.disabledAPIs] - list of disabled APIs
*/
function Postman (execution, onRequest, onSkipRequest, onAssertion, cookieStore, requireFn, options = {}) {
function Postman (execution, onRequest, onSkipRequest, onAssertion, cookieStore, vault, requireFn, options = {}) {
// @todo - ensure runtime passes data in a scope format
let iterationData = new VariableScope();

Expand All @@ -63,7 +64,6 @@ function Postman (execution, onRequest, onSkipRequest, onAssertion, cookieStore,
execution._variables.addLayer(execution.environment.values);
execution._variables.addLayer(execution.collectionVariables.values);
execution._variables.addLayer(execution.globals.values);
execution._variables.addLayer(execution.vaultSecrets.values);

execution.cookies && (execution.cookies.jar = function () {
return new PostmanCookieJar(cookieStore);
Expand Down Expand Up @@ -126,9 +126,16 @@ function Postman (execution, onRequest, onSkipRequest, onAssertion, cookieStore,
}),

/**
* @type {VariableScope}
* @typedef {Object} Vault
*
* @property {VariableScope.get} get
* @property {VariableScope.set} set
* @property {VariableScope.unset} unset
*/
/**
* @type {Vault}
*/
vault: execution.vaultSecrets,
vault: vault,

/**
* @type {VariableScope}
Expand Down
60 changes: 60 additions & 0 deletions lib/sandbox/vault.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
class Vault {
constructor (id, bridge, timers) {
this._bridge = bridge;
this._timers = timers;
this._event = `execution.vault.${id}`;

this.dispose = this._attachListener();
}

_dispatch (...args) {
this._bridge.dispatch(this._event, ...args);
}

_attachListener () {
const handler = (eventId, ...args) => {
this._timers.clearEvent(eventId, ...args);
};

this._bridge.on(this._event, handler);

return () => {
this._bridge.off(this._event, handler);
};
}

exec (...args) {
return new Promise((resolve, reject) => {
const eventId = this._timers.setEvent((err, ...args) => {
if (err) {
return reject(err instanceof Error ? err : new Error(err.message || err));
}

resolve(...args);
});

this._dispatch(eventId, ...args);
});
}
}

const VaultExternal = (vault) => {
return {
get: (key) => {
return vault('get', key);
},

set: (key, value) => {
return vault('set', key, value);
},

unset: (key) => {
return vault('unset', key);
}
};
};

module.exports = {
Vault,
VaultExternal
};
13 changes: 10 additions & 3 deletions types/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Type definitions for postman-sandbox 5.0.0
// Type definitions for postman-sandbox 5.1.1
// Project: https://github.com/postmanlabs/postman-sandbox
// Definitions by: PostmanLabs
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
Expand Down Expand Up @@ -161,12 +161,13 @@ declare function createPostmanRequire(fileCache: FileCache, scope: any): (...par
* @param onSkipRequest - callback to execute when pm.execution.skipRequest() called
* @param onAssertion - callback to execute when pm.expect() called
* @param cookieStore - cookie store
* @param vault - vault
* @param requireFn - requireFn
* @param [options] - options
* @param [options.disabledAPIs] - list of disabled APIs
*/
declare class Postman {
constructor(execution: Execution, onRequest: (...params: any[]) => any, onSkipRequest: (...params: any[]) => any, onAssertion: (...params: any[]) => any, cookieStore: any, requireFn: (...params: any[]) => any, options?: {
constructor(execution: Execution, onRequest: (...params: any[]) => any, onSkipRequest: (...params: any[]) => any, onAssertion: (...params: any[]) => any, cookieStore: any, vault: Vault, requireFn: (...params: any[]) => any, options?: {
disabledAPIs?: string[];
});
/**
Expand All @@ -175,7 +176,7 @@ declare class Postman {
* stored inside of this object.
*/
info: Info;
vault: VariableScope;
vault: Vault;
globals: VariableScope;
environment: VariableScope;
collectionVariables: VariableScope;
Expand Down Expand Up @@ -247,6 +248,12 @@ declare interface Info {
requestId: string;
}

declare type Vault = {
get: VariableScope.get;
set: VariableScope.set;
unset: VariableScope.unset;
};

declare interface Visualizer {
/**
* Set visualizer template and its options
Expand Down
13 changes: 10 additions & 3 deletions types/sandbox/prerequest.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Type definitions for postman-sandbox 5.0.0
// Type definitions for postman-sandbox 5.1.1
// Project: https://github.com/postmanlabs/postman-sandbox
// Definitions by: PostmanLabs
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
Expand Down Expand Up @@ -95,12 +95,13 @@ declare var cheerio;
* @param onSkipRequest - callback to execute when pm.execution.skipRequest() called
* @param onAssertion - callback to execute when pm.expect() called
* @param cookieStore - cookie store
* @param vault - vault
* @param requireFn - requireFn
* @param [options] - options
* @param [options.disabledAPIs] - list of disabled APIs
*/
declare class Postman {
constructor(execution: Execution, onRequest: (...params: any[]) => any, onSkipRequest: (...params: any[]) => any, onAssertion: (...params: any[]) => any, cookieStore: any, requireFn: (...params: any[]) => any, options?: {
constructor(execution: Execution, onRequest: (...params: any[]) => any, onSkipRequest: (...params: any[]) => any, onAssertion: (...params: any[]) => any, cookieStore: any, vault: Vault, requireFn: (...params: any[]) => any, options?: {
disabledAPIs?: string[];
});
/**
Expand All @@ -109,7 +110,7 @@ declare class Postman {
* stored inside of this object.
*/
info: Info;
vault: import("postman-collection").VariableScope;
vault: Vault;
globals: import("postman-collection").VariableScope;
environment: import("postman-collection").VariableScope;
collectionVariables: import("postman-collection").VariableScope;
Expand Down Expand Up @@ -176,6 +177,12 @@ declare interface Info {
requestId: string;
}

declare type Vault = {
get: VariableScope.get;
set: VariableScope.set;
unset: VariableScope.unset;
};

declare interface Visualizer {
/**
* Set visualizer template and its options
Expand Down
13 changes: 10 additions & 3 deletions types/sandbox/test.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Type definitions for postman-sandbox 5.0.0
// Type definitions for postman-sandbox 5.1.1
// Project: https://github.com/postmanlabs/postman-sandbox
// Definitions by: PostmanLabs
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
Expand Down Expand Up @@ -125,12 +125,13 @@ declare var cheerio;
* @param onSkipRequest - callback to execute when pm.execution.skipRequest() called
* @param onAssertion - callback to execute when pm.expect() called
* @param cookieStore - cookie store
* @param vault - vault
* @param requireFn - requireFn
* @param [options] - options
* @param [options.disabledAPIs] - list of disabled APIs
*/
declare class Postman {
constructor(execution: Execution, onRequest: (...params: any[]) => any, onSkipRequest: (...params: any[]) => any, onAssertion: (...params: any[]) => any, cookieStore: any, requireFn: (...params: any[]) => any, options?: {
constructor(execution: Execution, onRequest: (...params: any[]) => any, onSkipRequest: (...params: any[]) => any, onAssertion: (...params: any[]) => any, cookieStore: any, vault: Vault, requireFn: (...params: any[]) => any, options?: {
disabledAPIs?: string[];
});
/**
Expand All @@ -139,7 +140,7 @@ declare class Postman {
* stored inside of this object.
*/
info: Info;
vault: import("postman-collection").VariableScope;
vault: Vault;
globals: import("postman-collection").VariableScope;
environment: import("postman-collection").VariableScope;
collectionVariables: import("postman-collection").VariableScope;
Expand Down Expand Up @@ -212,6 +213,12 @@ declare interface Info {
requestId: string;
}

declare type Vault = {
get: VariableScope.get;
set: VariableScope.set;
unset: VariableScope.unset;
};

declare interface Visualizer {
/**
* Set visualizer template and its options
Expand Down

0 comments on commit ea7a903

Please sign in to comment.