vvauth 1.2.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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/index.js +49 -25
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -18,7 +18,7 @@ vauth configuration file is a simple yaml file with a specific macro expansion s
18
18
  The configuration file should abide the following schema
19
19
 
20
20
  ### configuration macro expansion set
21
- * $${profile.XXX} expand to vault entity metadata/custom_metadata vars
21
+ * $${profile.XXX} expand to vault entity metadata and user `.vauth_database` vars
22
22
  * $${env.XXX} expand to local environement vars
23
23
  * $${secrets.XXX} expand to remote scrapped secrets (see the env.paths)
24
24
 
package/index.js CHANGED
@@ -7,6 +7,7 @@ const path = require('path');
7
7
  const url = require('url');
8
8
  const {spawn} = require('child_process');
9
9
  const passthru = require('nyks/child_process/passthru');
10
+ const wait = require('nyks/child_process/wait');
10
11
 
11
12
  const {parse} = require('yaml');
12
13
  const semver = require('semver');
@@ -112,12 +113,12 @@ class vvauth {
112
113
 
113
114
 
114
115
  async set(k, v) {
115
- let {entity_id, identity : {metadata}} = await this._vault_get_profile();
116
- if(!metadata)
117
- metadata = {};
118
- let key_name = `env_${k.toUpperCase()}`;
119
- metadata[key_name] = v;
120
- await this._update_identity(this.VAULT_TOKEN, entity_id, {metadata});
116
+ let {profile, database} = await this._vault_get_profile();
117
+ if(!profile.VAUTH_USER_LOGIN)
118
+ throw "Could not resolve VAUTH_USER_LOGIN from vault identity";
119
+
120
+ database[k.toUpperCase()] = v;
121
+ await this._vault_write(`private/${profile.VAUTH_USER_LOGIN}`, '.vauth_database', database);
121
122
  }
122
123
 
123
124
  async unset(k) {
@@ -125,8 +126,8 @@ class vvauth {
125
126
  }
126
127
 
127
128
  async show() {
128
- let {profile} = await this._vault_get_profile();
129
- return profile;
129
+ let {profile, database} = await this._vault_get_profile();
130
+ return {...database, ...profile};
130
131
  }
131
132
 
132
133
  async _vault_get_profile() {
@@ -137,22 +138,18 @@ class vvauth {
137
138
 
138
139
  let {entity_id} = await this._lookup_token(this.VAULT_TOKEN);
139
140
  let identity = await this._lookup_identity(this.VAULT_TOKEN, entity_id);
140
- let profile = {};
141
- for(let alias of identity.aliases) {
142
- for(let [k, v] of Object.entries(alias.custom_metadata || {})) {
143
- if(k.startsWith('env_'))
144
- profile[k.substr(4)] = v;
145
- }
146
- }
147
- for(let [k, v] of Object.entries(identity.metadata || {})) {
148
- if(k.startsWith('env_'))
149
- profile[k.substr(4)] = v;
150
- }
151
- return {entity_id, identity, profile};
141
+ let profile = {...(identity.metadata || {})};
142
+ let database = {};
143
+
144
+ if(profile.VAUTH_USER_LOGIN)
145
+ database = await this._vault_read(`private/${profile.VAUTH_USER_LOGIN}`, '.vauth_database', true);
146
+
147
+ return {entity_id, identity, profile, database};
152
148
  }
153
149
 
154
150
  async _get_env() {
155
- let {profile} = await this._vault_get_profile();
151
+ let {profile, database} = await this._vault_get_profile();
152
+ profile = {...database, ...profile};
156
153
 
157
154
  let env = {VAULT_TOKEN : this.VAULT_TOKEN, VAULT_ADDR : this.VAULT_ADDR}, secrets = {},
158
155
  {git, map = {}, paths, path : mount = "secrets"} = this.rc.env || {};
@@ -163,7 +160,14 @@ class vvauth {
163
160
  let child = spawn('ssh-agent-crypt', ["-decrypt", identity]);
164
161
 
165
162
  child.stdin.end(fs.readFileSync(path));
166
- const result = JSON.parse(await drain(child.stdout));
163
+ child.stderr.pipe(process.stderr);
164
+
165
+ const [exit, body] = await Promise.all([wait(child, false), drain(child.stdout)]);
166
+ if(exit !== 0) {
167
+ console.error("Could not expand armored %s using %s", path, identity);
168
+ process.exit();
169
+ }
170
+ const result = JSON.parse(body);
167
171
  secrets = {...secrets, ...result};
168
172
  }
169
173
 
@@ -211,11 +215,31 @@ class vvauth {
211
215
  return env;
212
216
  }
213
217
 
214
- async _vault_read(mount, secret_path) {
218
+ async _vault_read(mount, secret_path, optional = false) {
215
219
  let remote_url = `${trim(this.VAULT_ADDR, '/')}/v1/${mount}/data/${trim(secret_path, '/')}`;
216
- let query = {...url.parse(remote_url), headers : {'x-vault-token' : this.VAULT_TOKEN}, expect : 200};
220
+ let query = {...url.parse(remote_url), headers : {'x-vault-token' : this.VAULT_TOKEN}};
217
221
  let res = await request(query);
218
- return get(JSON.parse(String(await drain(res))), 'data.data');
222
+ let body = String(await drain(res));
223
+
224
+ if(optional && res.statusCode == 404)
225
+ return {};
226
+
227
+ if(res.statusCode != 200)
228
+ throw `Could not read vault secret '${mount}/${trim(secret_path, '/')}' : ${body}`;
229
+
230
+ return get(JSON.parse(body), 'data.data');
231
+ }
232
+
233
+ async _vault_write(mount, secret_path, data) {
234
+ let remote_url = `${trim(this.VAULT_ADDR, '/')}/v1/${mount}/data/${trim(secret_path, '/')}`;
235
+ let query = {...url.parse(remote_url), headers : {'x-vault-token' : this.VAULT_TOKEN}, json : true};
236
+ let res = await request(query, {data});
237
+ let body = String(await drain(res));
238
+
239
+ if(res.statusCode != 200)
240
+ throw `Could not write vault secret '${mount}/${trim(secret_path, '/')}' : ${body}`;
241
+
242
+ return body ? JSON.parse(body) : {};
219
243
  }
220
244
 
221
245
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vvauth",
3
- "version": "1.2.1",
3
+ "version": "2.0.0",
4
4
  "description": "Vault Auth helper",
5
5
  "main": "index.js",
6
6
  "bin": {