Skip to content

Commit adbdcf8

Browse files
committed
Use proper schema for secrets and renamed type to source
1 parent 825fa9a commit adbdcf8

File tree

3 files changed

+74
-75
lines changed

3 files changed

+74
-75
lines changed

lib/runner/index.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,10 @@ _.assign(Runner.prototype, {
9797
* @param {String} [options.entrypoint.lookupStrategy=idOrName] strategy to lookup the entrypoint [idOrName, path]
9898
* @param {Array<String>} [options.entrypoint.path] path to lookup
9999
* @param {Object} [options.run] Run-specific options, such as options related to the host
100-
* @param {Object} [options.secretResolvers] - Object mapping source types to resolver configs.
100+
* @param {Object} [options.secretResolvers] - Object mapping provider names to resolver configs.
101+
* Keys must match secret.source.provider (e.g. postman, azure, 1password, aws, hashicorp).
101102
* Each resolver config may have:
102-
* - {String} id - (Required) Unique identifier for the resolver (same as secret.source.type)
103+
* - {String} id - (Required) Unique identifier for the resolver (same as secret.source.provider)
103104
* - {String} name - (Required) Human-readable name for the resolver
104105
* - {Function} resolver - (Required) Function(secret, context) that returns resolved value or Promise
105106
* - {Number} [timeout=5000] - (Optional) Timeout in milliseconds (default: 5000)

lib/runner/resolve-secrets.js

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ function createSecretError (code, message, details) {
102102
* Execute a single resolver with timeout and retry support
103103
*
104104
* @param {Function} resolver - The resolver function
105-
* @param {Object} secret - Secret object (source without type)
105+
* @param {Object} secret - Provider-specific secret object (e.g. source.postman)
106106
* @param {Object} context - Resolver context
107107
* @param {Object} options - Execution options
108108
* @param {Number} options.timeout - Timeout in ms
@@ -214,7 +214,7 @@ function executeResolver (resolver, secret, context, options, callback) {
214214
* @param {Object} payload.environment - Environment scope
215215
* @param {Object} payload.globals - Globals scope
216216
* @param {Object} payload.collectionVariables - Collection variables scope
217-
* @param {Object} secretResolvers - Object mapping source types to resolver configs
217+
* @param {Object} secretResolvers - Object mapping provider names to resolver configs
218218
* @param {Function} callback - callback(err)
219219
*/
220220
function resolveSecrets (payload, secretResolvers, callback) {
@@ -249,24 +249,23 @@ function resolveSecrets (payload, secretResolvers, callback) {
249249
async.each(variablesToResolve, function (item, next) {
250250
var variable = item.variable,
251251
source = variable.source,
252-
sourceType = source && source.type,
253-
resolverConfig = sourceType && secretResolvers[sourceType],
254-
secret,
252+
sourceProvider = source && source.provider,
253+
secret = sourceProvider && (source[sourceProvider] || null),
254+
resolverConfig = sourceProvider && secretResolvers[sourceProvider],
255255
context,
256256
errorDetails;
257257

258-
// No resolver for this source type - keep placeholder value
259-
if (!resolverConfig || typeof resolverConfig.resolver !== 'function') {
258+
// No resolver for this provider or invalid source - keep placeholder value
259+
if (!resolverConfig || typeof resolverConfig.resolver !== 'function' || !secret) {
260260
return next();
261261
}
262262

263-
secret = _.omit(source, 'type');
264263
context = buildResolverContext(payload, variable.key);
265264
errorDetails = {
266265
key: variable.key,
267-
secretType: sourceType,
268-
resolverId: resolverConfig.id || sourceType,
269-
resolverName: resolverConfig.name || sourceType
266+
provider: sourceProvider,
267+
resolverId: resolverConfig.id || sourceProvider,
268+
resolverName: resolverConfig.name || sourceProvider
270269
};
271270

272271
executeResolver(resolverConfig.resolver,

test/integration/sanity/secret-resolution.test.js

Lines changed: 61 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ describe('secret resolution', function () {
2222
value: 'placeholder-will-be-replaced',
2323
type: 'secret',
2424
source: {
25-
type: 'mock-secret-manager',
26-
secretId: 'my-api-key-secret'
25+
provider: 'postman',
26+
postman: { type: 'local', secretId: 'my-api-key-secret' }
2727
}
2828
},
2929
{
@@ -33,9 +33,9 @@ describe('secret resolution', function () {
3333
]
3434
},
3535
secretResolvers: {
36-
'mock-secret-manager': {
37-
id: 'mock-resolver-1',
38-
name: 'Mock Secret Manager',
36+
postman: {
37+
id: 'postman-resolver-1',
38+
name: 'Postman Secret Manager',
3939
resolver: function (secret) {
4040
// Return a Promise for async resolution
4141
return new Promise(function (resolve) {
@@ -97,8 +97,8 @@ describe('secret resolution', function () {
9797
value: 'placeholder-will-be-replaced',
9898
type: 'secret',
9999
source: {
100-
type: 'mock-secret-manager',
101-
secretId: 'my-api-key-secret'
100+
provider: 'postman',
101+
postman: { type: 'local', secretId: 'my-api-key-secret' }
102102
}
103103
},
104104
{
@@ -112,9 +112,9 @@ describe('secret resolution', function () {
112112
]
113113
},
114114
secretResolvers: {
115-
'mock-secret-manager': {
116-
id: 'mock-resolver-1',
117-
name: 'Mock Secret Manager',
115+
postman: {
116+
id: 'postman-resolver-1',
117+
name: 'Postman Secret Manager',
118118
resolver: function (secret) {
119119
return new Promise(function (resolve) {
120120
setTimeout(function () {
@@ -176,18 +176,21 @@ describe('secret resolution', function () {
176176
value: '',
177177
type: 'secret',
178178
source: {
179-
type: 'vault',
180-
path: '/secret/data/myapp'
179+
provider: 'hashicorp',
180+
hashicorp: {
181+
engine: 'secret',
182+
path: '/secret/data/myapp',
183+
key: 'value'
184+
}
181185
}
182186
}
183187
]
184188
},
185189
secretResolvers: {
186-
vault: {
187-
id: 'vault-resolver',
188-
name: 'Vault Resolver',
190+
hashicorp: {
191+
id: 'hashicorp-resolver',
192+
name: 'Hashicorp Resolver',
189193
resolver: function () {
190-
// Return a Promise
191194
return new Promise(function (resolve) {
192195
setTimeout(function () {
193196
resolve('promise-resolved-secret');
@@ -233,18 +236,17 @@ describe('secret resolution', function () {
233236
value: 'fallback-value',
234237
type: 'secret',
235238
source: {
236-
type: 'failing-source',
237-
secretId: 'will-fail'
239+
provider: 'postman',
240+
postman: { type: 'local', secretId: 'will-fail' }
238241
}
239242
}
240243
]
241244
},
242245
secretResolvers: {
243-
'failing-source': {
246+
postman: {
244247
id: 'failing-resolver',
245248
name: 'Failing Resolver',
246249
resolver: function () {
247-
// Simulate a failed resolution
248250
return new Promise(function (resolve, reject) {
249251
setTimeout(function () {
250252
reject(new Error('Failed to fetch secret'));
@@ -307,32 +309,32 @@ describe('secret resolution', function () {
307309
key: 'secret1',
308310
value: '',
309311
type: 'secret',
310-
source: { type: 'mock', id: '1' }
312+
source: { provider: 'postman', postman: { type: 'local', secretId: '1' } }
311313
},
312314
{
313315
key: 'secret2',
314316
value: '',
315317
type: 'secret',
316-
source: { type: 'mock', id: '2' }
318+
source: { provider: 'postman', postman: { type: 'local', secretId: '2' } }
317319
},
318320
{
319321
key: 'secret3',
320322
value: '',
321323
type: 'secret',
322-
source: { type: 'mock', id: '3' }
324+
source: { provider: 'postman', postman: { type: 'local', secretId: '3' } }
323325
}
324326
]
325327
},
326328
secretResolvers: {
327-
mock: {
328-
id: 'mock-resolver',
329-
name: 'Mock Resolver',
329+
postman: {
330+
id: 'postman-resolver',
331+
name: 'Postman Resolver',
330332
resolver: function (secret) {
331333
resolverCallCount++;
332334

333335
return new Promise(function (resolve) {
334336
setTimeout(function () {
335-
resolve('secret-value-' + secret.id);
337+
resolve('secret-value-' + secret.secretId);
336338
}, 10);
337339
});
338340
}
@@ -370,7 +372,7 @@ describe('secret resolution', function () {
370372
resolverSpy = sinon.spy(function (secret) {
371373
return new Promise(function (resolve) {
372374
setTimeout(function () {
373-
resolve('resolved-' + secret.id);
375+
resolve('resolved-' + secret.secretId);
374376
}, 10);
375377
});
376378
});
@@ -379,7 +381,6 @@ describe('secret resolution', function () {
379381
collection: {
380382
item: [{
381383
request: {
382-
// Only uses secret1 - secret2 and secret3 are NOT used
383384
url: global.servers.http + '?key1={{secret1}}'
384385
}
385386
}]
@@ -390,26 +391,26 @@ describe('secret resolution', function () {
390391
key: 'secret1',
391392
value: '',
392393
type: 'secret',
393-
source: { type: 'mock', id: '1' }
394+
source: { provider: 'postman', postman: { type: 'local', secretId: '1' } }
394395
},
395396
{
396397
key: 'secret2',
397398
value: '',
398399
type: 'secret',
399-
source: { type: 'mock', id: '2' }
400+
source: { provider: 'postman', postman: { type: 'local', secretId: '2' } }
400401
},
401402
{
402403
key: 'secret3',
403404
value: '',
404405
type: 'secret',
405-
source: { type: 'mock', id: '3' }
406+
source: { provider: 'postman', postman: { type: 'local', secretId: '3' } }
406407
}
407408
]
408409
},
409410
secretResolvers: {
410-
mock: {
411-
id: 'mock-resolver',
412-
name: 'Mock Resolver',
411+
postman: {
412+
id: 'postman-resolver',
413+
name: 'Postman Resolver',
413414
resolver: resolverSpy
414415
}
415416
}
@@ -432,7 +433,7 @@ describe('secret resolution', function () {
432433
it('should resolve only the used secret with correct source', function () {
433434
var secretArg = resolverSpy.getCall(0).args[0];
434435

435-
expect(secretArg.id).to.equal('1');
436+
expect(secretArg.secretId).to.equal('1');
436437
});
437438

438439
it('should resolve the used secret correctly', function () {
@@ -461,8 +462,8 @@ describe('secret resolution', function () {
461462
value: 'original-value',
462463
type: 'secret',
463464
source: {
464-
type: 'some-source',
465-
secretId: 'some-secret'
465+
provider: 'postman',
466+
postman: { type: 'local', secretId: 'some-secret' }
466467
}
467468
}
468469
]
@@ -515,27 +516,27 @@ describe('secret resolution', function () {
515516
key: 'authToken',
516517
value: '',
517518
type: 'secret',
518-
source: { type: 'mock', secretType: 'auth-token' }
519+
source: { provider: 'postman', postman: { type: 'local', secretId: 'auth-token-secret' } }
519520
},
520521
{
521522
key: 'apiKey',
522523
value: '',
523524
type: 'secret',
524-
source: { type: 'mock', secretType: 'api-key' }
525+
source: { provider: 'postman', postman: { type: 'local', secretId: 'api-key-secret' } }
525526
}
526527
]
527528
},
528529
secretResolvers: {
529-
mock: {
530-
id: 'mock-resolver',
531-
name: 'Mock Resolver',
530+
postman: {
531+
id: 'postman-resolver',
532+
name: 'Postman Resolver',
532533
resolver: function (secret) {
533534
return new Promise(function (resolve) {
534535
setTimeout(function () {
535-
if (secret.secretType === 'auth-token') {
536+
if (secret.secretId === 'auth-token-secret') {
536537
resolve('resolved-auth-token-xyz');
537538
}
538-
else if (secret.secretType === 'api-key') {
539+
else if (secret.secretId === 'api-key-secret') {
539540
resolve('resolved-api-key-abc');
540541
}
541542
else {
@@ -589,23 +590,22 @@ describe('secret resolution', function () {
589590
value: 'fallback-value',
590591
type: 'secret',
591592
source: {
592-
type: 'slow-source',
593-
secretId: 'slow-secret'
593+
provider: 'postman',
594+
postman: { type: 'local', secretId: 'slow-secret' }
594595
}
595596
}
596597
]
597598
},
598599
secretResolvers: {
599-
'slow-source': {
600+
postman: {
600601
id: 'slow-resolver',
601602
name: 'Slow Resolver',
602-
timeout: 50, // 50ms timeout
603+
timeout: 50,
603604
resolver: function () {
604-
// This resolver takes longer than the timeout
605605
return new Promise(function (resolve) {
606606
setTimeout(function () {
607607
resolve('should-not-resolve');
608-
}, 200); // 200ms - longer than timeout
608+
}, 200);
609609
});
610610
}
611611
}
@@ -665,21 +665,20 @@ describe('secret resolution', function () {
665665
value: '',
666666
type: 'secret',
667667
source: {
668-
type: 'retry-source',
669-
secretId: 'retry-secret'
668+
provider: 'postman',
669+
postman: { type: 'local', secretId: 'retry-secret' }
670670
}
671671
}
672672
]
673673
},
674674
secretResolvers: {
675-
'retry-source': {
675+
postman: {
676676
id: 'retry-resolver',
677677
name: 'Retry Resolver',
678-
retryCount: 2, // Retry up to 2 times
678+
retryCount: 2,
679679
resolver: function () {
680680
attemptCount++;
681681

682-
// Fail on first 2 attempts, succeed on 3rd
683682
if (attemptCount < 3) {
684683
return Promise.reject(new Error('Temporary failure'));
685684
}
@@ -730,17 +729,17 @@ describe('secret resolution', function () {
730729
value: 'placeholder-value',
731730
type: 'secret',
732731
source: {
733-
type: 'unknown-source-type',
734-
secretId: 'some-secret'
732+
provider: 'azure',
733+
azure: { secretId: 'some-secret' }
735734
}
736735
}
737736
]
738737
},
739738
secretResolvers: {
740-
// Only have resolver for 'mock' type, not 'unknown-source-type'
741-
mock: {
742-
id: 'mock-resolver',
743-
name: 'Mock Resolver',
739+
// Only have resolver for 'postman', not 'azure'
740+
postman: {
741+
id: 'postman-resolver',
742+
name: 'Postman Resolver',
744743
resolver: function () {
745744
return Promise.resolve('should-not-be-called');
746745
}

0 commit comments

Comments
 (0)