vvauth 0.1.5 → 0.2.1
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/index.js +115 -27
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -22,57 +22,59 @@ const replaceEnv = require('nyks/string/replaceEnv');
|
|
|
22
22
|
const debug = require('debug');
|
|
23
23
|
|
|
24
24
|
const logger = {
|
|
25
|
-
debug : debug('
|
|
26
|
-
info : debug('
|
|
27
|
-
error : debug('
|
|
25
|
+
debug : debug('vvauth:debug'),
|
|
26
|
+
info : debug('vvauth:info'),
|
|
27
|
+
error : debug('vvauth:error'),
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
const VAUTH_RC = process.env.VAUTHRC
|
|
31
|
+
const VAUTH_RC = [process.env.VAUTHRC, path.join(process.cwd(), ".vauthrc"), path.join(os.homedir(), ".vauthrc")];
|
|
32
32
|
const FUNCTION_NAME = "vauth";
|
|
33
33
|
const FUNCTION_DECL = "function vauth() { source <(/usr/bin/env vvauth --ir://raw --source --ir://run=$1 \"${@:2}\"); }";
|
|
34
34
|
|
|
35
35
|
class vvauth {
|
|
36
36
|
constructor(rc = null) {
|
|
37
|
+
|
|
37
38
|
this.rc = {};
|
|
38
39
|
if(rc) {
|
|
39
40
|
this.rc = rc;
|
|
40
41
|
} else {
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
let vauth_rc = VAUTH_RC.filter(path => path && fs.existsSync(path))[0];
|
|
43
|
+
if(vauth_rc) {
|
|
44
|
+
let body = fs.readFileSync(vauth_rc, 'utf8');
|
|
43
45
|
this.rc = walk(parse(body), v => replaceEnv(v, { env : process.env}));
|
|
44
46
|
}
|
|
45
47
|
}
|
|
46
48
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
+
this.vault_addr = this.rc.vault_addr;
|
|
50
|
+
|
|
51
|
+
if(!this.vault_addr)
|
|
49
52
|
throw `Invalid vault remote`;
|
|
50
|
-
|
|
53
|
+
|
|
54
|
+
this.VAULT_TOKEN = process.env.VAULT_TOKEN;
|
|
55
|
+
console.error("vauth bound to '%s'", this.vault_addr);
|
|
51
56
|
}
|
|
52
57
|
|
|
53
|
-
async
|
|
54
|
-
let {
|
|
58
|
+
async connect() {
|
|
59
|
+
let {VAULT_TOKEN, rc : {ssh_auth, jwt_auth}} = this;
|
|
55
60
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
token = await this._login_vault_ssh({...ssh_auth, vault_addr});
|
|
61
|
+
if(!VAULT_TOKEN && ssh_auth && process.env.SSH_AUTH_SOCK)
|
|
62
|
+
VAULT_TOKEN = await this._login_vault_ssh({...ssh_auth});
|
|
59
63
|
|
|
60
|
-
if(!
|
|
64
|
+
if(!VAULT_TOKEN && jwt_auth && jwt_auth.jwt) {
|
|
61
65
|
let {path, jwt, role} = jwt_auth, payload = {jwt, role};
|
|
62
|
-
|
|
66
|
+
VAULT_TOKEN = await this._login_vault(path, payload);
|
|
63
67
|
}
|
|
64
|
-
|
|
68
|
+
this.VAULT_TOKEN = VAULT_TOKEN;
|
|
65
69
|
}
|
|
66
70
|
|
|
67
71
|
async login(source = false) {
|
|
68
|
-
|
|
69
|
-
let VAULT_TOKEN = await this._get_token();
|
|
72
|
+
await this.connect();
|
|
70
73
|
if(source) {
|
|
71
|
-
let env = {VAULT_TOKEN};
|
|
74
|
+
let env = {VAULT_TOKEN : this.VAULT_TOKEN};
|
|
72
75
|
this._publish_env(env);
|
|
73
76
|
process.exit();
|
|
74
77
|
}
|
|
75
|
-
return VAULT_TOKEN;
|
|
76
78
|
}
|
|
77
79
|
|
|
78
80
|
_publish_env(env) {
|
|
@@ -84,7 +86,70 @@ class vvauth {
|
|
|
84
86
|
process.stdout.write(cmds.join("\n") + "\n");
|
|
85
87
|
}
|
|
86
88
|
|
|
87
|
-
|
|
89
|
+
|
|
90
|
+
async set(k, v) {
|
|
91
|
+
let {entity_id, identity : {metadata}} = await this._get_profile();
|
|
92
|
+
if(!metadata)
|
|
93
|
+
metadata = {};
|
|
94
|
+
let key_name = `env_${k.toUpperCase()}`;
|
|
95
|
+
metadata[key_name] = v;
|
|
96
|
+
await this._update_identity(this.VAULT_TOKEN, entity_id, {metadata});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async unset(k) {
|
|
100
|
+
await this.set(k, undefined);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async show() {
|
|
104
|
+
let {profile} = await this._get_profile();
|
|
105
|
+
return profile;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async _get_profile() {
|
|
109
|
+
await this.connect();
|
|
110
|
+
let {entity_id} = await this._lookup_token(this.VAULT_TOKEN);
|
|
111
|
+
let identity = await this._lookup_identity(this.VAULT_TOKEN, entity_id);
|
|
112
|
+
let profile = {};
|
|
113
|
+
for(let alias of identity.aliases) {
|
|
114
|
+
for(let [k, v] of Object.entries(alias.custom_metadata || {})) {
|
|
115
|
+
if(k.startsWith('env_'))
|
|
116
|
+
profile[k.substr(4)] = v;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
for(let [k, v] of Object.entries(identity.metadata || {})) {
|
|
120
|
+
if(k.startsWith('env_'))
|
|
121
|
+
profile[k.substr(4)] = v;
|
|
122
|
+
}
|
|
123
|
+
return {entity_id, identity, profile};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async env(source = false) {
|
|
127
|
+
let {profile} = await this._get_profile();
|
|
128
|
+
|
|
129
|
+
let env = {VAULT_TOKEN : this.VAULT_TOKEN}, {env : {git, map}} = this.rc;
|
|
130
|
+
if(git) {
|
|
131
|
+
map = {...map,
|
|
132
|
+
"GIT_COMMITTER_NAME" : "VAUTH_USER_NAME",
|
|
133
|
+
"GIT_COMMITTER_EMAIL" : "VAUTH_USER_MAIL",
|
|
134
|
+
"GIT_AUTHOR_EMAIL" : "VAUTH_USER_MAIL",
|
|
135
|
+
"GIT_AUTHOR_NAME" : "VAUTH_USER_NAME",
|
|
136
|
+
"GIT_USER_LOGIN" : "VAUTH_USER_LOGIN",
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
for(let [k, v] of Object.entries(map || {})) {
|
|
141
|
+
if(profile[v])
|
|
142
|
+
env[k] = profile[v];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if(source) {
|
|
146
|
+
this._publish_env(env);
|
|
147
|
+
process.exit();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async _login_vault_ssh({path = 'ssh', role}) {
|
|
152
|
+
logger.info("Trying to auth as '%s'", role);
|
|
88
153
|
let sock;
|
|
89
154
|
await new Promise(resolve => (sock = net.connect(process.env.SSH_AUTH_SOCK, resolve)));
|
|
90
155
|
let agent = new SSHAgent(sock);
|
|
@@ -95,7 +160,7 @@ class vvauth {
|
|
|
95
160
|
if(token)
|
|
96
161
|
return;
|
|
97
162
|
|
|
98
|
-
let remote_url = `${trim(vault_addr, '/')}/v1/auth/${path}/nonce`;
|
|
163
|
+
let remote_url = `${trim(this.vault_addr, '/')}/v1/auth/${path}/nonce`;
|
|
99
164
|
let query = {...url.parse(remote_url), json : true};
|
|
100
165
|
let res = await request(query);
|
|
101
166
|
let {data : {nonce}} = JSON.parse(String(await drain(res)));
|
|
@@ -105,7 +170,7 @@ class vvauth {
|
|
|
105
170
|
|
|
106
171
|
const payload = {public_key, role, nonce : Buffer.from(nonce).toString('base64'), signature};
|
|
107
172
|
try {
|
|
108
|
-
token = await this._login_vault(
|
|
173
|
+
token = await this._login_vault(path, payload);
|
|
109
174
|
} catch(err) {
|
|
110
175
|
logger.debug("ssh : invalid challenge for public key", comment);
|
|
111
176
|
}
|
|
@@ -137,8 +202,32 @@ class vvauth {
|
|
|
137
202
|
console.error(`Installation ok, please \nsource ${bashrc_path}`);
|
|
138
203
|
}
|
|
139
204
|
|
|
140
|
-
async
|
|
141
|
-
let remote_url = `${trim(vault_addr, '/')}/v1/auth
|
|
205
|
+
async _lookup_token(token) {
|
|
206
|
+
let remote_url = `${trim(this.vault_addr, '/')}/v1/auth/token/lookup-self`;
|
|
207
|
+
let query = {...url.parse(remote_url), headers : {'x-vault-token' : token}, expect : 200};
|
|
208
|
+
let res = await request(query);
|
|
209
|
+
let response = JSON.parse(await drain(res)).data;
|
|
210
|
+
return response;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
async _lookup_identity(token, id) {
|
|
214
|
+
let remote_url = `${trim(this.vault_addr, '/')}/v1/identity/entity/id/${id}`;
|
|
215
|
+
let query = {...url.parse(remote_url), headers : {'x-vault-token' : token}, expect : 200};
|
|
216
|
+
let res = await request(query);
|
|
217
|
+
return JSON.parse(String(await drain(res))).data;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
async _update_identity(token, id, payload) {
|
|
221
|
+
let remote_url = `${trim(this.vault_addr, '/')}/v1/identity/entity/id/${id}`;
|
|
222
|
+
let query = {...url.parse(remote_url), headers : {'x-vault-token' : token}, expect : 204, json : true};
|
|
223
|
+
await request(query, payload);
|
|
224
|
+
return payload;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
async _login_vault(path, payload) {
|
|
230
|
+
let remote_url = `${trim(this.vault_addr, '/')}/v1/auth/${path}/login`;
|
|
142
231
|
let query = {...url.parse(remote_url), json : true};
|
|
143
232
|
let res = await request(query, payload);
|
|
144
233
|
let response = String(await drain(res));
|
|
@@ -147,7 +236,6 @@ class vvauth {
|
|
|
147
236
|
throw `Could not login to vault : ${response}`;
|
|
148
237
|
|
|
149
238
|
response = JSON.parse(response);
|
|
150
|
-
//console.log(response);
|
|
151
239
|
let token = get(response, 'auth.client_token');
|
|
152
240
|
return token;
|
|
153
241
|
}
|