@athsra/cli 1.1.5 → 1.1.7
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/package.json +2 -2
- package/src/commands/rotate-master.ts +30 -12
- package/src/index.ts +3 -1
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@athsra/cli",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.7",
|
|
4
4
|
"description": "athsra CLI — E2EE secret manager on Cloudflare edge. Doppler-style dev UX + zero-knowledge encryption + soft-delete + version history. MIT.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
7
7
|
"bin": {
|
|
8
|
-
"athsra": "
|
|
8
|
+
"athsra": "src/index.ts"
|
|
9
9
|
},
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"repository": {
|
|
@@ -88,15 +88,33 @@ export async function rotateMasterCmd(_args: string[]): Promise<number> {
|
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
// 1. 모든
|
|
91
|
+
// 1. 모든 project × 모든 활성 config decrypt (옛 master pw, v1+v2 dispatcher). 비-default 환경
|
|
92
|
+
// (dev/staging/prod)까지 포함해야 한다 — 누락하면 회전 후 옛 pw 소실로 그 환경 시크릿이 영구
|
|
93
|
+
// 복호 불가(데이터 손실). dashboard lib/rotate-master 와 동일 정합.
|
|
92
94
|
const projects = await client.listProjects();
|
|
93
|
-
|
|
94
|
-
const plaintexts: Record<string, Record<string, string>> = {};
|
|
95
|
+
const targets: { project: string; config: string }[] = [];
|
|
95
96
|
for (const p of projects) {
|
|
96
|
-
|
|
97
|
+
try {
|
|
98
|
+
const res = await client.listConfigs(p);
|
|
99
|
+
const active = res.configs.filter((c) => c.active && !c.deleted).map((c) => c.config);
|
|
100
|
+
if (active.length === 0) targets.push({ project: p, config: 'default' });
|
|
101
|
+
else for (const config of active) targets.push({ project: p, config });
|
|
102
|
+
} catch {
|
|
103
|
+
// listConfigs 실패 — 최소 default 는 시도(누락보다 안전).
|
|
104
|
+
targets.push({ project: p, config: 'default' });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const cfgLabel = (t: { project: string; config: string }) =>
|
|
108
|
+
t.config === 'default' ? t.project : `${t.project}:${t.config}`;
|
|
109
|
+
console.log(
|
|
110
|
+
`\n• Decrypting ${targets.length} envelope(s) across ${projects.length} project(s) with old master pw...`,
|
|
111
|
+
);
|
|
112
|
+
const decrypted: { project: string; config: string; plain: Record<string, string> }[] = [];
|
|
113
|
+
for (const t of targets) {
|
|
114
|
+
const plain = await readPlain(ctx, t.project, t.config);
|
|
97
115
|
if (!plain) continue;
|
|
98
|
-
|
|
99
|
-
console.log(` ✓ ${
|
|
116
|
+
decrypted.push({ project: t.project, config: t.config, plain });
|
|
117
|
+
console.log(` ✓ ${cfgLabel(t)} (${Object.keys(plain).length} keys)`);
|
|
100
118
|
}
|
|
101
119
|
|
|
102
120
|
// 2. identity 키쌍 재포장 재료 계산 (있으면) — old pw 로 unwrap → new pw 로 wrap. proof 회전
|
|
@@ -135,18 +153,18 @@ export async function rotateMasterCmd(_args: string[]): Promise<number> {
|
|
|
135
153
|
|
|
136
154
|
// 4. re-encrypt + PUT (v2 envelope, 자동 마이그레이션)
|
|
137
155
|
console.log(
|
|
138
|
-
`\n• Re-encrypting ${
|
|
156
|
+
`\n• Re-encrypting ${decrypted.length} envelope(s) with new master pw ` +
|
|
139
157
|
'(v2, Argon2id m=256MB enterprise)...',
|
|
140
158
|
);
|
|
141
|
-
for (const
|
|
159
|
+
for (const { project, config, plain } of decrypted) {
|
|
142
160
|
// rotate-master = enterprise KDF 마이그레이션 지점 (m=256MB). 이후 routine set 은
|
|
143
|
-
// writePlain 의 보존 로직으로 256MB 유지 (silent downgrade 없음).
|
|
144
|
-
await writePlain(newCtx,
|
|
145
|
-
console.log(` ✓ ${
|
|
161
|
+
// writePlain 의 보존 로직으로 256MB 유지 (silent downgrade 없음). config 전파 필수.
|
|
162
|
+
await writePlain(newCtx, project, plain, { kdfParams: ENTERPRISE_KDF, config });
|
|
163
|
+
console.log(` ✓ ${cfgLabel({ project, config })}`);
|
|
146
164
|
}
|
|
147
165
|
|
|
148
166
|
console.log(
|
|
149
|
-
`\n✓ master password rotated. ${
|
|
167
|
+
`\n✓ master password rotated. ${decrypted.length} envelope(s) re-encrypted ` +
|
|
150
168
|
'as v2 (Argon2id m=256MB).',
|
|
151
169
|
);
|
|
152
170
|
console.log(
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
+
import pkg from '../package.json';
|
|
2
3
|
import { projectCmd, roleCmd, usersCmd } from './commands/admin.ts';
|
|
3
4
|
import { adoptCmd } from './commands/adopt.ts';
|
|
4
5
|
import { auditCmd } from './commands/audit.ts';
|
|
@@ -29,7 +30,8 @@ import { setCmd } from './commands/set.ts';
|
|
|
29
30
|
import { unsetCmd } from './commands/unset.ts';
|
|
30
31
|
import { versionsCmd } from './commands/versions.ts';
|
|
31
32
|
|
|
32
|
-
|
|
33
|
+
// package.json 단일 출처 — 하드코딩 desync 방지(1.1.3 이후 bump 누락으로 --version 이 stale 했던 버그 근본 수정).
|
|
34
|
+
const VERSION = pkg.version;
|
|
33
35
|
|
|
34
36
|
const commands: Record<string, (args: string[]) => Promise<number>> = {
|
|
35
37
|
login: loginCmd,
|