@synapseone/cli 0.9.0-dev.77 → 0.9.0-dev.79
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/synapseone.js +69 -9
- package/package.json +1 -1
package/bin/synapseone.js
CHANGED
|
@@ -261,6 +261,15 @@ function parse(argv) {
|
|
|
261
261
|
if (!v) throw new Error('missing value for --context-url <url>');
|
|
262
262
|
(opts.contextUrls ??= []).push(v);
|
|
263
263
|
}
|
|
264
|
+
// Token management flags.
|
|
265
|
+
else if (a === '--grace') opts.grace = argv[++i];
|
|
266
|
+
else if (a.startsWith('--grace=')) opts.grace = a.slice(8);
|
|
267
|
+
else if (a === '--scopes') opts.scopes = argv[++i];
|
|
268
|
+
else if (a.startsWith('--scopes=')) opts.scopes = a.slice(9);
|
|
269
|
+
else if (a === '--user') opts.user = argv[++i];
|
|
270
|
+
else if (a.startsWith('--user=')) opts.user = a.slice(7);
|
|
271
|
+
else if (a === '--managed') opts.managed = argv[++i];
|
|
272
|
+
else if (a.startsWith('--managed=')) opts.managed = a.slice(10);
|
|
264
273
|
else args.push(a);
|
|
265
274
|
}
|
|
266
275
|
return { args, opts };
|
|
@@ -428,7 +437,9 @@ async function cmdPolicies(o) {
|
|
|
428
437
|
const [sub, ...rest] = o._;
|
|
429
438
|
if (sub === 'create') {
|
|
430
439
|
const [account, slug] = rest;
|
|
431
|
-
need(account, 'account'); need(slug, 'slug');
|
|
440
|
+
need(account, 'account'); need(slug, 'slug');
|
|
441
|
+
if (o.managed) return out(await POST(`/v1/accounts/${encodeURIComponent(account)}/policies`, { slug, managed: o.managed }, o), o);
|
|
442
|
+
need(o.file, '--file policy.json (or --managed NAME)');
|
|
432
443
|
return out(await POST(`/v1/accounts/${encodeURIComponent(account)}/policies`, { slug, document: readJson(o.file) }, o), o);
|
|
433
444
|
}
|
|
434
445
|
if (sub === 'delete') {
|
|
@@ -475,9 +486,22 @@ async function cmdKeys(o) {
|
|
|
475
486
|
const [sub, ...rest] = o._;
|
|
476
487
|
if (sub === 'create') {
|
|
477
488
|
need(rest[0], 'account');
|
|
478
|
-
const
|
|
479
|
-
|
|
480
|
-
|
|
489
|
+
const scopes = o.scopes ? String(o.scopes).split(',').map((x) => x.trim()).filter(Boolean) : ['*'];
|
|
490
|
+
const body = { name: o.name || o.label || 'cli', scopes, ...(o.user ? { userId: o.user } : {}) };
|
|
491
|
+
const r = await POST(`/v1/accounts/${encodeURIComponent(rest[0])}/keys`, body, o);
|
|
492
|
+
// The new secret is printed to stdout once, on purpose (never to a log).
|
|
493
|
+
if (!o.json) process.stdout.write(`SAVE THIS KEY (shown once):\n${r.apiKey}\nid: ${r.id}\n`);
|
|
494
|
+
else process.stdout.write(`${JSON.stringify(r, null, 2)}\n`);
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
if (sub === 'rotate') {
|
|
498
|
+
need(rest[0], 'key-id');
|
|
499
|
+
const graceSeconds = o.grace === undefined ? 0 : Number(o.grace);
|
|
500
|
+
if (!Number.isInteger(graceSeconds) || graceSeconds < 0) throw new Error('--grace must be a non-negative integer (seconds)');
|
|
501
|
+
const r = await POST(`/v1/keys/${encodeURIComponent(rest[0])}/rotate`, { graceSeconds }, o);
|
|
502
|
+
// The new secret is printed to stdout once, on purpose (never to a log).
|
|
503
|
+
if (!o.json) process.stdout.write(`SAVE THIS KEY (shown once):\n${r.apiKey}\nid: ${r.id}\nold key ${r.rotatedFrom} expires at ${r.oldKeyExpiresAt}\n`);
|
|
504
|
+
else process.stdout.write(`${JSON.stringify(r, null, 2)}\n`);
|
|
481
505
|
return;
|
|
482
506
|
}
|
|
483
507
|
if (sub === 'revoke' || sub === 'delete') {
|
|
@@ -491,9 +515,9 @@ async function cmdKeys(o) {
|
|
|
491
515
|
if (sub === 'list') {
|
|
492
516
|
need(rest[0], 'account');
|
|
493
517
|
const r = await GET(`/v1/accounts/${encodeURIComponent(rest[0])}/keys`, o);
|
|
494
|
-
return out(Array.isArray(r) ? r : [], o, ['id', 'name', 'prefix', 'revoked_at']);
|
|
518
|
+
return out(Array.isArray(r) ? r : [], o, ['id', 'name', 'prefix', 'scopes', 'user_id', 'last_used_at', 'revoked_at']);
|
|
495
519
|
}
|
|
496
|
-
throw new Error(`usage: keys create <account> [--name N] | keys list <account> | keys revoke <key-id> | keys verify <api-key>`);
|
|
520
|
+
throw new Error(`usage: keys create <account> [--name N] [--scopes a,b] [--user USER_ID] | keys list <account> | keys rotate <key-id> [--grace SECONDS] | keys revoke <key-id> | keys verify <api-key>`);
|
|
497
521
|
}
|
|
498
522
|
async function cmdSa(o) {
|
|
499
523
|
const [sub, ...rest] = o._;
|
|
@@ -508,9 +532,42 @@ async function cmdSa(o) {
|
|
|
508
532
|
else console.log(JSON.stringify(r, null, 2));
|
|
509
533
|
return;
|
|
510
534
|
}
|
|
535
|
+
if (sub === 'roles') {
|
|
536
|
+
need(rest[0], 'sa-id');
|
|
537
|
+
return out(await GET(`/v1/service-accounts/${encodeURIComponent(rest[0])}/roles`, o), o, ['slug', 'id']);
|
|
538
|
+
}
|
|
539
|
+
if (sub === 'grant') {
|
|
540
|
+
need(rest[0], 'sa-id'); need(rest[1], 'role-id');
|
|
541
|
+
return out(await POST(`/v1/service-accounts/${encodeURIComponent(rest[0])}/roles`, { roleId: rest[1] }, o), o);
|
|
542
|
+
}
|
|
543
|
+
if (sub === 'revoke-role') {
|
|
544
|
+
need(rest[0], 'sa-id'); need(rest[1], 'role-id');
|
|
545
|
+
return out(await DEL(`/v1/service-accounts/${encodeURIComponent(rest[0])}/roles/${encodeURIComponent(rest[1])}`, o), o);
|
|
546
|
+
}
|
|
511
547
|
need(sub, 'account');
|
|
512
548
|
return out(await GET(`/v1/accounts/${encodeURIComponent(sub)}/service-accounts`, o), o, ['slug', 'id']);
|
|
513
549
|
}
|
|
550
|
+
|
|
551
|
+
// ---------- token management: sessions, org admins, managed policies ----------
|
|
552
|
+
async function cmdSessions(o) {
|
|
553
|
+
const [sub, ...rest] = o._;
|
|
554
|
+
if (sub === 'revoke') {
|
|
555
|
+
need(rest[0], 'session-id');
|
|
556
|
+
return out(await DEL(`/v1/auth/sessions/${encodeURIComponent(rest[0])}`, o), o);
|
|
557
|
+
}
|
|
558
|
+
if (sub && sub !== 'list') throw new Error('usage: sessions [list] | sessions revoke <session-id>');
|
|
559
|
+
return out(await GET('/v1/auth/sessions', o), o, ['id', 'created_at', 'expires_at']);
|
|
560
|
+
}
|
|
561
|
+
async function cmdOrgAdmin(o) {
|
|
562
|
+
const [userId, flag] = o._;
|
|
563
|
+
need(userId, 'user-id');
|
|
564
|
+
if (flag !== 'on' && flag !== 'off') throw new Error('usage: org-admin <user-id> on|off');
|
|
565
|
+
return out(await req('PUT', `/v1/users/${encodeURIComponent(userId)}/org-admin`, { isOrgAdmin: flag === 'on' }, o), o);
|
|
566
|
+
}
|
|
567
|
+
async function cmdManagedPolicies(o) {
|
|
568
|
+
return out(await GET('/v1/managed-policies', o), o, ['name', 'description']);
|
|
569
|
+
}
|
|
570
|
+
|
|
514
571
|
async function cmdWorkflows(o) {
|
|
515
572
|
const [sub, ...rest] = o._;
|
|
516
573
|
if (!sub || sub === 'list') {
|
|
@@ -955,7 +1012,10 @@ const COMMANDS = {
|
|
|
955
1012
|
accounts: { fn: cmdAccounts, use: 'accounts [org] [list] | accounts create [org] <slug> [name]', doc: 'Accounts' },
|
|
956
1013
|
users: { fn: cmdUsers, use: 'users [org] | users create <org> <email> [name] | users policies <user-id>', doc: 'Users + effective policies' },
|
|
957
1014
|
roles: { fn: cmdRoles, use: 'roles <account> [list] | roles create <account> <slug> | roles delete <id>', doc: 'Roles' },
|
|
958
|
-
policies: { fn: cmdPolicies, use: 'policies <account> [list] | policies create <account> <slug> --file p.json | policies delete <id>', doc: 'Policies' },
|
|
1015
|
+
policies: { fn: cmdPolicies, use: 'policies <account> [list] | policies create <account> <slug> (--file p.json | --managed ReadOnlyAccess) | policies delete <id>', doc: 'Policies' },
|
|
1016
|
+
'managed-policies': { fn: cmdManagedPolicies, use: 'managed-policies', doc: 'AWS-style managed policies (AdministratorAccess, ReadOnlyAccess, ...)' },
|
|
1017
|
+
'org-admin': { fn: cmdOrgAdmin, use: 'org-admin <user-id> on|off', doc: 'Grant/revoke organization administrator' },
|
|
1018
|
+
sessions: { fn: cmdSessions, use: 'sessions [list] | sessions revoke <session-id>', doc: 'Your login sessions (refresh tokens)' },
|
|
959
1019
|
attach: { fn: cmdAttach, use: 'attach <role-id> <policy-id>', doc: 'Attach policy to role' },
|
|
960
1020
|
detach: { fn: cmdDetach, use: 'detach <role-id> <policy-id>', doc: 'Detach policy from role' },
|
|
961
1021
|
assign: { fn: cmdAssign, use: 'assign <user-id> <role-id>', doc: 'Assign role to user' },
|
|
@@ -963,8 +1023,8 @@ const COMMANDS = {
|
|
|
963
1023
|
authz: { fn: cmdAuthz, use: 'authz <user> <action> <resource> [--context k=v]', doc: 'Authorize check' },
|
|
964
1024
|
sim: { fn: cmdSim, use: 'sim --file policy.json <action> <resource> [--context k=v]', doc: 'Policy simulator' },
|
|
965
1025
|
audit: { fn: cmdAudit, use: 'audit [--limit N] [--actor ID]', doc: 'Audit log' },
|
|
966
|
-
keys: { fn: cmdKeys, use: 'keys create <account> [--name N] | keys list <account> | keys revoke <key-id> | keys verify <api-key>', doc: 'API keys' },
|
|
967
|
-
sa: { fn: cmdSa, use: 'sa <account> [list] | sa create <account> <slug> | sa token <sa-id>', doc: 'Service accounts' },
|
|
1026
|
+
keys: { fn: cmdKeys, use: 'keys create <account> [--name N] [--scopes a,b] [--user USER_ID] | keys list <account> | keys rotate <key-id> [--grace SECONDS] | keys revoke <key-id> | keys verify <api-key>', doc: 'API keys (scoped, owner-bound, rotatable)' },
|
|
1027
|
+
sa: { fn: cmdSa, use: 'sa <account> [list] | sa create <account> <slug> | sa token <sa-id> | sa roles <sa-id> | sa grant <sa-id> <role-id> | sa revoke-role <sa-id> <role-id>', doc: 'Service accounts + their roles' },
|
|
968
1028
|
credentials: { fn: cmdCredentials, use: 'credentials create <account> --name N --type bearer|basic|apiKey|oauth2 (--secret S | --secret-file F) [--expires-at ISO] | credentials [list] <account> | credentials get|delete <id> | credentials rotate <id> (--secret S | --secret-file F)', doc: 'Account credentials, secrets write-only (PROPOSED: backend in progress)' },
|
|
969
1029
|
call: { fn: cmdCall, use: 'call <METHOD> <path> [--data \'{...}\'|body.json] [--file body.json]', doc: 'Generic gateway call (escape hatch for new endpoints)' },
|
|
970
1030
|
workflows: { fn: cmdWorkflows, use: 'workflows [list] | workflows create --template T [--name N] | workflows create --file def.json [--name N] | workflows get|activate|deactivate <id> | workflows exec|execute <id> [--data \'{...}\'|input.json] [--file payload.json] | workflows update [--name N] [--file def.json] <id> | workflows delete <id> | workflows test-run --file def.json [--input input.json|\'{...}\'] [--workflow-id ID]', doc: 'Workflows (local engine)' },
|
package/package.json
CHANGED