raqeb 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.
- package/README.md +316 -0
- package/dist/client.d.ts +103 -0
- package/dist/client.js +175 -0
- package/dist/errors.d.ts +15 -0
- package/dist/errors.js +38 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +43 -0
- package/dist/types.d.ts +49 -0
- package/dist/types.js +5 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
# Raqeb Node.js SDK
|
|
2
|
+
|
|
3
|
+
Official Node.js/TypeScript SDK for Raqeb Database PAM and Secrets Management.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install raqeb
|
|
9
|
+
# or
|
|
10
|
+
yarn add raqeb
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
### TypeScript
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { RaqebClient } from 'raqeb';
|
|
19
|
+
|
|
20
|
+
// Initialize client
|
|
21
|
+
const client = new RaqebClient({
|
|
22
|
+
apiKey: 'sa_your_api_key_here'
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Get a secret
|
|
26
|
+
const secret = await client.getSecret('secret-id');
|
|
27
|
+
console.log(`Secret value: ${secret.value}`);
|
|
28
|
+
|
|
29
|
+
// Get temporary database credentials
|
|
30
|
+
const creds = await client.getDatabaseCredentials('db-id', {
|
|
31
|
+
ttlHours: 4,
|
|
32
|
+
accessLevel: 'read-only'
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
console.log(`Username: ${creds.username}`);
|
|
36
|
+
console.log(`Password: ${creds.password}`);
|
|
37
|
+
console.log(`Expires: ${creds.expiresAt}`);
|
|
38
|
+
|
|
39
|
+
// Revoke credentials when done
|
|
40
|
+
await client.revokeLease(creds.leaseId);
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### JavaScript
|
|
44
|
+
|
|
45
|
+
```javascript
|
|
46
|
+
const { RaqebClient } = require('raqeb');
|
|
47
|
+
|
|
48
|
+
const client = new RaqebClient({
|
|
49
|
+
apiKey: 'sa_your_api_key_here'
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// Use async/await
|
|
53
|
+
(async () => {
|
|
54
|
+
const secret = await client.getSecret('secret-id');
|
|
55
|
+
console.log(secret.value);
|
|
56
|
+
})();
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Usage Examples
|
|
60
|
+
|
|
61
|
+
### Secrets Management
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
import { RaqebClient } from 'raqeb';
|
|
65
|
+
|
|
66
|
+
const client = new RaqebClient({ apiKey: process.env.RAQEB_API_KEY });
|
|
67
|
+
|
|
68
|
+
// Retrieve a secret
|
|
69
|
+
const secret = await client.getSecret('api-key-prod');
|
|
70
|
+
const apiKey = secret.value;
|
|
71
|
+
|
|
72
|
+
// Use the secret
|
|
73
|
+
import axios from 'axios';
|
|
74
|
+
const response = await axios.get('https://api.example.com/data', {
|
|
75
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Database Access with PostgreSQL
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
import { RaqebClient } from 'raqeb';
|
|
83
|
+
import { Client } from 'pg';
|
|
84
|
+
|
|
85
|
+
const raqeb = new RaqebClient({ apiKey: process.env.RAQEB_API_KEY });
|
|
86
|
+
|
|
87
|
+
// Get temporary credentials
|
|
88
|
+
const creds = await raqeb.getDatabaseCredentials('prod-postgres', {
|
|
89
|
+
ttlHours: 2,
|
|
90
|
+
accessLevel: 'read-only'
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Connect to database
|
|
94
|
+
const db = new Client({
|
|
95
|
+
host: 'db.example.com',
|
|
96
|
+
port: 5432,
|
|
97
|
+
database: 'myapp',
|
|
98
|
+
user: creds.username,
|
|
99
|
+
password: creds.password,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
await db.connect();
|
|
104
|
+
const result = await db.query('SELECT * FROM users LIMIT 10');
|
|
105
|
+
console.log(result.rows);
|
|
106
|
+
} finally {
|
|
107
|
+
await db.end();
|
|
108
|
+
// Revoke credentials
|
|
109
|
+
await raqeb.revokeLease(creds.leaseId);
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Database Access with MySQL
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
import { RaqebClient } from 'raqeb';
|
|
117
|
+
import mysql from 'mysql2/promise';
|
|
118
|
+
|
|
119
|
+
const raqeb = new RaqebClient({ apiKey: process.env.RAQEB_API_KEY });
|
|
120
|
+
|
|
121
|
+
const creds = await raqeb.getDatabaseCredentials('prod-mysql', {
|
|
122
|
+
ttlHours: 1,
|
|
123
|
+
accessLevel: 'read-write'
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
const connection = await mysql.createConnection({
|
|
127
|
+
host: 'db.example.com',
|
|
128
|
+
user: creds.username,
|
|
129
|
+
password: creds.password,
|
|
130
|
+
database: 'myapp'
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
const [rows] = await connection.execute('SELECT * FROM products');
|
|
135
|
+
console.log(rows);
|
|
136
|
+
} finally {
|
|
137
|
+
await connection.end();
|
|
138
|
+
await raqeb.revokeLease(creds.leaseId);
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### API Key Management
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
import { RaqebClient } from 'raqeb';
|
|
146
|
+
|
|
147
|
+
const client = new RaqebClient({ apiKey: process.env.RAQEB_API_KEY });
|
|
148
|
+
|
|
149
|
+
// List API keys
|
|
150
|
+
const keys = await client.listAPIKeys();
|
|
151
|
+
keys.forEach(key => {
|
|
152
|
+
console.log(`${key.name}: ${key.keyPrefix}...`);
|
|
153
|
+
console.log(` Active: ${key.isActive}`);
|
|
154
|
+
console.log(` Last used: ${key.lastUsedAt || 'Never'}`);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// Create new API key
|
|
158
|
+
const newKey = await client.createAPIKey({
|
|
159
|
+
name: 'CI/CD Pipeline',
|
|
160
|
+
scopes: ['secrets:read', 'databases:read'],
|
|
161
|
+
description: 'Key for automated deployments'
|
|
162
|
+
});
|
|
163
|
+
console.log(`New API Key: ${newKey.apiKey}`); // Save this!
|
|
164
|
+
|
|
165
|
+
// Delete API key
|
|
166
|
+
await client.deleteAPIKey('key-id');
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Error Handling
|
|
170
|
+
|
|
171
|
+
```typescript
|
|
172
|
+
import {
|
|
173
|
+
RaqebClient,
|
|
174
|
+
AuthenticationError,
|
|
175
|
+
PermissionError,
|
|
176
|
+
NotFoundError,
|
|
177
|
+
RaqebError
|
|
178
|
+
} from 'raqeb';
|
|
179
|
+
|
|
180
|
+
const client = new RaqebClient({ apiKey: process.env.RAQEB_API_KEY });
|
|
181
|
+
|
|
182
|
+
try {
|
|
183
|
+
const secret = await client.getSecret('secret-id');
|
|
184
|
+
console.log(secret.value);
|
|
185
|
+
|
|
186
|
+
} catch (error) {
|
|
187
|
+
if (error instanceof AuthenticationError) {
|
|
188
|
+
console.error('Invalid or expired API key');
|
|
189
|
+
} else if (error instanceof PermissionError) {
|
|
190
|
+
console.error('Insufficient permissions - check API key scopes');
|
|
191
|
+
} else if (error instanceof NotFoundError) {
|
|
192
|
+
console.error('Secret not found');
|
|
193
|
+
} else if (error instanceof RaqebError) {
|
|
194
|
+
console.error(`API error: ${error.message}`);
|
|
195
|
+
} else {
|
|
196
|
+
console.error('Unexpected error:', error);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Express.js Middleware
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
import express from 'express';
|
|
205
|
+
import { RaqebClient } from 'raqeb';
|
|
206
|
+
|
|
207
|
+
const app = express();
|
|
208
|
+
const raqeb = new RaqebClient({ apiKey: process.env.RAQEB_API_KEY });
|
|
209
|
+
|
|
210
|
+
// Middleware to inject database credentials
|
|
211
|
+
app.use(async (req, res, next) => {
|
|
212
|
+
try {
|
|
213
|
+
const creds = await raqeb.getDatabaseCredentials('prod-db', {
|
|
214
|
+
ttlHours: 1,
|
|
215
|
+
accessLevel: 'read-only'
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
req.dbCreds = creds;
|
|
219
|
+
|
|
220
|
+
// Cleanup after response
|
|
221
|
+
res.on('finish', async () => {
|
|
222
|
+
await raqeb.revokeLease(creds.leaseId);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
next();
|
|
226
|
+
} catch (error) {
|
|
227
|
+
res.status(500).json({ error: 'Failed to get database credentials' });
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
app.get('/users', async (req, res) => {
|
|
232
|
+
// Use req.dbCreds to connect to database
|
|
233
|
+
// ...
|
|
234
|
+
});
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## API Reference
|
|
238
|
+
|
|
239
|
+
### RaqebClient
|
|
240
|
+
|
|
241
|
+
#### Constructor
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
new RaqebClient(options: RaqebClientOptions)
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**Options:**
|
|
248
|
+
- `apiKey` (string, required): Service account API key
|
|
249
|
+
- `baseUrl` (string, optional): Base URL for Raqeb API (default: `https://app.raqeb.cloud/api/v1`)
|
|
250
|
+
- `timeout` (number, optional): Request timeout in milliseconds (default: 30000)
|
|
251
|
+
|
|
252
|
+
#### Methods
|
|
253
|
+
|
|
254
|
+
##### `getSecret(secretId: string): Promise<Secret>`
|
|
255
|
+
Retrieve a secret value.
|
|
256
|
+
|
|
257
|
+
##### `getDatabaseCredentials(databaseId: string, options?: DatabaseCredentialsOptions): Promise<DatabaseCredentials>`
|
|
258
|
+
Generate temporary database credentials.
|
|
259
|
+
|
|
260
|
+
**Options:**
|
|
261
|
+
- `ttlHours` (number): Time to live in hours (default: 4)
|
|
262
|
+
- `accessLevel` ('read-only' | 'read-write' | 'admin'): Access level (default: 'read-only')
|
|
263
|
+
|
|
264
|
+
##### `revokeLease(leaseId: string): Promise<void>`
|
|
265
|
+
Revoke a dynamic secret lease.
|
|
266
|
+
|
|
267
|
+
##### `listAPIKeys(): Promise<APIKey[]>`
|
|
268
|
+
List user's API keys.
|
|
269
|
+
|
|
270
|
+
##### `createAPIKey(data: APIKeyCreate): Promise<APIKey & { apiKey: string }>`
|
|
271
|
+
Create a new API key.
|
|
272
|
+
|
|
273
|
+
##### `deleteAPIKey(keyId: string): Promise<void>`
|
|
274
|
+
Delete an API key.
|
|
275
|
+
|
|
276
|
+
## TypeScript Support
|
|
277
|
+
|
|
278
|
+
This SDK is written in TypeScript and includes full type definitions.
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
import { RaqebClient, DatabaseCredentials, Secret } from 'raqeb';
|
|
282
|
+
|
|
283
|
+
const client: RaqebClient = new RaqebClient({ apiKey: 'sa_key' });
|
|
284
|
+
const creds: DatabaseCredentials = await client.getDatabaseCredentials('db-id');
|
|
285
|
+
const secret: Secret = await client.getSecret('secret-id');
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
## Environment Variables
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
import { RaqebClient } from 'raqeb';
|
|
292
|
+
|
|
293
|
+
const client = new RaqebClient({
|
|
294
|
+
apiKey: process.env.RAQEB_API_KEY!,
|
|
295
|
+
baseUrl: process.env.RAQEB_BASE_URL
|
|
296
|
+
});
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
## Best Practices
|
|
300
|
+
|
|
301
|
+
1. **Use environment variables** - Never hardcode API keys
|
|
302
|
+
2. **Minimal scopes** - Only grant necessary permissions
|
|
303
|
+
3. **Short TTLs** - Use shortest time needed for database access
|
|
304
|
+
4. **Always revoke** - Clean up credentials when done
|
|
305
|
+
5. **Error handling** - Catch and handle SDK exceptions
|
|
306
|
+
6. **TypeScript** - Leverage type safety for better development experience
|
|
307
|
+
|
|
308
|
+
## License
|
|
309
|
+
|
|
310
|
+
MIT License - see LICENSE file for details
|
|
311
|
+
|
|
312
|
+
## Support
|
|
313
|
+
|
|
314
|
+
- Documentation: https://docs.raqeb.cloud
|
|
315
|
+
- Email: support@raqeb.cloud
|
|
316
|
+
- GitHub: https://github.com/raqeb/nodejs-sdk
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Raqeb Client for Node.js
|
|
3
|
+
*/
|
|
4
|
+
import { RaqebClientOptions, Secret, DatabaseCredentials, APIKey, APIKeyCreate, DatabaseCredentialsOptions } from './types';
|
|
5
|
+
export declare class RaqebClient {
|
|
6
|
+
private client;
|
|
7
|
+
private apiKey;
|
|
8
|
+
/**
|
|
9
|
+
* Create a new Raqeb client
|
|
10
|
+
*
|
|
11
|
+
* @param options - Client configuration options
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const client = new RaqebClient({
|
|
15
|
+
* apiKey: 'sa_your_api_key',
|
|
16
|
+
* baseUrl: 'https://app.raqeb.cloud/api/v1'
|
|
17
|
+
* });
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
constructor(options: RaqebClientOptions);
|
|
21
|
+
private handleError;
|
|
22
|
+
/**
|
|
23
|
+
* Retrieve a secret value
|
|
24
|
+
*
|
|
25
|
+
* @param secretId - ID of the secret to retrieve
|
|
26
|
+
* @returns Secret object with value
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const secret = await client.getSecret('secret-123');
|
|
30
|
+
* console.log(secret.value);
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
getSecret(secretId: string): Promise<Secret>;
|
|
34
|
+
/**
|
|
35
|
+
* Generate temporary database credentials
|
|
36
|
+
*
|
|
37
|
+
* @param databaseId - ID of the database
|
|
38
|
+
* @param options - Credential options (ttlHours, accessLevel)
|
|
39
|
+
* @returns Temporary database credentials
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const creds = await client.getDatabaseCredentials('db-123', {
|
|
43
|
+
* ttlHours: 4,
|
|
44
|
+
* accessLevel: 'read-only'
|
|
45
|
+
* });
|
|
46
|
+
* console.log(`Username: ${creds.username}`);
|
|
47
|
+
* console.log(`Password: ${creds.password}`);
|
|
48
|
+
* console.log(`Expires: ${creds.expiresAt}`);
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
getDatabaseCredentials(databaseId: string, options?: DatabaseCredentialsOptions): Promise<DatabaseCredentials>;
|
|
52
|
+
/**
|
|
53
|
+
* Revoke a dynamic secret lease
|
|
54
|
+
*
|
|
55
|
+
* @param leaseId - ID of the lease to revoke
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* await client.revokeLease('lease-123');
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
revokeLease(leaseId: string): Promise<void>;
|
|
62
|
+
/**
|
|
63
|
+
* List user's API keys
|
|
64
|
+
*
|
|
65
|
+
* @returns Array of API key objects
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* const keys = await client.listAPIKeys();
|
|
69
|
+
* keys.forEach(key => {
|
|
70
|
+
* console.log(`${key.name}: ${key.keyPrefix}...`);
|
|
71
|
+
* });
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
listAPIKeys(): Promise<APIKey[]>;
|
|
75
|
+
/**
|
|
76
|
+
* Create a new API key
|
|
77
|
+
*
|
|
78
|
+
* @param data - API key creation data
|
|
79
|
+
* @returns Created API key (includes the key value - save it!)
|
|
80
|
+
* @example
|
|
81
|
+
* ```typescript
|
|
82
|
+
* const key = await client.createAPIKey({
|
|
83
|
+
* name: 'My App',
|
|
84
|
+
* scopes: ['secrets:read', 'databases:read'],
|
|
85
|
+
* description: 'Key for CI/CD'
|
|
86
|
+
* });
|
|
87
|
+
* console.log(`API Key: ${key.apiKey}`); // Save this!
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
createAPIKey(data: APIKeyCreate): Promise<APIKey & {
|
|
91
|
+
apiKey: string;
|
|
92
|
+
}>;
|
|
93
|
+
/**
|
|
94
|
+
* Delete an API key
|
|
95
|
+
*
|
|
96
|
+
* @param keyId - ID of the key to delete
|
|
97
|
+
* @example
|
|
98
|
+
* ```typescript
|
|
99
|
+
* await client.deleteAPIKey('key-123');
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
deleteAPIKey(keyId: string): Promise<void>;
|
|
103
|
+
}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Raqeb Client for Node.js
|
|
4
|
+
*/
|
|
5
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.RaqebClient = void 0;
|
|
10
|
+
const axios_1 = __importDefault(require("axios"));
|
|
11
|
+
const errors_1 = require("./errors");
|
|
12
|
+
class RaqebClient {
|
|
13
|
+
/**
|
|
14
|
+
* Create a new Raqeb client
|
|
15
|
+
*
|
|
16
|
+
* @param options - Client configuration options
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const client = new RaqebClient({
|
|
20
|
+
* apiKey: 'sa_your_api_key',
|
|
21
|
+
* baseUrl: 'https://app.raqeb.cloud/api/v1'
|
|
22
|
+
* });
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
constructor(options) {
|
|
26
|
+
this.apiKey = options.apiKey;
|
|
27
|
+
this.client = axios_1.default.create({
|
|
28
|
+
baseURL: options.baseUrl || 'https://app.raqeb.cloud/api/v1',
|
|
29
|
+
headers: {
|
|
30
|
+
'Authorization': `Bearer ${options.apiKey}`,
|
|
31
|
+
'Content-Type': 'application/json',
|
|
32
|
+
},
|
|
33
|
+
timeout: options.timeout || 30000,
|
|
34
|
+
});
|
|
35
|
+
// Error interceptor
|
|
36
|
+
this.client.interceptors.response.use((response) => response, (error) => {
|
|
37
|
+
return Promise.reject(this.handleError(error));
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
handleError(error) {
|
|
41
|
+
if (!error.response) {
|
|
42
|
+
return new errors_1.RaqebError(`Network error: ${error.message}`);
|
|
43
|
+
}
|
|
44
|
+
const status = error.response.status;
|
|
45
|
+
const detail = error.response.data?.detail || error.message;
|
|
46
|
+
switch (status) {
|
|
47
|
+
case 401:
|
|
48
|
+
return new errors_1.AuthenticationError(detail);
|
|
49
|
+
case 403:
|
|
50
|
+
return new errors_1.PermissionError(detail);
|
|
51
|
+
case 404:
|
|
52
|
+
return new errors_1.NotFoundError(detail);
|
|
53
|
+
default:
|
|
54
|
+
return new errors_1.RaqebError(`HTTP ${status}: ${detail}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// ============================================================================
|
|
58
|
+
// Secrets Management
|
|
59
|
+
// ============================================================================
|
|
60
|
+
/**
|
|
61
|
+
* Retrieve a secret value
|
|
62
|
+
*
|
|
63
|
+
* @param secretId - ID of the secret to retrieve
|
|
64
|
+
* @returns Secret object with value
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* const secret = await client.getSecret('secret-123');
|
|
68
|
+
* console.log(secret.value);
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
async getSecret(secretId) {
|
|
72
|
+
const response = await this.client.post('/service-accounts/secrets/retrieve', null, {
|
|
73
|
+
params: { secret_id: secretId },
|
|
74
|
+
});
|
|
75
|
+
return response.data;
|
|
76
|
+
}
|
|
77
|
+
// ============================================================================
|
|
78
|
+
// Database Credentials
|
|
79
|
+
// ============================================================================
|
|
80
|
+
/**
|
|
81
|
+
* Generate temporary database credentials
|
|
82
|
+
*
|
|
83
|
+
* @param databaseId - ID of the database
|
|
84
|
+
* @param options - Credential options (ttlHours, accessLevel)
|
|
85
|
+
* @returns Temporary database credentials
|
|
86
|
+
* @example
|
|
87
|
+
* ```typescript
|
|
88
|
+
* const creds = await client.getDatabaseCredentials('db-123', {
|
|
89
|
+
* ttlHours: 4,
|
|
90
|
+
* accessLevel: 'read-only'
|
|
91
|
+
* });
|
|
92
|
+
* console.log(`Username: ${creds.username}`);
|
|
93
|
+
* console.log(`Password: ${creds.password}`);
|
|
94
|
+
* console.log(`Expires: ${creds.expiresAt}`);
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
async getDatabaseCredentials(databaseId, options = {}) {
|
|
98
|
+
const payload = {
|
|
99
|
+
database_id: databaseId,
|
|
100
|
+
ttl_hours: options.ttlHours || 4,
|
|
101
|
+
access_level: options.accessLevel || 'read-only',
|
|
102
|
+
};
|
|
103
|
+
const response = await this.client.post('/service-accounts/databases/dynamic-credentials', payload);
|
|
104
|
+
return response.data;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Revoke a dynamic secret lease
|
|
108
|
+
*
|
|
109
|
+
* @param leaseId - ID of the lease to revoke
|
|
110
|
+
* @example
|
|
111
|
+
* ```typescript
|
|
112
|
+
* await client.revokeLease('lease-123');
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
async revokeLease(leaseId) {
|
|
116
|
+
await this.client.post(`/service-accounts/leases/${leaseId}/revoke`);
|
|
117
|
+
}
|
|
118
|
+
// ============================================================================
|
|
119
|
+
// API Keys Management
|
|
120
|
+
// ============================================================================
|
|
121
|
+
/**
|
|
122
|
+
* List user's API keys
|
|
123
|
+
*
|
|
124
|
+
* @returns Array of API key objects
|
|
125
|
+
* @example
|
|
126
|
+
* ```typescript
|
|
127
|
+
* const keys = await client.listAPIKeys();
|
|
128
|
+
* keys.forEach(key => {
|
|
129
|
+
* console.log(`${key.name}: ${key.keyPrefix}...`);
|
|
130
|
+
* });
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
async listAPIKeys() {
|
|
134
|
+
const response = await this.client.get('/service-accounts/api-keys');
|
|
135
|
+
return response.data;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Create a new API key
|
|
139
|
+
*
|
|
140
|
+
* @param data - API key creation data
|
|
141
|
+
* @returns Created API key (includes the key value - save it!)
|
|
142
|
+
* @example
|
|
143
|
+
* ```typescript
|
|
144
|
+
* const key = await client.createAPIKey({
|
|
145
|
+
* name: 'My App',
|
|
146
|
+
* scopes: ['secrets:read', 'databases:read'],
|
|
147
|
+
* description: 'Key for CI/CD'
|
|
148
|
+
* });
|
|
149
|
+
* console.log(`API Key: ${key.apiKey}`); // Save this!
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
async createAPIKey(data) {
|
|
153
|
+
const payload = {
|
|
154
|
+
name: data.name,
|
|
155
|
+
description: data.description,
|
|
156
|
+
scopes: data.scopes || ['secrets:read', 'databases:read'],
|
|
157
|
+
expires_at: data.expiresAt,
|
|
158
|
+
};
|
|
159
|
+
const response = await this.client.post('/service-accounts/api-keys', payload);
|
|
160
|
+
return response.data;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Delete an API key
|
|
164
|
+
*
|
|
165
|
+
* @param keyId - ID of the key to delete
|
|
166
|
+
* @example
|
|
167
|
+
* ```typescript
|
|
168
|
+
* await client.deleteAPIKey('key-123');
|
|
169
|
+
* ```
|
|
170
|
+
*/
|
|
171
|
+
async deleteAPIKey(keyId) {
|
|
172
|
+
await this.client.delete(`/service-accounts/api-keys/${keyId}`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
exports.RaqebClient = RaqebClient;
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error classes for Raqeb SDK
|
|
3
|
+
*/
|
|
4
|
+
export declare class RaqebError extends Error {
|
|
5
|
+
constructor(message: string);
|
|
6
|
+
}
|
|
7
|
+
export declare class AuthenticationError extends RaqebError {
|
|
8
|
+
constructor(message: string);
|
|
9
|
+
}
|
|
10
|
+
export declare class PermissionError extends RaqebError {
|
|
11
|
+
constructor(message: string);
|
|
12
|
+
}
|
|
13
|
+
export declare class NotFoundError extends RaqebError {
|
|
14
|
+
constructor(message: string);
|
|
15
|
+
}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Error classes for Raqeb SDK
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.NotFoundError = exports.PermissionError = exports.AuthenticationError = exports.RaqebError = void 0;
|
|
7
|
+
class RaqebError extends Error {
|
|
8
|
+
constructor(message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = 'RaqebError';
|
|
11
|
+
Object.setPrototypeOf(this, RaqebError.prototype);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.RaqebError = RaqebError;
|
|
15
|
+
class AuthenticationError extends RaqebError {
|
|
16
|
+
constructor(message) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.name = 'AuthenticationError';
|
|
19
|
+
Object.setPrototypeOf(this, AuthenticationError.prototype);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.AuthenticationError = AuthenticationError;
|
|
23
|
+
class PermissionError extends RaqebError {
|
|
24
|
+
constructor(message) {
|
|
25
|
+
super(message);
|
|
26
|
+
this.name = 'PermissionError';
|
|
27
|
+
Object.setPrototypeOf(this, PermissionError.prototype);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.PermissionError = PermissionError;
|
|
31
|
+
class NotFoundError extends RaqebError {
|
|
32
|
+
constructor(message) {
|
|
33
|
+
super(message);
|
|
34
|
+
this.name = 'NotFoundError';
|
|
35
|
+
Object.setPrototypeOf(this, NotFoundError.prototype);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.NotFoundError = NotFoundError;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Raqeb Node.js SDK - Database PAM and Secrets Management
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```typescript
|
|
6
|
+
* import { RaqebClient } from 'raqeb';
|
|
7
|
+
*
|
|
8
|
+
* const client = new RaqebClient({ apiKey: 'sa_your_api_key' });
|
|
9
|
+
*
|
|
10
|
+
* // Get secret
|
|
11
|
+
* const secret = await client.getSecret('secret-id');
|
|
12
|
+
* console.log(secret.value);
|
|
13
|
+
*
|
|
14
|
+
* // Get database credentials
|
|
15
|
+
* const creds = await client.getDatabaseCredentials('db-id', { ttlHours: 4 });
|
|
16
|
+
* console.log(`Username: ${creds.username}`);
|
|
17
|
+
* console.log(`Password: ${creds.password}`);
|
|
18
|
+
*
|
|
19
|
+
* // Revoke when done
|
|
20
|
+
* await client.revokeLease(creds.leaseId);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export { RaqebClient } from './client';
|
|
24
|
+
export * from './types';
|
|
25
|
+
export * from './errors';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Raqeb Node.js SDK - Database PAM and Secrets Management
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* import { RaqebClient } from 'raqeb';
|
|
8
|
+
*
|
|
9
|
+
* const client = new RaqebClient({ apiKey: 'sa_your_api_key' });
|
|
10
|
+
*
|
|
11
|
+
* // Get secret
|
|
12
|
+
* const secret = await client.getSecret('secret-id');
|
|
13
|
+
* console.log(secret.value);
|
|
14
|
+
*
|
|
15
|
+
* // Get database credentials
|
|
16
|
+
* const creds = await client.getDatabaseCredentials('db-id', { ttlHours: 4 });
|
|
17
|
+
* console.log(`Username: ${creds.username}`);
|
|
18
|
+
* console.log(`Password: ${creds.password}`);
|
|
19
|
+
*
|
|
20
|
+
* // Revoke when done
|
|
21
|
+
* await client.revokeLease(creds.leaseId);
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
27
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
28
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
29
|
+
}
|
|
30
|
+
Object.defineProperty(o, k2, desc);
|
|
31
|
+
}) : (function(o, m, k, k2) {
|
|
32
|
+
if (k2 === undefined) k2 = k;
|
|
33
|
+
o[k2] = m[k];
|
|
34
|
+
}));
|
|
35
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
36
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.RaqebClient = void 0;
|
|
40
|
+
var client_1 = require("./client");
|
|
41
|
+
Object.defineProperty(exports, "RaqebClient", { enumerable: true, get: function () { return client_1.RaqebClient; } });
|
|
42
|
+
__exportStar(require("./types"), exports);
|
|
43
|
+
__exportStar(require("./errors"), exports);
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for Raqeb SDK
|
|
3
|
+
*/
|
|
4
|
+
export interface RaqebClientOptions {
|
|
5
|
+
/** Service account API key */
|
|
6
|
+
apiKey: string;
|
|
7
|
+
/** Base URL for Raqeb API */
|
|
8
|
+
baseUrl?: string;
|
|
9
|
+
/** Request timeout in milliseconds */
|
|
10
|
+
timeout?: number;
|
|
11
|
+
}
|
|
12
|
+
export interface Secret {
|
|
13
|
+
secretId: string;
|
|
14
|
+
name: string;
|
|
15
|
+
value: string;
|
|
16
|
+
retrievedAt: string;
|
|
17
|
+
}
|
|
18
|
+
export interface DatabaseCredentials {
|
|
19
|
+
leaseId: string;
|
|
20
|
+
username: string;
|
|
21
|
+
password: string;
|
|
22
|
+
databaseId: string;
|
|
23
|
+
accessLevel: 'read-only' | 'read-write' | 'admin';
|
|
24
|
+
issuedAt: string;
|
|
25
|
+
expiresAt: string;
|
|
26
|
+
ttlSeconds: number;
|
|
27
|
+
}
|
|
28
|
+
export interface DatabaseCredentialsOptions {
|
|
29
|
+
/** Time to live in hours (default: 4) */
|
|
30
|
+
ttlHours?: number;
|
|
31
|
+
/** Access level (default: 'read-only') */
|
|
32
|
+
accessLevel?: 'read-only' | 'read-write' | 'admin';
|
|
33
|
+
}
|
|
34
|
+
export interface APIKey {
|
|
35
|
+
id: string;
|
|
36
|
+
name: string;
|
|
37
|
+
keyPrefix: string;
|
|
38
|
+
scopes: string[];
|
|
39
|
+
isActive: boolean;
|
|
40
|
+
createdAt: string;
|
|
41
|
+
lastUsedAt?: string;
|
|
42
|
+
expiresAt?: string;
|
|
43
|
+
}
|
|
44
|
+
export interface APIKeyCreate {
|
|
45
|
+
name: string;
|
|
46
|
+
description?: string;
|
|
47
|
+
scopes?: string[];
|
|
48
|
+
expiresAt?: string;
|
|
49
|
+
}
|
package/dist/types.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "raqeb",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Node.js SDK for Raqeb Database PAM and Secrets Management",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"test": "jest",
|
|
10
|
+
"lint": "eslint src --ext .ts",
|
|
11
|
+
"prepublishOnly": "npm run build"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"raqeb",
|
|
15
|
+
"pam",
|
|
16
|
+
"secrets",
|
|
17
|
+
"database",
|
|
18
|
+
"security",
|
|
19
|
+
"credentials"
|
|
20
|
+
],
|
|
21
|
+
"author": "Raqeb",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "https://github.com/raqeb/nodejs-sdk"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"axios": "^1.6.0"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/node": "^20.0.0",
|
|
32
|
+
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
33
|
+
"@typescript-eslint/parser": "^6.0.0",
|
|
34
|
+
"eslint": "^8.0.0",
|
|
35
|
+
"jest": "^29.0.0",
|
|
36
|
+
"typescript": "^5.0.0"
|
|
37
|
+
},
|
|
38
|
+
"files": [
|
|
39
|
+
"dist",
|
|
40
|
+
"README.md",
|
|
41
|
+
"LICENSE"
|
|
42
|
+
]
|
|
43
|
+
}
|