presidium 0.18.7 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SecretsManager.js +88 -53
- package/SecretsManager.test.js +67 -0
- package/package.json +1 -1
package/SecretsManager.js
CHANGED
|
@@ -1,58 +1,93 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
// If you need more information about configurations or implementing the sample code, visit the AWS docs:
|
|
4
|
-
// https://aws.amazon.com/developers/getting-started/nodejs/
|
|
1
|
+
require('rubico/global')
|
|
2
|
+
const AWSSecretsManager = require('aws-sdk/clients/secretsmanager')
|
|
5
3
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
/**
|
|
5
|
+
* @name SecretsManager
|
|
6
|
+
*
|
|
7
|
+
* @synopsis
|
|
8
|
+
* ```coffeescript [specscript]
|
|
9
|
+
* new SecretsManager(options {
|
|
10
|
+
* accessKeyId: string,
|
|
11
|
+
* secretAccessKey: string,
|
|
12
|
+
* region: string,
|
|
13
|
+
* }|{
|
|
14
|
+
* endpoint: string,
|
|
15
|
+
* region: string,
|
|
16
|
+
* }) -> secretsManager Object
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
const SecretsManager = function (options) {
|
|
20
|
+
this.awsSecretsManager = new AWSSecretsManager({
|
|
21
|
+
apiVersion: '2017-10-17',
|
|
22
|
+
...pick([
|
|
23
|
+
'accessKeyId',
|
|
24
|
+
'secretAccessKey',
|
|
25
|
+
'region',
|
|
26
|
+
'endpoint',
|
|
27
|
+
])(options),
|
|
28
|
+
})
|
|
29
|
+
}
|
|
12
30
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
31
|
+
/**
|
|
32
|
+
* @name SecretsManager.prototype.createSecret
|
|
33
|
+
*
|
|
34
|
+
* @synopsis
|
|
35
|
+
* ```coffeescript [specscript]
|
|
36
|
+
* new SecretsManager(...).createSecret(
|
|
37
|
+
* name string,
|
|
38
|
+
* secretString string,
|
|
39
|
+
* ) -> result Promise<{
|
|
40
|
+
* ARN: string,
|
|
41
|
+
* Name: string,
|
|
42
|
+
* VersionId: string,
|
|
43
|
+
* }>
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
SecretsManager.prototype.createSecret = function (name, secretString) {
|
|
47
|
+
return this.awsSecretsManager.createSecret({
|
|
48
|
+
Name: name,
|
|
49
|
+
SecretString: secretString,
|
|
50
|
+
}).promise()
|
|
51
|
+
}
|
|
17
52
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
53
|
+
/**
|
|
54
|
+
* @name SecretsManager.prototype.getSecretValue
|
|
55
|
+
*
|
|
56
|
+
* @synopsis
|
|
57
|
+
* ```coffeescript [specscript]
|
|
58
|
+
* new SecretsManager(...).getSecretValue(name string) -> result Promise<{
|
|
59
|
+
* ARN: string,
|
|
60
|
+
* CreatedDate: Date,
|
|
61
|
+
* Name: string,
|
|
62
|
+
* SecretString: string,
|
|
63
|
+
* VersionId: string,
|
|
64
|
+
* VersionStages: Array<string>,
|
|
65
|
+
* }>
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
SecretsManager.prototype.getSecretValue = function (name) {
|
|
69
|
+
return this.awsSecretsManager.getSecretValue({
|
|
70
|
+
SecretId: name,
|
|
71
|
+
}).promise()
|
|
72
|
+
}
|
|
21
73
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
else if (err.code === 'ResourceNotFoundException')
|
|
41
|
-
// We can't find the resource that you asked for.
|
|
42
|
-
// Deal with the exception here, and/or rethrow at your discretion.
|
|
43
|
-
throw err;
|
|
44
|
-
}
|
|
45
|
-
else {
|
|
46
|
-
// Decrypts secret using the associated KMS key.
|
|
47
|
-
// Depending on whether the secret is a string or binary, one of these fields will be populated.
|
|
48
|
-
if ('SecretString' in data) {
|
|
49
|
-
secret = data.SecretString;
|
|
50
|
-
} else {
|
|
51
|
-
let buff = new Buffer(data.SecretBinary, 'base64');
|
|
52
|
-
decodedBinarySecret = buff.toString('ascii');
|
|
53
|
-
}
|
|
54
|
-
}
|
|
74
|
+
/**
|
|
75
|
+
* @name SecretsManager.prototype.deleteSecret
|
|
76
|
+
*
|
|
77
|
+
* @synopsis
|
|
78
|
+
* ```coffeescript [specscript]
|
|
79
|
+
* new SecretsManager(...).deleteSecret(name string) -> result Promise<{
|
|
80
|
+
* ARN: string,
|
|
81
|
+
* DeletionDate: Date,
|
|
82
|
+
* Name: string,
|
|
83
|
+
* }>
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
SecretsManager.prototype.deleteSecret = function (name) {
|
|
87
|
+
return this.awsSecretsManager.deleteSecret({
|
|
88
|
+
SecretId: name,
|
|
89
|
+
ForceDeleteWithoutRecovery: true,
|
|
90
|
+
}).promise()
|
|
91
|
+
}
|
|
55
92
|
|
|
56
|
-
|
|
57
|
-
});
|
|
58
|
-
*/
|
|
93
|
+
module.exports = SecretsManager
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const Test = require('thunk-test')
|
|
2
|
+
const assert = require('assert')
|
|
3
|
+
const AwsCredentials = require('./internal/AwsCredentials')
|
|
4
|
+
const SecretsManager = require('./SecretsManager')
|
|
5
|
+
|
|
6
|
+
const test = new Test('SecretsManager', async function () {
|
|
7
|
+
const awsCreds = await AwsCredentials('default').catch(error => {
|
|
8
|
+
if (error.code == 'ENOENT') {
|
|
9
|
+
const accessKeyId = process.env.AWS_ACCESS_KEY_ID
|
|
10
|
+
const secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY
|
|
11
|
+
if (accessKeyId == null || secretAccessKey == null) {
|
|
12
|
+
throw new Error('No AWS credential file or environment variables')
|
|
13
|
+
}
|
|
14
|
+
return { accessKeyId, secretAccessKey }
|
|
15
|
+
}
|
|
16
|
+
throw error
|
|
17
|
+
})
|
|
18
|
+
awsCreds.region = 'us-west-1'
|
|
19
|
+
|
|
20
|
+
const secretsManager = new SecretsManager({ ...awsCreds })
|
|
21
|
+
|
|
22
|
+
const mySecret = {
|
|
23
|
+
name: `test-secret-${Math.trunc(Math.random() * 1e6)}`,
|
|
24
|
+
value: 'helloworld',
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let didRerunTooSoon = false
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
const result = await secretsManager.createSecret(mySecret.name, mySecret.value)
|
|
31
|
+
assert.equal(result.Name, mySecret.name)
|
|
32
|
+
} catch (error) {
|
|
33
|
+
if (error.message.includes('scheduled for deletion')) {
|
|
34
|
+
didRerunTooSoon = true
|
|
35
|
+
} else {
|
|
36
|
+
throw error
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
const result = await secretsManager.getSecretValue(mySecret.name)
|
|
42
|
+
assert.equal(result.Name, mySecret.name)
|
|
43
|
+
assert.equal(result.SecretString, mySecret.value)
|
|
44
|
+
} catch (error) {
|
|
45
|
+
if (error.message.includes('marked for deletion')) {
|
|
46
|
+
didRerunTooSoon = true
|
|
47
|
+
} else {
|
|
48
|
+
throw error
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
{
|
|
53
|
+
const result = await secretsManager.deleteSecret(mySecret.name, mySecret.value)
|
|
54
|
+
assert.equal(result.Name, mySecret.name)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (didRerunTooSoon) {
|
|
58
|
+
throw new Error('Reran test too soon, please try in a few seconds')
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
}).case()
|
|
62
|
+
|
|
63
|
+
if (process.argv[1] == __filename) {
|
|
64
|
+
test()
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
module.exports = test
|