@tadnt2003/n8n-nodes-infisical 0.2.0 → 0.3.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/LICENSE +1 -0
- package/README.md +198 -69
- package/dist/credentials/InfisicalApi.credentials.js +13 -0
- package/dist/credentials/infisical.png +0 -0
- package/dist/nodes/Infisical/Infisical.node.js +585 -227
- package/dist/nodes/InfisicalSync/InfisicalSync.node.d.ts +10 -0
- package/dist/nodes/InfisicalSync/InfisicalSync.node.js +1057 -0
- package/dist/nodes/InfisicalSync/infisical.png +0 -0
- package/dist/utils/auth.d.ts +5 -0
- package/dist/utils/auth.js +27 -0
- package/dist/utils/folderOperations.d.ts +2 -0
- package/dist/utils/folderOperations.js +103 -0
- package/dist/utils/projectOperations.d.ts +2 -0
- package/dist/utils/projectOperations.js +89 -0
- package/dist/utils/secretOperations.d.ts +2 -0
- package/dist/utils/secretOperations.js +256 -0
- package/dist/utils/syncOperations.d.ts +2 -0
- package/dist/utils/syncOperations.js +750 -0
- package/package.json +6 -4
|
@@ -2,22 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Infisical = void 0;
|
|
4
4
|
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const clientId = credentials.clientId;
|
|
10
|
-
const clientSecret = credentials.clientSecret;
|
|
11
|
-
const tokenResponse = await helpers.httpRequest({
|
|
12
|
-
method: 'POST',
|
|
13
|
-
url: `${apiUrl}/v1/auth/universal-auth/login`,
|
|
14
|
-
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
15
|
-
body: `clientId=${encodeURIComponent(clientId)}&clientSecret=${encodeURIComponent(clientSecret)}`,
|
|
16
|
-
});
|
|
17
|
-
return { apiUrl, accessToken: tokenResponse.accessToken };
|
|
18
|
-
}
|
|
19
|
-
return { apiUrl, accessToken: credentials.apiKey };
|
|
20
|
-
}
|
|
5
|
+
const secretOperations_1 = require("../../utils/secretOperations");
|
|
6
|
+
const projectOperations_1 = require("../../utils/projectOperations");
|
|
7
|
+
const folderOperations_1 = require("../../utils/folderOperations");
|
|
8
|
+
const auth_1 = require("../../utils/auth");
|
|
21
9
|
class Infisical {
|
|
22
10
|
constructor() {
|
|
23
11
|
this.description = {
|
|
@@ -48,8 +36,9 @@ class Infisical {
|
|
|
48
36
|
type: 'options',
|
|
49
37
|
noDataExpression: true,
|
|
50
38
|
options: [
|
|
39
|
+
{ name: 'Folder', value: 'folder' },
|
|
40
|
+
{ name: 'Project', value: 'project' },
|
|
51
41
|
{ name: 'Secret', value: 'secret' },
|
|
52
|
-
{ name: 'Workspace', value: 'workspace' },
|
|
53
42
|
],
|
|
54
43
|
default: 'secret',
|
|
55
44
|
},
|
|
@@ -79,6 +68,12 @@ class Infisical {
|
|
|
79
68
|
description: 'Delete a secret',
|
|
80
69
|
action: 'Delete a secret',
|
|
81
70
|
},
|
|
71
|
+
{
|
|
72
|
+
name: 'Delete Many',
|
|
73
|
+
value: 'deleteMany',
|
|
74
|
+
description: 'Delete multiple secrets in one request',
|
|
75
|
+
action: 'Delete many secrets',
|
|
76
|
+
},
|
|
82
77
|
{
|
|
83
78
|
name: 'Get',
|
|
84
79
|
value: 'get',
|
|
@@ -106,32 +101,375 @@ class Infisical {
|
|
|
106
101
|
],
|
|
107
102
|
default: 'get',
|
|
108
103
|
},
|
|
109
|
-
// ───
|
|
104
|
+
// ─── Project operations ────────────────────────────────────────────────
|
|
110
105
|
{
|
|
111
106
|
displayName: 'Operation',
|
|
112
107
|
name: 'operation',
|
|
113
108
|
type: 'options',
|
|
114
109
|
noDataExpression: true,
|
|
115
|
-
displayOptions: { show: { resource: ['
|
|
110
|
+
displayOptions: { show: { resource: ['project'] } },
|
|
116
111
|
options: [
|
|
112
|
+
{
|
|
113
|
+
name: 'Get',
|
|
114
|
+
value: 'get',
|
|
115
|
+
description: 'Get a project by ID',
|
|
116
|
+
action: 'Get a project',
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
name: 'Get By Slug',
|
|
120
|
+
value: 'getBySlug',
|
|
121
|
+
description: 'Get a project by slug',
|
|
122
|
+
action: 'Get a project by slug',
|
|
123
|
+
},
|
|
117
124
|
{
|
|
118
125
|
name: 'Get Many',
|
|
119
126
|
value: 'getAll',
|
|
120
|
-
description: 'List all accessible
|
|
121
|
-
action: 'Get many
|
|
127
|
+
description: 'List all accessible projects',
|
|
128
|
+
action: 'Get many projects',
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
name: 'Get Secret Snapshots',
|
|
132
|
+
value: 'getSecretSnapshots',
|
|
133
|
+
description: 'List secret snapshots for a project environment',
|
|
134
|
+
action: 'Get secret snapshots',
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: 'Get User By Username',
|
|
138
|
+
value: 'getUserByUsername',
|
|
139
|
+
description: 'Get a project member by username',
|
|
140
|
+
action: 'Get user by username',
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
name: 'Get User Memberships',
|
|
144
|
+
value: 'getUserMemberships',
|
|
145
|
+
description: 'List all user memberships in a project',
|
|
146
|
+
action: 'Get user memberships',
|
|
122
147
|
},
|
|
123
148
|
],
|
|
124
149
|
default: 'getAll',
|
|
125
150
|
},
|
|
151
|
+
// ─── Project fields ───────────────────────────────
|
|
152
|
+
{
|
|
153
|
+
displayName: 'Project ID',
|
|
154
|
+
name: 'projectId',
|
|
155
|
+
type: 'string',
|
|
156
|
+
required: true,
|
|
157
|
+
displayOptions: {
|
|
158
|
+
show: {
|
|
159
|
+
resource: ['project'],
|
|
160
|
+
operation: ['get', 'getSecretSnapshots', 'getUserMemberships', 'getUserByUsername'],
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
default: '',
|
|
164
|
+
description: 'The ID of the Infisical project',
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
displayName: 'Slug',
|
|
168
|
+
name: 'slug',
|
|
169
|
+
type: 'string',
|
|
170
|
+
required: true,
|
|
171
|
+
displayOptions: {
|
|
172
|
+
show: {
|
|
173
|
+
resource: ['project'],
|
|
174
|
+
operation: ['getBySlug'],
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
default: '',
|
|
178
|
+
description: 'The slug of the Infisical project',
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
displayName: 'Environment',
|
|
182
|
+
name: 'snapshotEnvironment',
|
|
183
|
+
type: 'string',
|
|
184
|
+
required: true,
|
|
185
|
+
displayOptions: {
|
|
186
|
+
show: {
|
|
187
|
+
resource: ['project'],
|
|
188
|
+
operation: ['getSecretSnapshots'],
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
default: 'dev',
|
|
192
|
+
description: 'The environment slug to retrieve snapshots for (e.g., dev, staging, prod)',
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
displayName: 'Username',
|
|
196
|
+
name: 'username',
|
|
197
|
+
type: 'string',
|
|
198
|
+
required: true,
|
|
199
|
+
displayOptions: {
|
|
200
|
+
show: {
|
|
201
|
+
resource: ['project'],
|
|
202
|
+
operation: ['getUserByUsername'],
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
default: '',
|
|
206
|
+
description: 'The username of the project member to retrieve',
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
displayName: 'Additional Fields',
|
|
210
|
+
name: 'snapshotOptions',
|
|
211
|
+
type: 'collection',
|
|
212
|
+
placeholder: 'Add Field',
|
|
213
|
+
default: {},
|
|
214
|
+
displayOptions: {
|
|
215
|
+
show: {
|
|
216
|
+
resource: ['project'],
|
|
217
|
+
operation: ['getSecretSnapshots'],
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
options: [
|
|
221
|
+
{
|
|
222
|
+
displayName: 'Limit',
|
|
223
|
+
name: 'limit',
|
|
224
|
+
type: 'number',
|
|
225
|
+
default: 20,
|
|
226
|
+
description: 'Maximum number of snapshots to return',
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
displayName: 'Offset',
|
|
230
|
+
name: 'offset',
|
|
231
|
+
type: 'number',
|
|
232
|
+
default: 0,
|
|
233
|
+
description: 'Number of snapshots to skip (pagination)',
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
displayName: 'Secret Path',
|
|
237
|
+
name: 'secretPath',
|
|
238
|
+
type: 'string',
|
|
239
|
+
default: '/',
|
|
240
|
+
description: 'Folder path to filter snapshots (default: /)',
|
|
241
|
+
},
|
|
242
|
+
],
|
|
243
|
+
},
|
|
244
|
+
// ─── Folder operations ──────────────────────────────────────────────────
|
|
245
|
+
{
|
|
246
|
+
displayName: 'Operation',
|
|
247
|
+
name: 'operation',
|
|
248
|
+
type: 'options',
|
|
249
|
+
noDataExpression: true,
|
|
250
|
+
displayOptions: { show: { resource: ['folder'] } },
|
|
251
|
+
options: [
|
|
252
|
+
{
|
|
253
|
+
name: 'Create',
|
|
254
|
+
value: 'createFolder',
|
|
255
|
+
description: 'Create a new folder',
|
|
256
|
+
action: 'Create a folder',
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
name: 'Delete',
|
|
260
|
+
value: 'deleteFolder',
|
|
261
|
+
description: 'Delete a folder by ID or name',
|
|
262
|
+
action: 'Delete a folder',
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
name: 'Get',
|
|
266
|
+
value: 'getFolderById',
|
|
267
|
+
description: 'Get a folder by ID',
|
|
268
|
+
action: 'Get a folder',
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
name: 'List',
|
|
272
|
+
value: 'listFolders',
|
|
273
|
+
description: 'List all folders at a path',
|
|
274
|
+
action: 'List folders',
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
name: 'Update',
|
|
278
|
+
value: 'updateFolder',
|
|
279
|
+
description: 'Update the name or description of a folder',
|
|
280
|
+
action: 'Update a folder',
|
|
281
|
+
},
|
|
282
|
+
],
|
|
283
|
+
default: 'listFolders',
|
|
284
|
+
},
|
|
285
|
+
// ─── Folder fields ──────────────────────────────────────────────────────
|
|
286
|
+
{
|
|
287
|
+
displayName: 'Project ID',
|
|
288
|
+
name: 'projectId',
|
|
289
|
+
type: 'string',
|
|
290
|
+
required: true,
|
|
291
|
+
displayOptions: {
|
|
292
|
+
show: {
|
|
293
|
+
resource: ['folder'],
|
|
294
|
+
operation: ['listFolders', 'createFolder', 'updateFolder', 'deleteFolder'],
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
default: '',
|
|
298
|
+
description: 'The ID of the Infisical project',
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
displayName: 'Environment',
|
|
302
|
+
name: 'environment',
|
|
303
|
+
type: 'string',
|
|
304
|
+
required: true,
|
|
305
|
+
displayOptions: {
|
|
306
|
+
show: {
|
|
307
|
+
resource: ['folder'],
|
|
308
|
+
operation: ['listFolders', 'createFolder', 'updateFolder', 'deleteFolder'],
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
default: 'dev',
|
|
312
|
+
description: 'The environment slug (e.g., dev, staging, prod)',
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
displayName: 'Folder Path',
|
|
316
|
+
name: 'folderPath',
|
|
317
|
+
type: 'string',
|
|
318
|
+
displayOptions: {
|
|
319
|
+
show: {
|
|
320
|
+
resource: ['folder'],
|
|
321
|
+
operation: ['listFolders', 'createFolder', 'updateFolder', 'deleteFolder'],
|
|
322
|
+
},
|
|
323
|
+
},
|
|
324
|
+
default: '/',
|
|
325
|
+
description: 'The path to list from or the parent path for create/update/delete (default: /)',
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
displayName: 'Folder ID',
|
|
329
|
+
name: 'folderId',
|
|
330
|
+
type: 'string',
|
|
331
|
+
required: true,
|
|
332
|
+
displayOptions: {
|
|
333
|
+
show: {
|
|
334
|
+
resource: ['folder'],
|
|
335
|
+
operation: ['getFolderById', 'updateFolder'],
|
|
336
|
+
},
|
|
337
|
+
},
|
|
338
|
+
default: '',
|
|
339
|
+
description: 'The ID of the folder',
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
displayName: 'Folder ID or Name',
|
|
343
|
+
name: 'folderIdOrName',
|
|
344
|
+
type: 'string',
|
|
345
|
+
required: true,
|
|
346
|
+
displayOptions: {
|
|
347
|
+
show: {
|
|
348
|
+
resource: ['folder'],
|
|
349
|
+
operation: ['deleteFolder'],
|
|
350
|
+
},
|
|
351
|
+
},
|
|
352
|
+
default: '',
|
|
353
|
+
description: 'The ID or name of the folder to delete',
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
displayName: 'Folder Name',
|
|
357
|
+
name: 'folderName',
|
|
358
|
+
type: 'string',
|
|
359
|
+
required: true,
|
|
360
|
+
displayOptions: {
|
|
361
|
+
show: {
|
|
362
|
+
resource: ['folder'],
|
|
363
|
+
operation: ['createFolder', 'updateFolder'],
|
|
364
|
+
},
|
|
365
|
+
},
|
|
366
|
+
default: '',
|
|
367
|
+
description: 'The name of the folder',
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
displayName: 'Additional Fields',
|
|
371
|
+
name: 'listFolderOptions',
|
|
372
|
+
type: 'collection',
|
|
373
|
+
placeholder: 'Add Field',
|
|
374
|
+
default: {},
|
|
375
|
+
displayOptions: {
|
|
376
|
+
show: {
|
|
377
|
+
resource: ['folder'],
|
|
378
|
+
operation: ['listFolders'],
|
|
379
|
+
},
|
|
380
|
+
},
|
|
381
|
+
options: [
|
|
382
|
+
{
|
|
383
|
+
displayName: 'Last Secret Modified',
|
|
384
|
+
name: 'lastSecretModified',
|
|
385
|
+
type: 'string',
|
|
386
|
+
default: '',
|
|
387
|
+
description: 'Filter folders modified after this ISO 8601 datetime',
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
displayName: 'Recursive',
|
|
391
|
+
name: 'recursive',
|
|
392
|
+
type: 'boolean',
|
|
393
|
+
default: false,
|
|
394
|
+
description: 'Whether to include subdirectories in the listing',
|
|
395
|
+
},
|
|
396
|
+
],
|
|
397
|
+
},
|
|
398
|
+
{
|
|
399
|
+
displayName: 'Additional Fields',
|
|
400
|
+
name: 'createFolderOptions',
|
|
401
|
+
type: 'collection',
|
|
402
|
+
placeholder: 'Add Field',
|
|
403
|
+
default: {},
|
|
404
|
+
displayOptions: {
|
|
405
|
+
show: {
|
|
406
|
+
resource: ['folder'],
|
|
407
|
+
operation: ['createFolder'],
|
|
408
|
+
},
|
|
409
|
+
},
|
|
410
|
+
options: [
|
|
411
|
+
{
|
|
412
|
+
displayName: 'Description',
|
|
413
|
+
name: 'description',
|
|
414
|
+
type: 'string',
|
|
415
|
+
default: '',
|
|
416
|
+
description: 'An optional label for the folder',
|
|
417
|
+
},
|
|
418
|
+
],
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
displayName: 'Additional Fields',
|
|
422
|
+
name: 'updateFolderOptions',
|
|
423
|
+
type: 'collection',
|
|
424
|
+
placeholder: 'Add Field',
|
|
425
|
+
default: {},
|
|
426
|
+
displayOptions: {
|
|
427
|
+
show: {
|
|
428
|
+
resource: ['folder'],
|
|
429
|
+
operation: ['updateFolder'],
|
|
430
|
+
},
|
|
431
|
+
},
|
|
432
|
+
options: [
|
|
433
|
+
{
|
|
434
|
+
displayName: 'Description',
|
|
435
|
+
name: 'description',
|
|
436
|
+
type: 'string',
|
|
437
|
+
default: '',
|
|
438
|
+
description: 'An updated label for the folder',
|
|
439
|
+
},
|
|
440
|
+
],
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
displayName: 'Additional Fields',
|
|
444
|
+
name: 'deleteFolderOptions',
|
|
445
|
+
type: 'collection',
|
|
446
|
+
placeholder: 'Add Field',
|
|
447
|
+
default: {},
|
|
448
|
+
displayOptions: {
|
|
449
|
+
show: {
|
|
450
|
+
resource: ['folder'],
|
|
451
|
+
operation: ['deleteFolder'],
|
|
452
|
+
},
|
|
453
|
+
},
|
|
454
|
+
options: [
|
|
455
|
+
{
|
|
456
|
+
displayName: 'Force Delete',
|
|
457
|
+
name: 'forceDelete',
|
|
458
|
+
type: 'boolean',
|
|
459
|
+
default: false,
|
|
460
|
+
description: 'Whether to force delete the folder even if it contains secrets or sub-folders',
|
|
461
|
+
},
|
|
462
|
+
],
|
|
463
|
+
},
|
|
126
464
|
// ─── Shared secret fields ────────────────────────────────────────────────
|
|
127
465
|
{
|
|
128
466
|
displayName: 'Project ID',
|
|
129
|
-
name: '
|
|
467
|
+
name: 'projectId',
|
|
130
468
|
type: 'string',
|
|
131
469
|
required: true,
|
|
132
470
|
displayOptions: { show: { resource: ['secret'] } },
|
|
133
471
|
default: '',
|
|
134
|
-
description: 'The ID of the Infisical project
|
|
472
|
+
description: 'The ID of the Infisical project',
|
|
135
473
|
},
|
|
136
474
|
{
|
|
137
475
|
displayName: 'Environment',
|
|
@@ -221,6 +559,44 @@ class Infisical {
|
|
|
221
559
|
},
|
|
222
560
|
],
|
|
223
561
|
},
|
|
562
|
+
{
|
|
563
|
+
displayName: 'Secret Metadata',
|
|
564
|
+
name: 'secretMetadata',
|
|
565
|
+
type: 'fixedCollection',
|
|
566
|
+
typeOptions: { multipleValues: true },
|
|
567
|
+
placeholder: 'Add Metadata Entry',
|
|
568
|
+
default: {},
|
|
569
|
+
displayOptions: {
|
|
570
|
+
show: {
|
|
571
|
+
resource: ['secret'],
|
|
572
|
+
operation: ['create'],
|
|
573
|
+
},
|
|
574
|
+
},
|
|
575
|
+
description: 'Key/value metadata tags to attach to the secret',
|
|
576
|
+
options: [
|
|
577
|
+
{
|
|
578
|
+
displayName: 'Metadata Entry',
|
|
579
|
+
name: 'values',
|
|
580
|
+
values: [
|
|
581
|
+
{
|
|
582
|
+
displayName: 'Key',
|
|
583
|
+
name: 'key',
|
|
584
|
+
type: 'string',
|
|
585
|
+
required: true,
|
|
586
|
+
default: '',
|
|
587
|
+
description: 'Metadata key',
|
|
588
|
+
},
|
|
589
|
+
{
|
|
590
|
+
displayName: 'Value',
|
|
591
|
+
name: 'value',
|
|
592
|
+
type: 'string',
|
|
593
|
+
default: '',
|
|
594
|
+
description: 'Metadata value',
|
|
595
|
+
},
|
|
596
|
+
],
|
|
597
|
+
},
|
|
598
|
+
],
|
|
599
|
+
},
|
|
224
600
|
// ─── Update: all fields optional ─────────────────────────────────────────
|
|
225
601
|
{
|
|
226
602
|
displayName: 'Additional Fields',
|
|
@@ -277,6 +653,44 @@ class Infisical {
|
|
|
277
653
|
},
|
|
278
654
|
],
|
|
279
655
|
},
|
|
656
|
+
{
|
|
657
|
+
displayName: 'Secret Metadata',
|
|
658
|
+
name: 'secretMetadata',
|
|
659
|
+
type: 'fixedCollection',
|
|
660
|
+
typeOptions: { multipleValues: true },
|
|
661
|
+
placeholder: 'Add Metadata Entry',
|
|
662
|
+
default: {},
|
|
663
|
+
displayOptions: {
|
|
664
|
+
show: {
|
|
665
|
+
resource: ['secret'],
|
|
666
|
+
operation: ['update'],
|
|
667
|
+
},
|
|
668
|
+
},
|
|
669
|
+
description: 'Key/value metadata tags to attach to the secret',
|
|
670
|
+
options: [
|
|
671
|
+
{
|
|
672
|
+
displayName: 'Metadata Entry',
|
|
673
|
+
name: 'values',
|
|
674
|
+
values: [
|
|
675
|
+
{
|
|
676
|
+
displayName: 'Key',
|
|
677
|
+
name: 'key',
|
|
678
|
+
type: 'string',
|
|
679
|
+
required: true,
|
|
680
|
+
default: '',
|
|
681
|
+
description: 'Metadata key',
|
|
682
|
+
},
|
|
683
|
+
{
|
|
684
|
+
displayName: 'Value',
|
|
685
|
+
name: 'value',
|
|
686
|
+
type: 'string',
|
|
687
|
+
default: '',
|
|
688
|
+
description: 'Metadata value',
|
|
689
|
+
},
|
|
690
|
+
],
|
|
691
|
+
},
|
|
692
|
+
],
|
|
693
|
+
},
|
|
280
694
|
// ─── Create Many: secrets fixedCollection ─────────────────────────────────
|
|
281
695
|
{
|
|
282
696
|
displayName: 'Secrets',
|
|
@@ -327,6 +741,38 @@ class Infisical {
|
|
|
327
741
|
default: false,
|
|
328
742
|
description: 'Whether to disable multiline encoding for this secret value',
|
|
329
743
|
},
|
|
744
|
+
{
|
|
745
|
+
displayName: 'Secret Metadata',
|
|
746
|
+
name: 'secretMetadata',
|
|
747
|
+
type: 'fixedCollection',
|
|
748
|
+
typeOptions: { multipleValues: true },
|
|
749
|
+
placeholder: 'Add Metadata Entry',
|
|
750
|
+
default: {},
|
|
751
|
+
description: 'Key/value metadata tags to attach to this secret',
|
|
752
|
+
options: [
|
|
753
|
+
{
|
|
754
|
+
displayName: 'Metadata Entry',
|
|
755
|
+
name: 'values',
|
|
756
|
+
values: [
|
|
757
|
+
{
|
|
758
|
+
displayName: 'Key',
|
|
759
|
+
name: 'key',
|
|
760
|
+
type: 'string',
|
|
761
|
+
required: true,
|
|
762
|
+
default: '',
|
|
763
|
+
description: 'Metadata key',
|
|
764
|
+
},
|
|
765
|
+
{
|
|
766
|
+
displayName: 'Value',
|
|
767
|
+
name: 'value',
|
|
768
|
+
type: 'string',
|
|
769
|
+
default: '',
|
|
770
|
+
description: 'Metadata value',
|
|
771
|
+
},
|
|
772
|
+
],
|
|
773
|
+
},
|
|
774
|
+
],
|
|
775
|
+
},
|
|
330
776
|
],
|
|
331
777
|
},
|
|
332
778
|
],
|
|
@@ -409,6 +855,38 @@ class Infisical {
|
|
|
409
855
|
default: false,
|
|
410
856
|
description: 'Whether to disable multiline encoding for this secret value',
|
|
411
857
|
},
|
|
858
|
+
{
|
|
859
|
+
displayName: 'Secret Metadata',
|
|
860
|
+
name: 'secretMetadata',
|
|
861
|
+
type: 'fixedCollection',
|
|
862
|
+
typeOptions: { multipleValues: true },
|
|
863
|
+
placeholder: 'Add Metadata Entry',
|
|
864
|
+
default: {},
|
|
865
|
+
description: 'Key/value metadata tags to attach to this secret',
|
|
866
|
+
options: [
|
|
867
|
+
{
|
|
868
|
+
displayName: 'Metadata Entry',
|
|
869
|
+
name: 'values',
|
|
870
|
+
values: [
|
|
871
|
+
{
|
|
872
|
+
displayName: 'Key',
|
|
873
|
+
name: 'key',
|
|
874
|
+
type: 'string',
|
|
875
|
+
required: true,
|
|
876
|
+
default: '',
|
|
877
|
+
description: 'Metadata key',
|
|
878
|
+
},
|
|
879
|
+
{
|
|
880
|
+
displayName: 'Value',
|
|
881
|
+
name: 'value',
|
|
882
|
+
type: 'string',
|
|
883
|
+
default: '',
|
|
884
|
+
description: 'Metadata value',
|
|
885
|
+
},
|
|
886
|
+
],
|
|
887
|
+
},
|
|
888
|
+
],
|
|
889
|
+
},
|
|
412
890
|
],
|
|
413
891
|
},
|
|
414
892
|
],
|
|
@@ -459,6 +937,70 @@ class Infisical {
|
|
|
459
937
|
},
|
|
460
938
|
],
|
|
461
939
|
},
|
|
940
|
+
// ─── Delete Many: secrets fixedCollection ─────────────────────────────────
|
|
941
|
+
{
|
|
942
|
+
displayName: 'Secrets',
|
|
943
|
+
name: 'secretsToDelete',
|
|
944
|
+
type: 'fixedCollection',
|
|
945
|
+
typeOptions: { multipleValues: true },
|
|
946
|
+
required: true,
|
|
947
|
+
default: {},
|
|
948
|
+
displayOptions: {
|
|
949
|
+
show: {
|
|
950
|
+
resource: ['secret'],
|
|
951
|
+
operation: ['deleteMany'],
|
|
952
|
+
},
|
|
953
|
+
},
|
|
954
|
+
options: [
|
|
955
|
+
{
|
|
956
|
+
displayName: 'Secret',
|
|
957
|
+
name: 'values',
|
|
958
|
+
values: [
|
|
959
|
+
{
|
|
960
|
+
displayName: 'Secret Key',
|
|
961
|
+
name: 'secretKey',
|
|
962
|
+
type: 'string',
|
|
963
|
+
required: true,
|
|
964
|
+
default: '',
|
|
965
|
+
description: 'The name of the secret to delete',
|
|
966
|
+
},
|
|
967
|
+
{
|
|
968
|
+
displayName: 'Type',
|
|
969
|
+
name: 'type',
|
|
970
|
+
type: 'options',
|
|
971
|
+
options: [
|
|
972
|
+
{ name: 'Shared', value: 'shared' },
|
|
973
|
+
{ name: 'Personal', value: 'personal' },
|
|
974
|
+
],
|
|
975
|
+
default: 'shared',
|
|
976
|
+
description: 'Whether to delete the shared or personal variant of the secret',
|
|
977
|
+
},
|
|
978
|
+
],
|
|
979
|
+
},
|
|
980
|
+
],
|
|
981
|
+
},
|
|
982
|
+
{
|
|
983
|
+
displayName: 'Additional Fields',
|
|
984
|
+
name: 'deleteManyOptions',
|
|
985
|
+
type: 'collection',
|
|
986
|
+
placeholder: 'Add Field',
|
|
987
|
+
default: {},
|
|
988
|
+
displayOptions: {
|
|
989
|
+
show: {
|
|
990
|
+
resource: ['secret'],
|
|
991
|
+
operation: ['deleteMany'],
|
|
992
|
+
},
|
|
993
|
+
},
|
|
994
|
+
options: [
|
|
995
|
+
{
|
|
996
|
+
displayName: 'Secret Path Override',
|
|
997
|
+
name: 'secretPath',
|
|
998
|
+
type: 'string',
|
|
999
|
+
default: '/',
|
|
1000
|
+
description: 'Override the top-level Secret Path for this batch request',
|
|
1001
|
+
},
|
|
1002
|
+
],
|
|
1003
|
+
},
|
|
462
1004
|
],
|
|
463
1005
|
};
|
|
464
1006
|
this.methods = {
|
|
@@ -470,13 +1012,17 @@ class Infisical {
|
|
|
470
1012
|
try {
|
|
471
1013
|
let accessToken;
|
|
472
1014
|
if (authType === 'universalAuth') {
|
|
1015
|
+
const loginForm = {
|
|
1016
|
+
clientId: creds.clientId,
|
|
1017
|
+
clientSecret: creds.clientSecret,
|
|
1018
|
+
};
|
|
1019
|
+
if (creds.organizationSlug) {
|
|
1020
|
+
loginForm.organizationSlug = creds.organizationSlug;
|
|
1021
|
+
}
|
|
473
1022
|
const tokenResponse = await this.helpers.request({
|
|
474
1023
|
method: 'POST',
|
|
475
1024
|
uri: `${apiUrl}/v1/auth/universal-auth/login`,
|
|
476
|
-
form:
|
|
477
|
-
clientId: creds.clientId,
|
|
478
|
-
clientSecret: creds.clientSecret,
|
|
479
|
-
},
|
|
1025
|
+
form: loginForm,
|
|
480
1026
|
json: true,
|
|
481
1027
|
});
|
|
482
1028
|
accessToken = tokenResponse.accessToken;
|
|
@@ -506,13 +1052,12 @@ class Infisical {
|
|
|
506
1052
|
};
|
|
507
1053
|
}
|
|
508
1054
|
async execute() {
|
|
509
|
-
var _a, _b, _c;
|
|
510
1055
|
const items = this.getInputData();
|
|
511
1056
|
const returnData = [];
|
|
512
1057
|
const resource = this.getNodeParameter('resource', 0);
|
|
513
1058
|
const operation = this.getNodeParameter('operation', 0);
|
|
514
1059
|
const credentials = await this.getCredentials('infisicalApi');
|
|
515
|
-
const { apiUrl, accessToken } = await getInfisicalToken(this.helpers, credentials);
|
|
1060
|
+
const { apiUrl, accessToken } = await (0, auth_1.getInfisicalToken)(this.helpers, credentials);
|
|
516
1061
|
const baseHeaders = {
|
|
517
1062
|
Authorization: `Bearer ${accessToken}`,
|
|
518
1063
|
Accept: 'application/json',
|
|
@@ -522,205 +1067,18 @@ class Infisical {
|
|
|
522
1067
|
try {
|
|
523
1068
|
// ── Secret resource ─────────────────────────────────────────────────────
|
|
524
1069
|
if (resource === 'secret') {
|
|
525
|
-
const
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
// ── get ───────────────────────────────────────────────────────────────
|
|
529
|
-
if (operation === 'get') {
|
|
530
|
-
const secretKey = this.getNodeParameter('secretKey', i);
|
|
531
|
-
const response = await this.helpers.httpRequest({
|
|
532
|
-
method: 'GET',
|
|
533
|
-
url: `${apiUrl}/v3/secrets/raw/${encodeURIComponent(secretKey)}`,
|
|
534
|
-
headers: baseHeaders,
|
|
535
|
-
qs: { workspaceId, environment, secretPath },
|
|
536
|
-
});
|
|
537
|
-
returnData.push({ json: response, pairedItem: { item: i } });
|
|
538
|
-
// ── getAll ────────────────────────────────────────────────────────────
|
|
539
|
-
}
|
|
540
|
-
else if (operation === 'getAll') {
|
|
541
|
-
const response = await this.helpers.httpRequest({
|
|
542
|
-
method: 'GET',
|
|
543
|
-
url: `${apiUrl}/v3/secrets/raw`,
|
|
544
|
-
headers: baseHeaders,
|
|
545
|
-
qs: { workspaceId, environment, secretPath },
|
|
546
|
-
});
|
|
547
|
-
const secrets = response.secrets;
|
|
548
|
-
for (const secret of secrets) {
|
|
549
|
-
returnData.push({ json: secret, pairedItem: { item: i } });
|
|
550
|
-
}
|
|
551
|
-
// ── create ────────────────────────────────────────────────────────────
|
|
552
|
-
}
|
|
553
|
-
else if (operation === 'create') {
|
|
554
|
-
const secretKey = this.getNodeParameter('secretKey', i);
|
|
555
|
-
const secretValue = this.getNodeParameter('secretValue', i);
|
|
556
|
-
const createOptions = this.getNodeParameter('createOptions', i, {});
|
|
557
|
-
const body = {
|
|
558
|
-
workspaceId,
|
|
559
|
-
environment,
|
|
560
|
-
secretName: secretKey,
|
|
561
|
-
secretValue,
|
|
562
|
-
secretPath,
|
|
563
|
-
type: (_a = createOptions.type) !== null && _a !== void 0 ? _a : 'shared',
|
|
564
|
-
};
|
|
565
|
-
if (createOptions.secretComment)
|
|
566
|
-
body.secretComment = createOptions.secretComment;
|
|
567
|
-
if (createOptions.skipMultilineEncoding) {
|
|
568
|
-
body.skipMultilineEncoding = createOptions.skipMultilineEncoding;
|
|
569
|
-
}
|
|
570
|
-
const response = await this.helpers.httpRequest({
|
|
571
|
-
method: 'POST',
|
|
572
|
-
url: `${apiUrl}/v3/secrets/raw/${encodeURIComponent(secretKey)}`,
|
|
573
|
-
headers: baseHeaders,
|
|
574
|
-
body: JSON.stringify(body),
|
|
575
|
-
});
|
|
576
|
-
returnData.push({ json: response, pairedItem: { item: i } });
|
|
577
|
-
// ── update (v4) ───────────────────────────────────────────────────────
|
|
578
|
-
}
|
|
579
|
-
else if (operation === 'update') {
|
|
580
|
-
const secretKey = this.getNodeParameter('secretKey', i);
|
|
581
|
-
const updateOptions = this.getNodeParameter('updateOptions', i, {});
|
|
582
|
-
const body = {
|
|
583
|
-
projectId: workspaceId,
|
|
584
|
-
environment,
|
|
585
|
-
secretPath,
|
|
586
|
-
};
|
|
587
|
-
// Spread only non-empty optional fields
|
|
588
|
-
if (updateOptions.secretValue !== undefined && updateOptions.secretValue !== '') {
|
|
589
|
-
body.secretValue = updateOptions.secretValue;
|
|
590
|
-
}
|
|
591
|
-
if (updateOptions.newSecretName)
|
|
592
|
-
body.newSecretName = updateOptions.newSecretName;
|
|
593
|
-
if (updateOptions.secretComment !== undefined)
|
|
594
|
-
body.secretComment = updateOptions.secretComment;
|
|
595
|
-
if (updateOptions.type)
|
|
596
|
-
body.type = updateOptions.type;
|
|
597
|
-
if (updateOptions.skipMultilineEncoding) {
|
|
598
|
-
body.skipMultilineEncoding = updateOptions.skipMultilineEncoding;
|
|
599
|
-
}
|
|
600
|
-
const response = await this.helpers.httpRequest({
|
|
601
|
-
method: 'PATCH',
|
|
602
|
-
url: `${apiUrl}/v4/secrets/${encodeURIComponent(secretKey)}`,
|
|
603
|
-
headers: baseHeaders,
|
|
604
|
-
body: JSON.stringify(body),
|
|
605
|
-
});
|
|
606
|
-
returnData.push({ json: response, pairedItem: { item: i } });
|
|
607
|
-
// ── delete ────────────────────────────────────────────────────────────
|
|
608
|
-
}
|
|
609
|
-
else if (operation === 'delete') {
|
|
610
|
-
const secretKey = this.getNodeParameter('secretKey', i);
|
|
611
|
-
const response = await this.helpers.httpRequest({
|
|
612
|
-
method: 'DELETE',
|
|
613
|
-
url: `${apiUrl}/v3/secrets/raw/${encodeURIComponent(secretKey)}`,
|
|
614
|
-
headers: baseHeaders,
|
|
615
|
-
qs: { workspaceId, environment, secretPath },
|
|
616
|
-
});
|
|
617
|
-
returnData.push({ json: response, pairedItem: { item: i } });
|
|
618
|
-
// ── createMany (v4 batch POST) ────────────────────────────────────────
|
|
619
|
-
}
|
|
620
|
-
else if (operation === 'createMany') {
|
|
621
|
-
const secretsParam = this.getNodeParameter('secrets', i, {});
|
|
622
|
-
const secretItems = (_b = secretsParam.values) !== null && _b !== void 0 ? _b : [];
|
|
623
|
-
if (secretItems.length === 0) {
|
|
624
|
-
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'At least one secret must be added in the Secrets list', { itemIndex: i });
|
|
625
|
-
}
|
|
626
|
-
const createManyOptions = this.getNodeParameter('createManyOptions', i, {});
|
|
627
|
-
const effectivePath = createManyOptions.secretPath || secretPath;
|
|
628
|
-
const secrets = secretItems.map((item) => {
|
|
629
|
-
const s = {
|
|
630
|
-
secretKey: item.secretKey,
|
|
631
|
-
secretValue: item.secretValue,
|
|
632
|
-
};
|
|
633
|
-
if (item.secretComment)
|
|
634
|
-
s.secretComment = item.secretComment;
|
|
635
|
-
if (item.skipMultilineEncoding)
|
|
636
|
-
s.skipMultilineEncoding = item.skipMultilineEncoding;
|
|
637
|
-
return s;
|
|
638
|
-
});
|
|
639
|
-
const body = {
|
|
640
|
-
projectId: workspaceId,
|
|
641
|
-
environment,
|
|
642
|
-
secretPath: effectivePath,
|
|
643
|
-
secrets,
|
|
644
|
-
};
|
|
645
|
-
const response = await this.helpers.httpRequest({
|
|
646
|
-
method: 'POST',
|
|
647
|
-
url: `${apiUrl}/v4/secrets/batch`,
|
|
648
|
-
headers: baseHeaders,
|
|
649
|
-
body: JSON.stringify(body),
|
|
650
|
-
});
|
|
651
|
-
const responseData = response;
|
|
652
|
-
if (Array.isArray(responseData.secrets)) {
|
|
653
|
-
for (const secret of responseData.secrets) {
|
|
654
|
-
returnData.push({ json: secret, pairedItem: { item: i } });
|
|
655
|
-
}
|
|
656
|
-
}
|
|
657
|
-
else {
|
|
658
|
-
// Approval / policy-gated response
|
|
659
|
-
returnData.push({ json: responseData, pairedItem: { item: i } });
|
|
660
|
-
}
|
|
661
|
-
// ── updateMany (v4 batch PATCH) ───────────────────────────────────────
|
|
662
|
-
}
|
|
663
|
-
else if (operation === 'updateMany') {
|
|
664
|
-
const secretsToUpdateParam = this.getNodeParameter('secretsToUpdate', i, {});
|
|
665
|
-
const secretItems = (_c = secretsToUpdateParam.values) !== null && _c !== void 0 ? _c : [];
|
|
666
|
-
if (secretItems.length === 0) {
|
|
667
|
-
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'At least one secret must be added in the Secrets list', { itemIndex: i });
|
|
668
|
-
}
|
|
669
|
-
const updateManyOptions = this.getNodeParameter('updateManyOptions', i, {});
|
|
670
|
-
const effectivePath = updateManyOptions.secretPath || secretPath;
|
|
671
|
-
const secrets = secretItems.map((item) => {
|
|
672
|
-
const s = { secretKey: item.secretKey };
|
|
673
|
-
if (item.secretValue !== undefined && item.secretValue !== '') {
|
|
674
|
-
s.secretValue = item.secretValue;
|
|
675
|
-
}
|
|
676
|
-
if (item.newSecretName)
|
|
677
|
-
s.newSecretName = item.newSecretName;
|
|
678
|
-
if (item.secretComment !== undefined && item.secretComment !== '') {
|
|
679
|
-
s.secretComment = item.secretComment;
|
|
680
|
-
}
|
|
681
|
-
if (item.skipMultilineEncoding)
|
|
682
|
-
s.skipMultilineEncoding = item.skipMultilineEncoding;
|
|
683
|
-
return s;
|
|
684
|
-
});
|
|
685
|
-
const body = {
|
|
686
|
-
projectId: workspaceId,
|
|
687
|
-
environment,
|
|
688
|
-
secretPath: effectivePath,
|
|
689
|
-
secrets,
|
|
690
|
-
};
|
|
691
|
-
if (updateManyOptions.mode)
|
|
692
|
-
body.mode = updateManyOptions.mode;
|
|
693
|
-
const response = await this.helpers.httpRequest({
|
|
694
|
-
method: 'PATCH',
|
|
695
|
-
url: `${apiUrl}/v4/secrets/batch`,
|
|
696
|
-
headers: baseHeaders,
|
|
697
|
-
body: JSON.stringify(body),
|
|
698
|
-
});
|
|
699
|
-
const responseData = response;
|
|
700
|
-
if (Array.isArray(responseData.secrets)) {
|
|
701
|
-
for (const secret of responseData.secrets) {
|
|
702
|
-
returnData.push({ json: secret, pairedItem: { item: i } });
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
else {
|
|
706
|
-
// Approval / policy-gated response
|
|
707
|
-
returnData.push({ json: responseData, pairedItem: { item: i } });
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
// ── Workspace resource ──────────────────────────────────────────────────
|
|
1070
|
+
const results = await (0, secretOperations_1.executeSecretOperation)(this, apiUrl, baseHeaders, operation, i);
|
|
1071
|
+
returnData.push(...results);
|
|
1072
|
+
// ── Project resource ──────────────────────────────────────────────────
|
|
711
1073
|
}
|
|
712
|
-
else if (resource === '
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
for (const workspace of workspaces) {
|
|
721
|
-
returnData.push({ json: workspace, pairedItem: { item: i } });
|
|
722
|
-
}
|
|
723
|
-
}
|
|
1074
|
+
else if (resource === 'project') {
|
|
1075
|
+
const results = await (0, projectOperations_1.executeProjectOperation)(this, apiUrl, baseHeaders, operation, i);
|
|
1076
|
+
returnData.push(...results);
|
|
1077
|
+
// ── Folder resource ──────────────────────────────────────────────────
|
|
1078
|
+
}
|
|
1079
|
+
else if (resource === 'folder') {
|
|
1080
|
+
const results = await (0, folderOperations_1.executeFolderOperation)(this, apiUrl, baseHeaders, operation, i);
|
|
1081
|
+
returnData.push(...results);
|
|
724
1082
|
}
|
|
725
1083
|
}
|
|
726
1084
|
catch (error) {
|