Skip to content
This repository was archived by the owner on Jul 26, 2022. It is now read-only.

Commit 95827bc

Browse files
sonotsFlydiverny
andauthored
feat(secretsManager): add support for versionId in AWS Secrets Manager (#436)
* AWS Secrets Manager: Support versionId Co-authored-by: Markus Maga <[email protected]>
1 parent 8eb0fbe commit 95827bc

File tree

5 files changed

+49
-3
lines changed

5 files changed

+49
-3
lines changed

README.md

+5
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,11 @@ spec:
279279
# Version Stage in Secrets Manager
280280
versionStage: AWSPREVIOUS
281281
property: password_previous
282+
- key: hello-service/credentials
283+
name: password
284+
# Version ID in Secrets Manager
285+
versionId: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
286+
property: password_versioned
282287
```
283288

284289
alternatively you can use `dataFrom` and get all the values from hello-service/credentials:

lib/backends/kv-backend.test.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ describe('kv-backend', () => {
134134
it('fetches secret property with version', async () => {
135135
kvBackend._get.onFirstCall().resolves('fakePropertyValue1')
136136
kvBackend._get.onSecondCall().resolves('fakePropertyValue2')
137+
kvBackend._get.onThirdCall().resolves('fakePropertyValue3')
137138

138139
const secretPropertyValues = await kvBackend._fetchDataValues({
139140
data: [{
@@ -143,6 +144,10 @@ describe('kv-backend', () => {
143144
key: 'fakePropertyKey2',
144145
versionStage: 'AWSPREVIOUS',
145146
name: 'fakePropertyName2'
147+
}, {
148+
key: 'fakePropertyKey3',
149+
versionId: 'ea9ef8d7-ea54-4a3b-b24b-99510e8d7a3d',
150+
name: 'fakePropertyName3'
146151
}],
147152
specOptions: {}
148153
})
@@ -157,7 +162,12 @@ describe('kv-backend', () => {
157162
keyOptions: { versionStage: 'AWSPREVIOUS' },
158163
specOptions: {}
159164
})
160-
expect(secretPropertyValues).deep.equals([{ fakePropertyName1: 'fakePropertyValue1' }, { fakePropertyName2: 'fakePropertyValue2' }])
165+
expect(kvBackend._get.getCall(2).args[0]).to.deep.equal({
166+
key: 'fakePropertyKey3',
167+
keyOptions: { versionId: 'ea9ef8d7-ea54-4a3b-b24b-99510e8d7a3d' },
168+
specOptions: {}
169+
})
170+
expect(secretPropertyValues).deep.equals([{ fakePropertyName1: 'fakePropertyValue1' }, { fakePropertyName2: 'fakePropertyValue2' }, { fakePropertyName3: 'fakePropertyValue3' }])
161171
})
162172
})
163173

lib/backends/secrets-manager-backend.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,12 @@ class SecretsManagerBackend extends KVBackend {
2121
* @param {string} key - Key used to store secret property value in Secrets Manager.
2222
* @param {object} keyOptions - Options for this specific key, eg version etc.
2323
* @param {string} keyOptions.versionStage - Version stage
24+
* @param {string} keyOptions.versionId - Version ID
2425
* @param {object} specOptions - Options for this external secret, eg role
2526
* @param {string} specOptions.roleArn - IAM role arn to assume
2627
* @returns {Promise} Promise object representing secret property value.
2728
*/
28-
async _get ({ key, specOptions: { roleArn }, keyOptions: { versionStage = 'AWSCURRENT' } }) {
29+
async _get ({ key, specOptions: { roleArn }, keyOptions: { versionStage = 'AWSCURRENT', versionId = null } }) {
2930
this._logger.info(`fetching secret property ${key} with role: ${roleArn || 'pods role'}`)
3031

3132
let client = this._client
@@ -41,8 +42,15 @@ class SecretsManagerBackend extends KVBackend {
4142
})
4243
}
4344

45+
let params
46+
if (versionId) {
47+
params = { SecretId: key, VersionId: versionId }
48+
} else {
49+
params = { SecretId: key, VersionStage: versionStage }
50+
}
51+
4452
const data = await client
45-
.getSecretValue({ SecretId: key, VersionStage: versionStage })
53+
.getSecretValue(params)
4654
.promise()
4755

4856
if ('SecretBinary' in data) {

lib/backends/secrets-manager-backend.test.js

+22
Original file line numberDiff line numberDiff line change
@@ -136,5 +136,27 @@ describe('SecretsManagerBackend', () => {
136136
expect(assumeRoleMock.callCount).equals(0)
137137
expect(secretPropertyValue).equals('fakeSecretPropertyValuePreviousVersion')
138138
})
139+
140+
it('returns secret property value with versionId', async () => {
141+
getSecretValuePromise.promise.resolves({
142+
SecretString: 'fakeSecretPropertyValueVersionId'
143+
})
144+
145+
const secretPropertyValue = await secretsManagerBackend._get({
146+
key: 'fakeSecretKey',
147+
specOptions,
148+
keyOptions: {
149+
versionId: 'ea9ef8d7-ea54-4a3b-b24b-99510e8d7a3d'
150+
}
151+
})
152+
153+
expect(clientMock.getSecretValue.calledWith({
154+
SecretId: 'fakeSecretKey',
155+
VersionId: 'ea9ef8d7-ea54-4a3b-b24b-99510e8d7a3d'
156+
})).to.equal(true)
157+
expect(clientFactoryMock.getCall(0).args).deep.equals([])
158+
expect(assumeRoleMock.callCount).equals(0)
159+
expect(secretPropertyValue).equals('fakeSecretPropertyValueVersionId')
160+
})
139161
})
140162
})

lib/poller.js

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const merge = require('lodash.merge')
1414
* @param {string} properties[].property - If the backend secret is an
1515
* object, this is the property name of the value to use.
1616
* @param {string} properties[].versionStage - If the backend supports versioning, eg secretsManager backend
17+
* @param {string} properties[].versionId - If the backend supports versioning, eg secretsManager backend
1718
*/
1819

1920
/** Poller class. */

0 commit comments

Comments
 (0)