node-vault-client 1.0.1 → 2.0.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/LICENSE.txt +200 -200
- package/README.md +337 -154
- package/package.json +64 -44
- package/src/Lease.js +57 -57
- package/src/VaultApiClient.js +94 -55
- package/src/VaultClient.js +288 -263
- package/src/VaultNodeConfig.js +104 -105
- package/src/auth/AuthToken.js +141 -94
- package/src/auth/VaultAppRoleAuth.js +49 -40
- package/src/auth/VaultBaseAuth.js +162 -140
- package/src/auth/VaultIAMAuth.js +212 -187
- package/src/auth/VaultKubernetesAuth.js +49 -48
- package/src/auth/VaultTokenAuth.js +35 -34
- package/src/errors.js +21 -21
|
@@ -1,140 +1,162 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const lt = require('long-timeout');
|
|
4
|
-
const prettyMs = require('pretty-ms');
|
|
5
|
-
const AuthToken = require('./AuthToken');
|
|
6
|
-
const errors = require('../errors');
|
|
7
|
-
|
|
8
|
-
class VaultBaseAuth {
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* @param {VaultApiClient} apiClient
|
|
12
|
-
* @param {Object} logger
|
|
13
|
-
* @param {String} mount - Vault's mount point
|
|
14
|
-
*/
|
|
15
|
-
constructor(apiClient, logger, mount) {
|
|
16
|
-
this.__apiClient = apiClient;
|
|
17
|
-
/** @protected */
|
|
18
|
-
this._log = logger;
|
|
19
|
-
this._mount = mount;
|
|
20
|
-
|
|
21
|
-
/** @type AuthToken */
|
|
22
|
-
this.__authToken = null;
|
|
23
|
-
this.__refreshTimeout = null;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* @protected
|
|
28
|
-
* @returns {Promise<AuthToken>}
|
|
29
|
-
*/
|
|
30
|
-
_authenticate() {
|
|
31
|
-
throw new Error('Method should be overridden');
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
getAuthToken() {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
this.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
*
|
|
80
|
-
* @returns {
|
|
81
|
-
*/
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const lt = require('long-timeout');
|
|
4
|
+
const prettyMs = require('pretty-ms');
|
|
5
|
+
const AuthToken = require('./AuthToken');
|
|
6
|
+
const errors = require('../errors');
|
|
7
|
+
|
|
8
|
+
class VaultBaseAuth {
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {VaultApiClient} apiClient
|
|
12
|
+
* @param {Object} logger
|
|
13
|
+
* @param {String} mount - Vault's mount point
|
|
14
|
+
*/
|
|
15
|
+
constructor(apiClient, logger, mount) {
|
|
16
|
+
this.__apiClient = apiClient;
|
|
17
|
+
/** @protected */
|
|
18
|
+
this._log = logger;
|
|
19
|
+
this._mount = mount;
|
|
20
|
+
|
|
21
|
+
/** @type AuthToken */
|
|
22
|
+
this.__authToken = null;
|
|
23
|
+
this.__refreshTimeout = null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @protected
|
|
28
|
+
* @returns {Promise<AuthToken>}
|
|
29
|
+
*/
|
|
30
|
+
_authenticate() {
|
|
31
|
+
throw new Error('Method should be overridden');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
getAuthToken() {
|
|
35
|
+
const tokenExpired = this.__authToken instanceof AuthToken && this.__authToken.isExpired();
|
|
36
|
+
|
|
37
|
+
if (tokenExpired && !this._reauthenticationAllowed()) {
|
|
38
|
+
return Promise.reject(new errors.AuthTokenExpiredError(
|
|
39
|
+
'Auth token has expired & cannot be refreshed since auth method doesn\'t support this.'
|
|
40
|
+
));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (this.__authToken === null || tokenExpired) {
|
|
44
|
+
this._log.info('getting auth token (mount=%s)', this._mount);
|
|
45
|
+
|
|
46
|
+
const tokenPromise = this._authenticate().then(authToken => {
|
|
47
|
+
this.__authToken = authToken;
|
|
48
|
+
|
|
49
|
+
if (this.__authToken.isRenewable()) {
|
|
50
|
+
this._log.debug(
|
|
51
|
+
'setting refresh timer for token %s',
|
|
52
|
+
authToken.getId()
|
|
53
|
+
);
|
|
54
|
+
this.__setupTokenRefreshTimer(this.__authToken);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return this.__authToken;
|
|
58
|
+
}).catch(e => {
|
|
59
|
+
this.__authToken = null;
|
|
60
|
+
throw e;
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
this.__authToken = tokenPromise;
|
|
64
|
+
return tokenPromise;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
this._log.debug('token already exist');
|
|
68
|
+
return Promise.resolve(this.__authToken);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Cancel any pending token-refresh timer.
|
|
73
|
+
*
|
|
74
|
+
* When a renewable token is fetched the client arms a `long-timeout` timer to renew it
|
|
75
|
+
* before it expires. That timer keeps the Node.js event loop alive, so a short-lived
|
|
76
|
+
* script never exits on its own. Call this (or {@link VaultClient#close}) once you are
|
|
77
|
+
* done with the client to release the event loop. Safe to call when no timer is armed
|
|
78
|
+
* and safe to call multiple times.
|
|
79
|
+
*
|
|
80
|
+
* @returns {void}
|
|
81
|
+
*/
|
|
82
|
+
cancelTokenRefresh() {
|
|
83
|
+
if (this.__refreshTimeout !== null) {
|
|
84
|
+
lt.clearTimeout(this.__refreshTimeout);
|
|
85
|
+
this.__refreshTimeout = null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @protected
|
|
91
|
+
* @returns {Promise<AuthToken>}
|
|
92
|
+
*/
|
|
93
|
+
_getTokenEntity(tokenId) {
|
|
94
|
+
return this.__apiClient.makeRequest('GET', '/auth/token/lookup-self', null, {'X-Vault-Token': tokenId})
|
|
95
|
+
.then(res => {
|
|
96
|
+
return AuthToken.fromResponse(res);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* @protected
|
|
102
|
+
* @returns {boolean}
|
|
103
|
+
*/
|
|
104
|
+
_reauthenticationAllowed() {
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* @param {AuthToken} authToken
|
|
110
|
+
* @private
|
|
111
|
+
*/
|
|
112
|
+
__setupTokenRefreshTimer(authToken) {
|
|
113
|
+
if (this.__refreshTimeout !== null) {
|
|
114
|
+
lt.clearTimeout(this.__refreshTimeout);
|
|
115
|
+
this.__refreshTimeout = null;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (!authToken.isRenewable() || authToken.isExpired()) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const timer = Math.max((authToken.getExpiresAt() - Math.floor(Date.now() / 1000)) / 2, 1) * 1000;
|
|
123
|
+
|
|
124
|
+
this.__refreshTimeout = lt.setTimeout(() => {
|
|
125
|
+
this.__renewToken(authToken).then(authToken => {
|
|
126
|
+
this.__authToken = authToken;
|
|
127
|
+
this.__setupTokenRefreshTimer(authToken);
|
|
128
|
+
}).catch(err => {
|
|
129
|
+
this.__setupTokenRefreshTimer(authToken);
|
|
130
|
+
|
|
131
|
+
this._log.error(`Cannot refresh auth token with "${authToken.getAccessor()}" accessor. Error: ${err.message}`);
|
|
132
|
+
this._log.error(err);
|
|
133
|
+
});
|
|
134
|
+
}, timer);
|
|
135
|
+
|
|
136
|
+
this._log.debug(
|
|
137
|
+
'sleeping for %s',
|
|
138
|
+
prettyMs(timer)
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* @param {AuthToken} authToken
|
|
144
|
+
* @returns {Promise.<AuthToken>}
|
|
145
|
+
* @private
|
|
146
|
+
*/
|
|
147
|
+
__renewToken(authToken) {
|
|
148
|
+
this._log.debug('renewing vault token');
|
|
149
|
+
|
|
150
|
+
return this.__apiClient.makeRequest('POST', '/auth/token/renew-self', null, {'X-Vault-Token': authToken.getId()})
|
|
151
|
+
.then(() => {
|
|
152
|
+
this._log.info('successfully renewed token');
|
|
153
|
+
return this._getTokenEntity(authToken.getId());
|
|
154
|
+
})
|
|
155
|
+
.catch((reason) => {
|
|
156
|
+
this._log.error('token renew failed: %s', reason.message);
|
|
157
|
+
throw reason;
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
module.exports = VaultBaseAuth;
|