@nourmohamed/vaultix-cli 1.0.0 → 1.0.2
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/bin/cli.js +110 -21
- package/package.json +1 -1
package/bin/cli.js
CHANGED
|
@@ -1,51 +1,140 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
const CONFIG_PATH = path.join(os.homedir(), '.vaultix.json');
|
|
7
|
+
|
|
8
|
+
function saveConfig(config) {
|
|
9
|
+
fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function loadConfig() {
|
|
13
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
14
|
+
try {
|
|
15
|
+
return JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8'));
|
|
16
|
+
} catch (e) {
|
|
17
|
+
return {};
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return {};
|
|
21
|
+
}
|
|
4
22
|
|
|
5
23
|
async function run() {
|
|
6
24
|
const args = process.argv.slice(2);
|
|
7
25
|
const command = args[0];
|
|
8
26
|
const target = args[1];
|
|
27
|
+
const config = loadConfig();
|
|
28
|
+
|
|
29
|
+
if (command === 'login') {
|
|
30
|
+
const key = args[1];
|
|
31
|
+
if (!key) {
|
|
32
|
+
console.error('\x1b[31m[Error]\x1b[0m Please provide your API key: vaultix login vtx_your_key');
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const newConfig = { ...config, apiKey: key };
|
|
37
|
+
|
|
38
|
+
// Auto-detect URL from smart token vtx_BASE64URL_HASH
|
|
39
|
+
const parts = key.split('_');
|
|
40
|
+
if (parts.length === 3 && parts[0] === 'vtx') {
|
|
41
|
+
try {
|
|
42
|
+
const decodedUrl = Buffer.from(parts[1], 'base64').toString('utf8');
|
|
43
|
+
if (decodedUrl.startsWith('http')) {
|
|
44
|
+
newConfig.baseUrl = decodedUrl;
|
|
45
|
+
console.log(`\x1b[36m[Auto-Config]\x1b[0m Detected Platform URL: ${decodedUrl}`);
|
|
46
|
+
}
|
|
47
|
+
} catch (e) {
|
|
48
|
+
// Fallback to existing or default
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
saveConfig(newConfig);
|
|
53
|
+
console.log('\x1b[32m[Success]\x1b[0m Authenticated successfully.');
|
|
54
|
+
process.exit(0);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (command === 'config') {
|
|
58
|
+
const key = args[1];
|
|
59
|
+
const val = args[2];
|
|
60
|
+
if (!key || !val) {
|
|
61
|
+
console.log('\x1b[33mUsage:\x1b[0m vaultix config <key> <value>');
|
|
62
|
+
console.log('Available keys: baseUrl');
|
|
63
|
+
console.log(`Current Config: ${JSON.stringify(config, null, 2)}`);
|
|
64
|
+
process.exit(0);
|
|
65
|
+
}
|
|
66
|
+
config[key] = val;
|
|
67
|
+
saveConfig(config);
|
|
68
|
+
console.log(`\x1b[32m[Success]\x1b[0m Config ${key} updated.`);
|
|
69
|
+
process.exit(0);
|
|
70
|
+
}
|
|
9
71
|
|
|
10
72
|
if (!command) {
|
|
11
73
|
console.error(`
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
74
|
+
\x1b[36m--- Vaultix CLI v1.0.2 ---\x1b[0m
|
|
75
|
+
Steps to get started:
|
|
76
|
+
1. \x1b[33mvaultix login <API_KEY> [URL]\x1b[0m (Authenticates your machine)
|
|
77
|
+
2. \x1b[33mvaultix list\x1b[0m (Shows your secrets)
|
|
78
|
+
3. \x1b[33mvaultix get <NAME>\x1b[0m (Retrieves a secret)
|
|
17
79
|
|
|
18
|
-
|
|
80
|
+
Commands:
|
|
81
|
+
vaultix login <KEY> [URL]
|
|
82
|
+
vaultix get <NAME>
|
|
83
|
+
vaultix list
|
|
84
|
+
vaultix set <NAME> <VALUE>
|
|
85
|
+
vaultix delete <NAME>
|
|
86
|
+
vaultix config baseUrl <URL>
|
|
19
87
|
`);
|
|
20
88
|
process.exit(1);
|
|
21
89
|
}
|
|
22
90
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
91
|
+
const { apiKey, baseUrl: configUrl } = loadConfig();
|
|
92
|
+
const token = process.env.VAULTIX_API_KEY || apiKey;
|
|
93
|
+
const baseUrl = process.env.VAULTIX_URL || configUrl || 'http://localhost:3000';
|
|
94
|
+
|
|
95
|
+
if (!token) {
|
|
96
|
+
console.error(`\x1b[31m[Error]\x1b[0m No API key found.`);
|
|
97
|
+
console.log('\x1b[33mTip:\x1b[0m Run "vaultix login <key>" to authenticate.');
|
|
28
98
|
process.exit(1);
|
|
29
99
|
}
|
|
30
100
|
|
|
101
|
+
// Simplified internal client to avoid dependency issues
|
|
102
|
+
const callApi = async (path, method = 'GET', body = null) => {
|
|
103
|
+
try {
|
|
104
|
+
const response = await fetch(`${baseUrl}${path}`, {
|
|
105
|
+
method,
|
|
106
|
+
headers: {
|
|
107
|
+
'Authorization': `Bearer ${token}`,
|
|
108
|
+
'Content-Type': 'application/json'
|
|
109
|
+
},
|
|
110
|
+
body: body ? JSON.stringify(body) : null
|
|
111
|
+
});
|
|
112
|
+
const data = await response.json();
|
|
113
|
+
if (!response.ok) throw new Error(data.error || response.statusText);
|
|
114
|
+
return data;
|
|
115
|
+
} catch (err) {
|
|
116
|
+
throw new Error(`Vaultix API Error: ${err.message}`);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
31
120
|
if (command === 'get') {
|
|
32
121
|
if (!target) {
|
|
33
|
-
console.error('\x1b[31m[Error]\x1b[0m
|
|
122
|
+
console.error('\x1b[31m[Error]\x1b[0m Missing secret name.');
|
|
34
123
|
process.exit(1);
|
|
35
124
|
}
|
|
36
125
|
|
|
37
126
|
try {
|
|
38
|
-
const
|
|
39
|
-
console.log(value);
|
|
127
|
+
const data = await callApi(`/api/v1/secrets/${encodeURIComponent(target)}`);
|
|
128
|
+
console.log(data.value);
|
|
40
129
|
} catch (err) {
|
|
41
130
|
console.error(`\x1b[31m[Error]\x1b[0m ${err.message}`);
|
|
42
131
|
process.exit(1);
|
|
43
132
|
}
|
|
44
133
|
} else if (command === 'list') {
|
|
45
134
|
try {
|
|
46
|
-
const
|
|
135
|
+
const data = await callApi('/api/v1/secrets');
|
|
47
136
|
console.log('\x1b[36m--- Active Secrets ---\x1b[0m');
|
|
48
|
-
secrets.forEach(s => {
|
|
137
|
+
data.secrets.forEach(s => {
|
|
49
138
|
console.log(`\x1b[32m${s.name}\x1b[0m (Service: ${s.service})`);
|
|
50
139
|
});
|
|
51
140
|
} catch (err) {
|
|
@@ -55,12 +144,12 @@ Make sure VAULTIX_API_KEY environment variable is set.
|
|
|
55
144
|
} else if (command === 'set') {
|
|
56
145
|
const value = args[2];
|
|
57
146
|
if (!target || !value) {
|
|
58
|
-
console.error('\x1b[31m[Error]\x1b[0m
|
|
147
|
+
console.error('\x1b[31m[Error]\x1b[0m Usage: vaultix set <NAME> <VALUE>');
|
|
59
148
|
process.exit(1);
|
|
60
149
|
}
|
|
61
150
|
|
|
62
151
|
try {
|
|
63
|
-
await
|
|
152
|
+
await callApi(`/api/v1/secrets/${encodeURIComponent(target)}`, 'PUT', { value });
|
|
64
153
|
console.log(`\x1b[32m[Success]\x1b[0m Secret '${target}' configured successfully.`);
|
|
65
154
|
} catch (err) {
|
|
66
155
|
console.error(`\x1b[31m[Error]\x1b[0m ${err.message}`);
|
|
@@ -68,12 +157,12 @@ Make sure VAULTIX_API_KEY environment variable is set.
|
|
|
68
157
|
}
|
|
69
158
|
} else if (command === 'delete') {
|
|
70
159
|
if (!target) {
|
|
71
|
-
console.error('\x1b[31m[Error]\x1b[0m
|
|
160
|
+
console.error('\x1b[31m[Error]\x1b[0m Missing secret name.');
|
|
72
161
|
process.exit(1);
|
|
73
162
|
}
|
|
74
163
|
|
|
75
164
|
try {
|
|
76
|
-
await
|
|
165
|
+
await callApi(`/api/v1/secrets/${encodeURIComponent(target)}`, 'DELETE');
|
|
77
166
|
console.log(`\x1b[32m[Success]\x1b[0m Secret '${target}' deleted successfully.`);
|
|
78
167
|
} catch (err) {
|
|
79
168
|
console.error(`\x1b[31m[Error]\x1b[0m ${err.message}`);
|