raqeb-cli 1.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 +134 -0
  2. package/bin/raqeb.js +212 -0
  3. package/package.json +43 -0
package/README.md ADDED
@@ -0,0 +1,134 @@
1
+ # raqeb-cli
2
+
3
+ Official Raqeb CLI - Command-line tool for Database PAM and Developer Secrets Management.
4
+
5
+ ## Installation
6
+
7
+ ### Via npm (Recommended)
8
+
9
+ ```bash
10
+ npm install -g raqeb-cli
11
+ ```
12
+
13
+ ### Via yarn
14
+
15
+ ```bash
16
+ yarn global add raqeb-cli
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ### 1. Login
22
+
23
+ ```bash
24
+ raqeb login --api-key sa_your_api_key_here
25
+ ```
26
+
27
+ ### 2. Get Secret
28
+
29
+ ```bash
30
+ raqeb secrets get <secret-id>
31
+ ```
32
+
33
+ ### 3. Get Database Credentials
34
+
35
+ ```bash
36
+ raqeb db connect <database-id> --ttl 4 --access-level read-only
37
+ ```
38
+
39
+ ### 4. Revoke Credentials
40
+
41
+ ```bash
42
+ raqeb db revoke <lease-id>
43
+ ```
44
+
45
+ ## Commands
46
+
47
+ ### Authentication
48
+
49
+ ```bash
50
+ raqeb login --api-key <key>
51
+ ```
52
+
53
+ ### Secrets Management
54
+
55
+ ```bash
56
+ # Get secret value
57
+ raqeb secrets get <secret-id>
58
+ ```
59
+
60
+ ### Database Access
61
+
62
+ ```bash
63
+ # Get temporary credentials
64
+ raqeb db connect <database-id> [options]
65
+ --ttl <hours> Time to live (default: 4)
66
+ --access-level <level> read-only, read-write, or admin (default: read-only)
67
+
68
+ # Revoke credentials
69
+ raqeb db revoke <lease-id>
70
+ ```
71
+
72
+ ### API Keys
73
+
74
+ ```bash
75
+ # List API keys
76
+ raqeb keys list
77
+
78
+ # Create new API key
79
+ raqeb keys create <name> [--scopes <scopes>]
80
+
81
+ # Delete API key
82
+ raqeb keys delete <key-id>
83
+ ```
84
+
85
+ ## Configuration
86
+
87
+ Configuration is stored in `~/.raqeb/config.json`
88
+
89
+ ```json
90
+ {
91
+ "base_url": "https://app.raqeb.cloud/api/v1",
92
+ "api_key": "sa_your_api_key"
93
+ }
94
+ ```
95
+
96
+ ## Examples
97
+
98
+ ### CI/CD Integration
99
+
100
+ ```bash
101
+ #!/bin/bash
102
+ # Get database credentials for deployment
103
+
104
+ # Login (use environment variable)
105
+ raqeb login --api-key $RAQEB_API_KEY
106
+
107
+ # Get temporary credentials
108
+ raqeb db connect prod-mysql-db --ttl 1 --access-level read-write
109
+
110
+ # ... your deployment script ...
111
+
112
+ # Revoke when done
113
+ raqeb db revoke $LEASE_ID
114
+ ```
115
+
116
+ ### Retrieve Application Secrets
117
+
118
+ ```bash
119
+ # Get API key from secrets vault
120
+ raqeb secrets get api-key-prod
121
+
122
+ # Use in your application
123
+ export EXTERNAL_API_KEY=$(raqeb secrets get api-key-prod | grep "Value:" | cut -d' ' -f2)
124
+ ```
125
+
126
+ ## License
127
+
128
+ MIT
129
+
130
+ ## Support
131
+
132
+ - Documentation: https://docs.raqeb.cloud
133
+ - Email: support@raqeb.cloud
134
+ - GitHub: https://github.com/raqeb/cli
package/bin/raqeb.js ADDED
@@ -0,0 +1,212 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { program } = require('commander');
4
+ const axios = require('axios');
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+ const os = require('os');
8
+ const chalk = require('chalk');
9
+
10
+ const CONFIG_DIR = path.join(os.homedir(), '.raqeb');
11
+ const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
12
+
13
+ // Ensure config directory exists
14
+ if (!fs.existsSync(CONFIG_DIR)) {
15
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
16
+ }
17
+
18
+ // Load config
19
+ function loadConfig() {
20
+ if (fs.existsSync(CONFIG_FILE)) {
21
+ return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8'));
22
+ }
23
+ return { base_url: 'https://app.raqeb.cloud/api/v1' };
24
+ }
25
+
26
+ // Save config
27
+ function saveConfig(config) {
28
+ fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
29
+ fs.chmodSync(CONFIG_FILE, 0o600);
30
+ }
31
+
32
+ // Get API client
33
+ function getClient() {
34
+ const config = loadConfig();
35
+ if (!config.api_key) {
36
+ console.error(chalk.red('❌ Not authenticated. Run: raqeb login --api-key <key>'));
37
+ process.exit(1);
38
+ }
39
+ return axios.create({
40
+ baseURL: config.base_url,
41
+ headers: {
42
+ 'Authorization': `Bearer ${config.api_key}`,
43
+ 'Content-Type': 'application/json'
44
+ }
45
+ });
46
+ }
47
+
48
+ // Login command
49
+ program
50
+ .command('login')
51
+ .description('Authenticate with API key')
52
+ .requiredOption('--api-key <key>', 'Your API key')
53
+ .action((options) => {
54
+ const config = loadConfig();
55
+ config.api_key = options.apiKey;
56
+ saveConfig(config);
57
+ console.log(chalk.green('✅ Successfully authenticated!'));
58
+ console.log(chalk.gray(`Config saved to: ${CONFIG_FILE}`));
59
+ });
60
+
61
+ // Secrets commands
62
+ const secrets = program.command('secrets').description('Manage secrets');
63
+
64
+ secrets
65
+ .command('get <secret-id>')
66
+ .description('Get secret value')
67
+ .action(async (secretId) => {
68
+ try {
69
+ const client = getClient();
70
+ const response = await client.post('/service-accounts/secrets/retrieve', null, {
71
+ params: { secret_id: secretId }
72
+ });
73
+ const data = response.data;
74
+ console.log(chalk.cyan(`\n🔐 Secret: ${data.name}`));
75
+ console.log(chalk.white(`Value: ${data.value}`));
76
+ console.log(chalk.gray(`Retrieved at: ${data.retrieved_at}`));
77
+ } catch (error) {
78
+ console.error(chalk.red(`❌ Error: ${error.response?.data?.detail || error.message}`));
79
+ process.exit(1);
80
+ }
81
+ });
82
+
83
+ // Database commands
84
+ const db = program.command('db').description('Manage database access');
85
+
86
+ db
87
+ .command('connect <database-id>')
88
+ .description('Get temporary database credentials')
89
+ .option('--ttl <hours>', 'Time to live in hours', '4')
90
+ .option('--access-level <level>', 'Access level (read-only, read-write, admin)', 'read-only')
91
+ .action(async (databaseId, options) => {
92
+ try {
93
+ const client = getClient();
94
+ const response = await client.post('/service-accounts/databases/dynamic-credentials', {
95
+ database_id: databaseId,
96
+ ttl_hours: parseInt(options.ttl),
97
+ access_level: options.accessLevel
98
+ });
99
+ const data = response.data;
100
+
101
+ console.log(chalk.cyan('\n🔑 Temporary Database Credentials'));
102
+ console.log(chalk.gray('━'.repeat(40)));
103
+ console.log(chalk.white(`Username: ${data.username}`));
104
+ console.log(chalk.white(`Password: ${data.password}`));
105
+ console.log(chalk.white(`Access Level: ${data.access_level}`));
106
+ console.log(chalk.white(`Expires: ${data.expires_at}`));
107
+ console.log(chalk.white(`Lease ID: ${data.lease_id}`));
108
+ console.log(chalk.yellow(`\n⚠️ These credentials will expire in ${options.ttl} hours`));
109
+ console.log(chalk.gray(`To revoke early: raqeb db revoke ${data.lease_id}`));
110
+ } catch (error) {
111
+ console.error(chalk.red(`❌ Error: ${error.response?.data?.detail || error.message}`));
112
+ process.exit(1);
113
+ }
114
+ });
115
+
116
+ db
117
+ .command('revoke <lease-id>')
118
+ .description('Revoke database credentials')
119
+ .action(async (leaseId) => {
120
+ try {
121
+ const client = getClient();
122
+ await client.post(`/service-accounts/leases/${leaseId}/revoke`);
123
+ console.log(chalk.green(`✅ Lease ${leaseId} revoked successfully`));
124
+ } catch (error) {
125
+ console.error(chalk.red(`❌ Error: ${error.response?.data?.detail || error.message}`));
126
+ process.exit(1);
127
+ }
128
+ });
129
+
130
+ // API Keys commands
131
+ const keys = program.command('keys').description('Manage API keys');
132
+
133
+ keys
134
+ .command('list')
135
+ .description('List API keys')
136
+ .action(async () => {
137
+ try {
138
+ const client = getClient();
139
+ const response = await client.get('/service-accounts/api-keys');
140
+ const apiKeys = response.data;
141
+
142
+ if (apiKeys.length === 0) {
143
+ console.log(chalk.yellow('No API keys found'));
144
+ return;
145
+ }
146
+
147
+ console.log(chalk.cyan(`\n📋 API Keys (${apiKeys.length})`));
148
+ console.log(chalk.gray('━'.repeat(40)));
149
+
150
+ apiKeys.forEach(key => {
151
+ const status = key.is_active ? chalk.green('🟢 Active') : chalk.red('🔴 Inactive');
152
+ console.log(chalk.white(`\n${key.name}`));
153
+ console.log(chalk.gray(` ID: ${key.id}`));
154
+ console.log(chalk.gray(` Prefix: ${key.key_prefix}...`));
155
+ console.log(` Status: ${status}`);
156
+ console.log(chalk.gray(` Created: ${key.created_at}`));
157
+ if (key.last_used_at) {
158
+ console.log(chalk.gray(` Last Used: ${key.last_used_at}`));
159
+ }
160
+ });
161
+ } catch (error) {
162
+ console.error(chalk.red(`❌ Error: ${error.response?.data?.detail || error.message}`));
163
+ process.exit(1);
164
+ }
165
+ });
166
+
167
+ keys
168
+ .command('create <name>')
169
+ .description('Create new API key')
170
+ .option('--scopes <scopes>', 'Comma-separated scopes', 'secrets:read,databases:read')
171
+ .action(async (name, options) => {
172
+ try {
173
+ const client = getClient();
174
+ const response = await client.post('/service-accounts/api-keys', {
175
+ name: name,
176
+ scopes: options.scopes.split(',')
177
+ });
178
+ const data = response.data;
179
+
180
+ console.log(chalk.green('\n✅ API Key Created!'));
181
+ console.log(chalk.gray('━'.repeat(40)));
182
+ console.log(chalk.white(`Name: ${data.name}`));
183
+ console.log(chalk.white(`API Key: ${data.api_key}`));
184
+ console.log(chalk.yellow('\n⚠️ IMPORTANT: Save this key now! It won\'t be shown again.'));
185
+ console.log(chalk.gray(`\nTo use this key:`));
186
+ console.log(chalk.gray(` raqeb login --api-key ${data.api_key}`));
187
+ } catch (error) {
188
+ console.error(chalk.red(`❌ Error: ${error.response?.data?.detail || error.message}`));
189
+ process.exit(1);
190
+ }
191
+ });
192
+
193
+ keys
194
+ .command('delete <key-id>')
195
+ .description('Delete API key')
196
+ .action(async (keyId) => {
197
+ try {
198
+ const client = getClient();
199
+ await client.delete(`/service-accounts/api-keys/${keyId}`);
200
+ console.log(chalk.green(`✅ API key ${keyId} deleted successfully`));
201
+ } catch (error) {
202
+ console.error(chalk.red(`❌ Error: ${error.response?.data?.detail || error.message}`));
203
+ process.exit(1);
204
+ }
205
+ });
206
+
207
+ program
208
+ .name('raqeb')
209
+ .description('Raqeb CLI - Database PAM and Secrets Management')
210
+ .version('1.0.0');
211
+
212
+ program.parse();
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "raqeb-cli",
3
+ "version": "1.0.0",
4
+ "description": "Raqeb CLI - Command-line tool for Database PAM and Developer Secrets Management",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "raqeb": "bin/raqeb.js"
8
+ },
9
+ "scripts": {
10
+ "test": "echo \"Error: no test specified\" && exit 1"
11
+ },
12
+ "keywords": [
13
+ "raqeb",
14
+ "pam",
15
+ "database",
16
+ "secrets",
17
+ "cli",
18
+ "security",
19
+ "credentials"
20
+ ],
21
+ "author": "Raqeb",
22
+ "license": "MIT",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "https://github.com/raqeb/cli"
26
+ },
27
+ "dependencies": {
28
+ "axios": "^1.6.0",
29
+ "commander": "^11.0.0",
30
+ "chalk": "^4.1.2",
31
+ "ora": "^5.4.1",
32
+ "inquirer": "^8.2.5"
33
+ },
34
+ "engines": {
35
+ "node": ">=14.0.0"
36
+ },
37
+ "files": [
38
+ "bin",
39
+ "lib",
40
+ "README.md",
41
+ "LICENSE"
42
+ ]
43
+ }