@mstone6969/vault 0.2.0 → 0.5.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 +198 -6
- package/dist/crypto.d.ts +99 -2
- package/dist/crypto.d.ts.map +1 -1
- package/dist/errors.d.ts +122 -4
- package/dist/errors.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +447 -33
- package/dist/index.js.map +9 -7
- package/dist/providers.d.ts +131 -0
- package/dist/providers.d.ts.map +1 -0
- package/dist/stores/file.d.ts +190 -0
- package/dist/stores/file.d.ts.map +1 -0
- package/dist/stores/file.js +1 -0
- package/dist/stores/memory.d.ts +98 -7
- package/dist/stores/memory.d.ts.map +1 -1
- package/dist/stores/sqlite.d.ts +140 -9
- package/dist/stores/sqlite.d.ts.map +1 -1
- package/dist/stores/sqlite.js +47 -12
- package/dist/stores/sqlite.js.map +3 -3
- package/dist/types.d.ts +408 -17
- package/dist/types.d.ts.map +1 -1
- package/dist/vault.d.ts +554 -19
- package/dist/vault.d.ts.map +1 -1
- package/docs/README.md +10 -0
- package/docs/index/README.md +48 -0
- package/docs/index/classes/FileStore.md +341 -0
- package/docs/index/classes/MemoryStore.md +240 -0
- package/docs/index/classes/Vault.md +805 -0
- package/docs/index/classes/VaultError.md +371 -0
- package/docs/index/classes/VaultKeyError.md +370 -0
- package/docs/index/functions/envKey.md +43 -0
- package/docs/index/functions/fileKey.md +46 -0
- package/docs/index/functions/generateKey.md +39 -0
- package/docs/index/functions/importKey.md +49 -0
- package/docs/index/functions/isKeyProvider.md +43 -0
- package/docs/index/functions/open.md +67 -0
- package/docs/index/functions/randomValue.md +53 -0
- package/docs/index/functions/seal.md +56 -0
- package/docs/index/functions/staticKey.md +39 -0
- package/docs/index/type-aliases/Generator.md +58 -0
- package/docs/index/type-aliases/HistoryEntry.md +65 -0
- package/docs/index/type-aliases/KeyProvider.md +74 -0
- package/docs/index/type-aliases/PutOptions.md +141 -0
- package/docs/index/type-aliases/RekeyReport.md +37 -0
- package/docs/index/type-aliases/RotationContext.md +49 -0
- package/docs/index/type-aliases/RotationPolicy.md +142 -0
- package/docs/index/type-aliases/SecretRecord.md +214 -0
- package/docs/index/type-aliases/SecretSummary.md +56 -0
- package/docs/index/type-aliases/VaultEvent.md +95 -0
- package/docs/index/type-aliases/VaultOptions.md +142 -0
- package/docs/index/type-aliases/VaultStore.md +156 -0
- package/docs/index/variables/DEFAULT_ALPHABET.md +29 -0
- package/docs/index/variables/DEFAULT_HISTORY_LIMIT.md +28 -0
- package/docs/index/variables/DEFAULT_PREFIX.md +23 -0
- package/docs/stores/sqlite/README.md +11 -0
- package/docs/stores/sqlite/classes/SqliteStore.md +307 -0
- package/package.json +15 -5
package/dist/vault.d.ts
CHANGED
|
@@ -1,24 +1,266 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import { type KeyProvider } from "./providers";
|
|
2
|
+
import type { PutOptions, SecretSummary, VaultEvent, VaultStore } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* How a stored value is referenced from configuration.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* {@link Vault.resolve} substitutes any value that starts with this. Give a
|
|
8
|
+
* vault its own {@link VaultOptions.prefix} when `@vault:` already means
|
|
9
|
+
* something else in the configuration you are resolving.
|
|
10
|
+
*
|
|
11
|
+
* @defaultValue `"@vault:"`
|
|
12
|
+
*/
|
|
3
13
|
export declare const DEFAULT_PREFIX = "@vault:";
|
|
14
|
+
/**
|
|
15
|
+
* How many previous values an entry keeps, unless you say otherwise.
|
|
16
|
+
*
|
|
17
|
+
* @remarks
|
|
18
|
+
* Only {@link Vault.rotate} adds to history, so this is how many superseded
|
|
19
|
+
* values {@link Vault.versions} can still hand back.
|
|
20
|
+
*
|
|
21
|
+
* @defaultValue 5
|
|
22
|
+
* @see {@link VaultOptions.historyLimit}
|
|
23
|
+
*/
|
|
24
|
+
export declare const DEFAULT_HISTORY_LIMIT = 5;
|
|
25
|
+
/**
|
|
26
|
+
* What a random rotation draws from unless the policy says otherwise.
|
|
27
|
+
*
|
|
28
|
+
* @remarks
|
|
29
|
+
* Letters and digits only, so a generated value survives being pasted into a
|
|
30
|
+
* shell command or a connection string without quoting. Set
|
|
31
|
+
* {@link RotationPolicy.alphabet} for anything narrower or wider.
|
|
32
|
+
*
|
|
33
|
+
* @defaultValue A-Z, a-z and 0-9: 62 characters
|
|
34
|
+
* @see {@link randomValue}
|
|
35
|
+
*/
|
|
36
|
+
export declare const DEFAULT_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
37
|
+
/**
|
|
38
|
+
* Everything a generator is told: which entry is being rotated and the
|
|
39
|
+
* non-secret arguments its policy carries. Deliberately not the current value —
|
|
40
|
+
* a generator that needs it can ask the vault for it.
|
|
41
|
+
*
|
|
42
|
+
* @see {@link Generator}, {@link RotationPolicy.arguments}
|
|
43
|
+
*/
|
|
44
|
+
export type RotationContext = {
|
|
45
|
+
/** Whose entry is being rotated. */
|
|
46
|
+
owner: string;
|
|
47
|
+
/** Which entry is being rotated. */
|
|
48
|
+
name: string;
|
|
49
|
+
/** The non-secret arguments its policy carries. */
|
|
50
|
+
arguments: Record<string, string>;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Produces the next value for an entry whose policy names it.
|
|
54
|
+
*
|
|
55
|
+
* @remarks
|
|
56
|
+
* Registered under a name in {@link VaultOptions.generators} and asked for by
|
|
57
|
+
* {@link RotationPolicy.generator}. Use one where the vault cannot invent the
|
|
58
|
+
* value itself — a key only the far end can mint, or a password that has to be
|
|
59
|
+
* set on a database before it means anything.
|
|
60
|
+
*
|
|
61
|
+
* @param context Which entry is being rotated and its policy's arguments. Not
|
|
62
|
+
* the value being replaced.
|
|
63
|
+
* @returns The next value, or a promise of it.
|
|
64
|
+
*
|
|
65
|
+
* @example Minting a key at the provider that issues it
|
|
66
|
+
* ```ts
|
|
67
|
+
* const vault = new Vault({
|
|
68
|
+
* key: generateKey(),
|
|
69
|
+
* store: new MemoryStore(),
|
|
70
|
+
* generators: {
|
|
71
|
+
* provider: async ({ arguments: args }) => mintKeyFor(args.account),
|
|
72
|
+
* },
|
|
73
|
+
* })
|
|
74
|
+
*
|
|
75
|
+
* await vault.put("alice", "api", "old-key", {
|
|
76
|
+
* rotation: {
|
|
77
|
+
* kind: "generator",
|
|
78
|
+
* generator: "provider",
|
|
79
|
+
* arguments: { account: "acct_123" },
|
|
80
|
+
* },
|
|
81
|
+
* })
|
|
82
|
+
* await vault.rotate("alice", "api")
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
export type Generator = (context: RotationContext) => Promise<string> | string;
|
|
86
|
+
/**
|
|
87
|
+
* A random string of `length` characters drawn from `alphabet`.
|
|
88
|
+
*
|
|
89
|
+
* Sampling is rejected rather than folded with `%`, so every character is
|
|
90
|
+
* equally likely however odd the alphabet's length.
|
|
91
|
+
*
|
|
92
|
+
* @param length How many characters to produce. Defaults to 32.
|
|
93
|
+
* @param alphabet The characters to draw from. Defaults to
|
|
94
|
+
* {@link DEFAULT_ALPHABET}.
|
|
95
|
+
* @returns A fresh string of exactly `length` characters.
|
|
96
|
+
* @throws {@link VaultError} 422 when `length` is below one, or `alphabet` has
|
|
97
|
+
* fewer than two characters — neither can produce anything unguessable.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```ts
|
|
101
|
+
* randomValue() // 32 characters of A-Z, a-z, 0-9
|
|
102
|
+
* randomValue(16, "0123456789abcdef") // 16 hex characters
|
|
103
|
+
* ```
|
|
104
|
+
*
|
|
105
|
+
* @see {@link RotationPolicy} to have the vault call this during a rotation.
|
|
106
|
+
*/
|
|
107
|
+
export declare function randomValue(length?: number, alphabet?: string): string;
|
|
108
|
+
/**
|
|
109
|
+
* Everything a {@link Vault} is built from.
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```ts
|
|
113
|
+
* import { Vault, MemoryStore, envKey } from "@mstone6969/vault"
|
|
114
|
+
*
|
|
115
|
+
* const vault = new Vault({
|
|
116
|
+
* key: envKey("VAULT_KEY"),
|
|
117
|
+
* store: new MemoryStore(),
|
|
118
|
+
* historyLimit: 2,
|
|
119
|
+
* onAccess: (event) => console.log(event.action, event.owner, event.name),
|
|
120
|
+
* })
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
4
123
|
export type VaultOptions = {
|
|
5
|
-
/**
|
|
6
|
-
key: string | CryptoKey;
|
|
124
|
+
/** The master key: base64, already imported, or a provider that finds one. */
|
|
125
|
+
key: string | CryptoKey | KeyProvider;
|
|
126
|
+
/** Where records are kept. */
|
|
7
127
|
store: VaultStore;
|
|
8
|
-
/**
|
|
128
|
+
/**
|
|
129
|
+
* Reference prefix, `@vault:` unless you say otherwise.
|
|
130
|
+
*
|
|
131
|
+
* @defaultValue {@link DEFAULT_PREFIX}
|
|
132
|
+
*/
|
|
9
133
|
prefix?: string;
|
|
134
|
+
/**
|
|
135
|
+
* Keys this vault will still open values with, but never seal under.
|
|
136
|
+
*
|
|
137
|
+
* Keep the old key here while a `rekey` is in flight, or after one that did
|
|
138
|
+
* not finish: values left under it stay readable instead of becoming
|
|
139
|
+
* unopenable the moment the primary key changes.
|
|
140
|
+
*
|
|
141
|
+
* @defaultValue none
|
|
142
|
+
* @see {@link Vault.rekey}
|
|
143
|
+
*/
|
|
144
|
+
previousKeys?: (string | CryptoKey | KeyProvider)[];
|
|
145
|
+
/**
|
|
146
|
+
* How many previous values `rotate` keeps.
|
|
147
|
+
*
|
|
148
|
+
* @defaultValue {@link DEFAULT_HISTORY_LIMIT}
|
|
149
|
+
*/
|
|
150
|
+
historyLimit?: number;
|
|
151
|
+
/**
|
|
152
|
+
* Functions that mint new values, by the name a rotation policy uses.
|
|
153
|
+
*
|
|
154
|
+
* The vault stores the *name*, never the function — so what is written down
|
|
155
|
+
* is that an entry can be rotated, not how to impersonate the thing that
|
|
156
|
+
* rotates it.
|
|
157
|
+
*
|
|
158
|
+
* @defaultValue none, so a `generator` policy fails with 501
|
|
159
|
+
*/
|
|
160
|
+
generators?: Record<string, Generator>;
|
|
161
|
+
/**
|
|
162
|
+
* Called after everything the vault does, for an audit trail. It is never
|
|
163
|
+
* awaited and its failures are ignored — logging must not break a vault.
|
|
164
|
+
*
|
|
165
|
+
* @see {@link VaultEvent} for what it is told, including the refusals,
|
|
166
|
+
* which arrive as `denied` with a `detail` saying which rule was hit.
|
|
167
|
+
*/
|
|
168
|
+
onAccess?: (event: VaultEvent) => void;
|
|
169
|
+
};
|
|
170
|
+
/**
|
|
171
|
+
* What a `rekey` did, and to what it could not do it.
|
|
172
|
+
*
|
|
173
|
+
* @see {@link Vault.rekey}
|
|
174
|
+
*/
|
|
175
|
+
export type RekeyReport = {
|
|
176
|
+
/** How many entries were re-sealed under the new key. */
|
|
177
|
+
rekeyed: number;
|
|
178
|
+
/** Entries that would not open, by `owner/name`, left exactly as they were. */
|
|
179
|
+
failed: string[];
|
|
10
180
|
};
|
|
11
181
|
/**
|
|
12
|
-
* A write-only credential store: values go in, and only `open` and
|
|
13
|
-
* take them out again.
|
|
14
|
-
*
|
|
182
|
+
* A write-only credential store: values go in, and only `open`, `read` and
|
|
183
|
+
* `resolve` take them out again.
|
|
184
|
+
*
|
|
185
|
+
* Every value is sealed under its own data key, and only that key is sealed
|
|
186
|
+
* under the master key. Changing the master key therefore re-seals a handful of
|
|
187
|
+
* bytes per entry rather than every value, and one exposed data key exposes one
|
|
188
|
+
* value rather than all of them.
|
|
189
|
+
*
|
|
190
|
+
* @example Storing a credential and handing it to the thing that needs it
|
|
191
|
+
* ```ts
|
|
192
|
+
* import { Vault, MemoryStore, generateKey } from "@mstone6969/vault"
|
|
193
|
+
*
|
|
194
|
+
* const vault = new Vault({ key: generateKey(), store: new MemoryStore() })
|
|
195
|
+
*
|
|
196
|
+
* await vault.put("alice", "stripe_key", "sk_live_x", {
|
|
197
|
+
* metadata: { kind: "api" },
|
|
198
|
+
* })
|
|
199
|
+
*
|
|
200
|
+
* // Nothing but open, read and resolve gets the value back out.
|
|
201
|
+
* await vault.list("alice") // name, metadata, dates — no value
|
|
202
|
+
* await vault.open("alice", "stripe_key")
|
|
203
|
+
* await vault.resolve("alice", { STRIPE_KEY: "@vault:stripe_key" })
|
|
204
|
+
* ```
|
|
205
|
+
*
|
|
206
|
+
* @see {@link VaultOptions} for what it is built from, {@link VaultStore} for
|
|
207
|
+
* where the records go, and {@link VaultError} for what it throws.
|
|
15
208
|
*/
|
|
16
209
|
export declare class Vault {
|
|
17
|
-
private
|
|
210
|
+
private keySource;
|
|
211
|
+
private previousSources;
|
|
212
|
+
/** Resolved on first use, not at construction: a provider may need to wait,
|
|
213
|
+
* or fail, and a vault nobody uses should do neither. */
|
|
214
|
+
private keyCache;
|
|
215
|
+
private previousCache;
|
|
18
216
|
private readonly store;
|
|
217
|
+
private readonly historyLimit;
|
|
218
|
+
private readonly generators;
|
|
219
|
+
private readonly onAccess;
|
|
220
|
+
/** The prefix {@link Vault.resolve} treats as a reference. */
|
|
19
221
|
readonly prefix: string;
|
|
20
|
-
|
|
21
|
-
|
|
222
|
+
/**
|
|
223
|
+
* @param options The key, the store and the policies this vault applies.
|
|
224
|
+
* Nothing is contacted here: the key is resolved on first use, so a vault
|
|
225
|
+
* built from a provider that is slow or unreachable costs nothing until
|
|
226
|
+
* something asks it for a value.
|
|
227
|
+
*/
|
|
228
|
+
constructor({ key, store, prefix, previousKeys, historyLimit, generators, onAccess, }: VaultOptions);
|
|
229
|
+
private master;
|
|
230
|
+
private retired;
|
|
231
|
+
private record;
|
|
232
|
+
/** Opens something with the master key, falling back to retired ones. */
|
|
233
|
+
private unsealWithMaster;
|
|
234
|
+
/** Opens a value: its data key first, then the value under that key. */
|
|
235
|
+
private unseal;
|
|
236
|
+
/** Seals a value under a fresh data key, and that key under the master. */
|
|
237
|
+
private enseal;
|
|
238
|
+
private checkName;
|
|
239
|
+
/**
|
|
240
|
+
* Everything an owner holds, sorted by name. Never a sealed value.
|
|
241
|
+
*
|
|
242
|
+
* @param owner Whose entries to list.
|
|
243
|
+
* @returns One summary per entry, in name order. A sealed value is absent
|
|
244
|
+
* entirely; an entry stored in the open carries its value in `value`.
|
|
245
|
+
*
|
|
246
|
+
* @remarks
|
|
247
|
+
* Expiry hides nothing here: an entry past its `expiresAt` is still listed,
|
|
248
|
+
* and still refuses to open, until {@link Vault.purgeExpired} clears it.
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
* ```ts
|
|
252
|
+
* await vault.put("alice", "stripe_key", "sk_live_x", {
|
|
253
|
+
* metadata: { kind: "api" },
|
|
254
|
+
* })
|
|
255
|
+
*
|
|
256
|
+
* const [entry] = await vault.list("alice")
|
|
257
|
+
* entry.name // "stripe_key"
|
|
258
|
+
* entry.metadata // { kind: "api" }
|
|
259
|
+
* entry.versions // 0
|
|
260
|
+
* ```
|
|
261
|
+
*
|
|
262
|
+
* @see {@link SecretSummary}
|
|
263
|
+
*/
|
|
22
264
|
list(owner: string): Promise<SecretSummary[]>;
|
|
23
265
|
/**
|
|
24
266
|
* Stores a value, replacing whatever was under that name.
|
|
@@ -26,25 +268,318 @@ export declare class Vault {
|
|
|
26
268
|
* `metadata` is kept in the clear and comes back from `list`, so it must
|
|
27
269
|
* hold nothing secret — a credential's kind, or the username it belongs to,
|
|
28
270
|
* not the password.
|
|
271
|
+
*
|
|
272
|
+
* @param owner Whose entry it is. Owners never see each other's entries.
|
|
273
|
+
* @param name What to call it: 1-64 characters of letters, numbers, dot,
|
|
274
|
+
* dash or underscore. Surrounding whitespace is trimmed.
|
|
275
|
+
* @param value The value to store.
|
|
276
|
+
* @param options Metadata, expiry, rotation policy, and whether the entry
|
|
277
|
+
* is sealed, final, or keeps what it replaces. An option left out is
|
|
278
|
+
* inherited from the existing entry.
|
|
279
|
+
* @returns The stored entry, summarised — never its sealed value.
|
|
280
|
+
* @throws {@link VaultError} 422 when the name is not 1-64 characters of
|
|
281
|
+
* letters, numbers, dot, dash or underscore, or the value is empty.
|
|
282
|
+
* @throws {@link VaultError} 409 when the entry is already there and
|
|
283
|
+
* `final`: it can be deleted, never replaced.
|
|
284
|
+
*
|
|
285
|
+
* @example Replacing a value without restating what the entry is
|
|
286
|
+
* ```ts
|
|
287
|
+
* await vault.put("alice", "db", "first-password", {
|
|
288
|
+
* metadata: { kind: "login", username: "ada" },
|
|
289
|
+
* rotation: { kind: "random", length: 24 },
|
|
290
|
+
* })
|
|
291
|
+
*
|
|
292
|
+
* // Still a login, still rotatable at 24 characters, still sealed.
|
|
293
|
+
* await vault.put("alice", "db", "second-password")
|
|
294
|
+
* ```
|
|
295
|
+
*
|
|
296
|
+
* @see {@link Vault.rotate} to replace a value and keep the old one,
|
|
297
|
+
* {@link PutOptions} for the rest of the options.
|
|
298
|
+
*/
|
|
299
|
+
put(owner: string, name: string, value: string, options?: PutOptions): Promise<SecretSummary>;
|
|
300
|
+
/**
|
|
301
|
+
* Replaces a value, keeping the one it replaces.
|
|
302
|
+
*
|
|
303
|
+
* Called without a value, the entry's rotation policy produces one — which
|
|
304
|
+
* is the point of storing a policy: whatever runs the rotation is told how
|
|
305
|
+
* to make the next password, never what the current one is.
|
|
306
|
+
*
|
|
307
|
+
* Previous values stay openable, so a job that read the credential moments
|
|
308
|
+
* before a rotation can still finish on what it was given.
|
|
309
|
+
*
|
|
310
|
+
* @param owner Whose entry to rotate.
|
|
311
|
+
* @param name The entry to rotate.
|
|
312
|
+
* @param value The new value. Left out, the entry's rotation policy makes
|
|
313
|
+
* one.
|
|
314
|
+
* @param options As {@link Vault.put}, minus `keepHistory`: a rotation
|
|
315
|
+
* always keeps what it replaced, up to {@link VaultOptions.historyLimit}.
|
|
316
|
+
* @returns The rotated entry, summarised, with `rotatedAt` stamped.
|
|
317
|
+
* @throws {@link VaultError} 404 when no value is given and there is no
|
|
318
|
+
* such entry to take a policy from.
|
|
319
|
+
* @throws {@link VaultError} 410 when no value is given and the entry has
|
|
320
|
+
* expired.
|
|
321
|
+
* @throws {@link VaultError} 422 when no value is given and the entry has
|
|
322
|
+
* no rotation policy to make one with.
|
|
323
|
+
* @throws {@link VaultError} 501 when the policy names a generator this
|
|
324
|
+
* vault was not constructed with.
|
|
325
|
+
* @throws {@link VaultError} 409 when the entry is final.
|
|
326
|
+
*
|
|
327
|
+
* @example
|
|
328
|
+
* ```ts
|
|
329
|
+
* await vault.put("alice", "db", "first-password", {
|
|
330
|
+
* rotation: { kind: "random", length: 24 },
|
|
331
|
+
* })
|
|
332
|
+
*
|
|
333
|
+
* const rotated = await vault.rotate("alice", "db")
|
|
334
|
+
* rotated.rotatedAt // stamped just now
|
|
335
|
+
* await vault.versions("alice", "db") // ["first-password"]
|
|
336
|
+
* ```
|
|
337
|
+
*
|
|
338
|
+
* @see {@link Vault.rotationDue} for which entries are asking for this.
|
|
339
|
+
*/
|
|
340
|
+
rotate(owner: string, name: string, value?: string, options?: Omit<PutOptions, "keepHistory">): Promise<SecretSummary>;
|
|
341
|
+
/** The next value an entry's policy calls for. */
|
|
342
|
+
private generate;
|
|
343
|
+
/**
|
|
344
|
+
* Entries whose policy says how often they want rotating, and whose time
|
|
345
|
+
* has come. Nothing rotates them for you — schedule this and act on it.
|
|
346
|
+
*
|
|
347
|
+
* @param now The moment to judge against. Pass a later one to ask what will
|
|
348
|
+
* be due by then.
|
|
349
|
+
* @returns Summaries of every entry, whoever owns it, whose
|
|
350
|
+
* {@link RotationPolicy.every} seconds have passed since it was last
|
|
351
|
+
* rotated — or since it was stored, if it never has been.
|
|
352
|
+
*
|
|
353
|
+
* @remarks
|
|
354
|
+
* One of the three calls that reach across owners, so it belongs to
|
|
355
|
+
* whatever runs the schedule rather than to a request.
|
|
356
|
+
*
|
|
357
|
+
* @example
|
|
358
|
+
* ```ts
|
|
359
|
+
* await vault.put("alice", "db", "x", {
|
|
360
|
+
* rotation: { kind: "random", every: 86_400 },
|
|
361
|
+
* })
|
|
362
|
+
*
|
|
363
|
+
* for (const entry of await vault.rotationDue()) {
|
|
364
|
+
* await vault.rotate(entry.owner, entry.name)
|
|
365
|
+
* }
|
|
366
|
+
* ```
|
|
367
|
+
*/
|
|
368
|
+
rotationDue(now?: Date): Promise<SecretSummary[]>;
|
|
369
|
+
/**
|
|
370
|
+
* Previous values of an entry, newest first, opened.
|
|
371
|
+
*
|
|
372
|
+
* @param owner Whose entry it is.
|
|
373
|
+
* @param name The entry to look back through.
|
|
374
|
+
* @returns The values it used to hold, newest first, in the clear. Empty
|
|
375
|
+
* for an entry that has never been rotated.
|
|
376
|
+
* @throws {@link VaultError} 404 when there is no such entry.
|
|
377
|
+
* @throws {@link VaultError} 410 when the entry has expired.
|
|
378
|
+
* @throws {@link VaultError} 422 when the name is not a legal one.
|
|
379
|
+
* @throws {@link VaultKeyError} 500 when a kept value will not open under
|
|
380
|
+
* the master key or any of {@link VaultOptions.previousKeys}.
|
|
381
|
+
*
|
|
382
|
+
* @example
|
|
383
|
+
* ```ts
|
|
384
|
+
* await vault.put("alice", "deploy", "v1")
|
|
385
|
+
* await vault.rotate("alice", "deploy", "v2")
|
|
386
|
+
* await vault.rotate("alice", "deploy", "v3")
|
|
387
|
+
*
|
|
388
|
+
* await vault.versions("alice", "deploy") // ["v2", "v1"]
|
|
389
|
+
* ```
|
|
390
|
+
*/
|
|
391
|
+
versions(owner: string, name: string): Promise<string[]>;
|
|
392
|
+
/**
|
|
393
|
+
* True when the owner has a secret under that name, expired or not.
|
|
394
|
+
*
|
|
395
|
+
* @param owner Whose entry to look for.
|
|
396
|
+
* @param name The name to look for.
|
|
397
|
+
* @returns Whether a record exists under it.
|
|
398
|
+
* @throws {@link VaultError} 422 when the name is not a legal one.
|
|
399
|
+
*
|
|
400
|
+
* @remarks
|
|
401
|
+
* Opens nothing and is not stopped by expiry, so it answers "is this name
|
|
402
|
+
* taken" rather than "can this value still be used".
|
|
29
403
|
*/
|
|
30
|
-
put(owner: string, name: string, value: string, metadata?: Record<string, string>): Promise<SecretSummary>;
|
|
31
|
-
/** True when the owner has a secret under that name. */
|
|
32
404
|
has(owner: string, name: string): Promise<boolean>;
|
|
33
|
-
/**
|
|
405
|
+
/**
|
|
406
|
+
* Removes a secret, returning false if it wasn't there.
|
|
407
|
+
*
|
|
408
|
+
* @param owner Whose entry to delete.
|
|
409
|
+
* @param name The entry to delete.
|
|
410
|
+
* @returns True when something was deleted, false when there was nothing
|
|
411
|
+
* under that name.
|
|
412
|
+
* @throws {@link VaultError} 422 when the name is not a legal one.
|
|
413
|
+
*
|
|
414
|
+
* @remarks
|
|
415
|
+
* Deleting takes the kept previous values with it, and it is the one thing
|
|
416
|
+
* a `final` entry allows.
|
|
417
|
+
*/
|
|
34
418
|
remove(owner: string, name: string): Promise<boolean>;
|
|
419
|
+
private require;
|
|
35
420
|
/**
|
|
36
|
-
* Reads one value back. The only way plaintext leaves
|
|
37
|
-
* in memory and out of logs and responses.
|
|
421
|
+
* Reads one value back. The only way plaintext leaves a sealed entry — keep
|
|
422
|
+
* it in memory and out of logs and responses.
|
|
423
|
+
*
|
|
424
|
+
* @param owner Whose entry to open.
|
|
425
|
+
* @param name The entry to open.
|
|
426
|
+
* @returns The value, sealed or not.
|
|
427
|
+
* @throws {@link VaultError} 404 when there is no such entry.
|
|
428
|
+
* @throws {@link VaultError} 410 when the entry has expired. The record is
|
|
429
|
+
* still there; it just cannot be used.
|
|
430
|
+
* @throws {@link VaultError} 422 when the name is not a legal one.
|
|
431
|
+
* @throws {@link VaultKeyError} 500 when the value will not open under the
|
|
432
|
+
* master key or any of {@link VaultOptions.previousKeys} — a wrong key or
|
|
433
|
+
* an altered value, which GCM cannot tell apart.
|
|
434
|
+
*
|
|
435
|
+
* @example
|
|
436
|
+
* ```ts
|
|
437
|
+
* await vault.put("alice", "token", "shhh")
|
|
438
|
+
* await vault.open("alice", "token") // "shhh"
|
|
439
|
+
* ```
|
|
440
|
+
*
|
|
441
|
+
* @see {@link Vault.read} for entries stored in the open,
|
|
442
|
+
* {@link Vault.resolve} for substituting several at once.
|
|
38
443
|
*/
|
|
39
444
|
open(owner: string, name: string): Promise<string>;
|
|
445
|
+
/**
|
|
446
|
+
* Reads an entry stored in the open. A sealed one refuses.
|
|
447
|
+
*
|
|
448
|
+
* @param owner Whose entry to read.
|
|
449
|
+
* @param name The entry to read.
|
|
450
|
+
* @returns The value, which was stored with `open: true` and was therefore
|
|
451
|
+
* never secret.
|
|
452
|
+
* @throws {@link VaultError} 403 when the entry is sealed.
|
|
453
|
+
* {@link Vault.open} is the only way a sealed value comes out.
|
|
454
|
+
* @throws {@link VaultError} 404 when there is no such entry.
|
|
455
|
+
* @throws {@link VaultError} 410 when the entry has expired.
|
|
456
|
+
* @throws {@link VaultError} 422 when the name is not a legal one.
|
|
457
|
+
*
|
|
458
|
+
* @example
|
|
459
|
+
* ```ts
|
|
460
|
+
* await vault.put("alice", "region", "eu-west-1", { open: true })
|
|
461
|
+
* await vault.read("alice", "region") // "eu-west-1"
|
|
462
|
+
*
|
|
463
|
+
* await vault.put("alice", "token", "shhh")
|
|
464
|
+
* await vault.read("alice", "token") // throws: 403, sealed
|
|
465
|
+
* ```
|
|
466
|
+
*/
|
|
467
|
+
read(owner: string, name: string): Promise<string>;
|
|
40
468
|
/**
|
|
41
469
|
* Substitutes `@vault:<name>` references in a set of values — an
|
|
42
470
|
* environment, a config object — leaving everything else alone.
|
|
43
471
|
*
|
|
44
|
-
* A reference to a secret that isn't there
|
|
45
|
-
* credential is worse than not running.
|
|
472
|
+
* A reference to a secret that isn't there, or that has expired, throws:
|
|
473
|
+
* running with a blank credential is worse than not running.
|
|
474
|
+
*
|
|
475
|
+
* @param owner Whose entries the references name.
|
|
476
|
+
* @param values The set to substitute into. Not modified.
|
|
477
|
+
* @returns A copy with every reference replaced by its value, or the same
|
|
478
|
+
* object back when nothing in it is a reference.
|
|
479
|
+
* @throws {@link VaultError} 404 when a reference names no entry.
|
|
480
|
+
* @throws {@link VaultError} 410 when a referenced entry has expired.
|
|
481
|
+
* @throws {@link VaultError} 422 when what follows the prefix is not a
|
|
482
|
+
* legal name.
|
|
483
|
+
*
|
|
484
|
+
* @remarks
|
|
485
|
+
* Whitespace around the name is ignored, so `"@vault: token "` finds
|
|
486
|
+
* `token`. Sealed and open entries both resolve; the prefix comes from
|
|
487
|
+
* {@link Vault.prefix}.
|
|
488
|
+
*
|
|
489
|
+
* @example Filling in an environment before spawning something
|
|
490
|
+
* ```ts
|
|
491
|
+
* await vault.put("alice", "token", "secret")
|
|
492
|
+
*
|
|
493
|
+
* await vault.resolve("alice", {
|
|
494
|
+
* PLAIN: "kept",
|
|
495
|
+
* API_TOKEN: "@vault:token",
|
|
496
|
+
* })
|
|
497
|
+
* // { PLAIN: "kept", API_TOKEN: "secret" }
|
|
498
|
+
* ```
|
|
46
499
|
*/
|
|
47
500
|
resolve(owner: string, values: Record<string, string>): Promise<Record<string, string>>;
|
|
48
|
-
|
|
501
|
+
/**
|
|
502
|
+
* Re-seals values under fresh data keys, without changing the master key.
|
|
503
|
+
*
|
|
504
|
+
* Cheap hygiene: the ciphertext of an unchanged secret stops being
|
|
505
|
+
* comparable between two copies of the database taken at different times.
|
|
506
|
+
*
|
|
507
|
+
* @param owner Limit it to one owner's entries. Left out, it walks the
|
|
508
|
+
* whole store, whoever owns it.
|
|
509
|
+
* @returns How many entries were re-sealed. Entries stored in the open hold
|
|
510
|
+
* nothing to re-seal and are skipped.
|
|
511
|
+
* @throws {@link VaultKeyError} 500 when a value will not open. Unlike
|
|
512
|
+
* {@link Vault.rekey} this stops there, having already re-sealed the
|
|
513
|
+
* entries it got to — those are unharmed, since the key did not change.
|
|
514
|
+
*
|
|
515
|
+
* @example
|
|
516
|
+
* ```ts
|
|
517
|
+
* await vault.reseal("alice") // just this owner
|
|
518
|
+
* await vault.reseal() // the whole store
|
|
519
|
+
* ```
|
|
520
|
+
*/
|
|
521
|
+
reseal(owner?: string): Promise<number>;
|
|
522
|
+
/**
|
|
523
|
+
* Re-seals every data key under a new master key.
|
|
524
|
+
*
|
|
525
|
+
* The old key is kept as a fallback for the rest of this vault's life, so a
|
|
526
|
+
* run that stops halfway leaves a mix that still opens. Construct the next
|
|
527
|
+
* vault with `key: next, previousKeys: [old]` until you are confident, then
|
|
528
|
+
* drop the old one.
|
|
529
|
+
*
|
|
530
|
+
* An entry that will not open is left untouched and named in the report,
|
|
531
|
+
* because re-sealing what you cannot read would only destroy it.
|
|
532
|
+
*
|
|
533
|
+
* @param next The new master key: base64, already imported, or a provider
|
|
534
|
+
* that finds one.
|
|
535
|
+
* @returns How many entries moved, and which would not, by `owner/name`.
|
|
536
|
+
* @throws {@link VaultKeyError} 500 when `next` is not a usable key. It is
|
|
537
|
+
* resolved before anything is written, so nothing has changed.
|
|
538
|
+
*
|
|
539
|
+
* @remarks
|
|
540
|
+
* Walks every owner, and changes this vault as it goes: from here on it
|
|
541
|
+
* seals under `next` and keeps the key it had as a fallback. An entry
|
|
542
|
+
* stored in the open holds no key and is skipped, and one written before
|
|
543
|
+
* envelope encryption is given a data key on the way past.
|
|
544
|
+
*
|
|
545
|
+
* @example
|
|
546
|
+
* ```ts
|
|
547
|
+
* const next = generateKey()
|
|
548
|
+
* const report = await vault.rekey(next)
|
|
549
|
+
* report.rekeyed // 2
|
|
550
|
+
* report.failed // ["alice/stranger"] — left exactly as they were
|
|
551
|
+
*
|
|
552
|
+
* // Until the failures are dealt with, keep the old key readable.
|
|
553
|
+
* const moved = new Vault({ key: next, store, previousKeys: [old] })
|
|
554
|
+
* ```
|
|
555
|
+
*
|
|
556
|
+
* @see {@link RekeyReport}, {@link VaultOptions.previousKeys}
|
|
557
|
+
*/
|
|
558
|
+
rekey(next: string | CryptoKey | KeyProvider): Promise<RekeyReport>;
|
|
559
|
+
/** Moves an entry's kept values onto the new master key alongside it. */
|
|
560
|
+
private rekeyHistory;
|
|
561
|
+
/**
|
|
562
|
+
* Deletes entries whose time is up. Returns how many went.
|
|
563
|
+
*
|
|
564
|
+
* @param now The moment to judge against. Pass a later one to see what a
|
|
565
|
+
* run then would take.
|
|
566
|
+
* @returns How many entries were deleted.
|
|
567
|
+
*
|
|
568
|
+
* @remarks
|
|
569
|
+
* Walks every owner. Expiry stops an entry being used, not being stored:
|
|
570
|
+
* until this runs, an expired entry is still there and still listed.
|
|
571
|
+
*
|
|
572
|
+
* @example
|
|
573
|
+
* ```ts
|
|
574
|
+
* await vault.put("alice", "temporary", "x", {
|
|
575
|
+
* expiresAt: new Date(Date.now() - 1),
|
|
576
|
+
* })
|
|
577
|
+
*
|
|
578
|
+
* await vault.open("alice", "temporary") // throws: 410, expired
|
|
579
|
+
* await vault.purgeExpired() // 1
|
|
580
|
+
* await vault.has("alice", "temporary") // false
|
|
581
|
+
* ```
|
|
582
|
+
*/
|
|
583
|
+
purgeExpired(now?: Date): Promise<number>;
|
|
49
584
|
}
|
|
50
585
|
//# sourceMappingURL=vault.d.ts.map
|
package/dist/vault.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vault.d.ts","sourceRoot":"","sources":["../src/vault.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"vault.d.ts","sourceRoot":"","sources":["../src/vault.ts"],"names":[],"mappings":"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"}
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
[**@mstone6969/vault**](../README.md)
|
|
2
|
+
|
|
3
|
+
***
|
|
4
|
+
|
|
5
|
+
[@mstone6969/vault](../README.md) / index
|
|
6
|
+
|
|
7
|
+
# index
|
|
8
|
+
|
|
9
|
+
## Classes
|
|
10
|
+
|
|
11
|
+
- [VaultError](classes/VaultError.md)
|
|
12
|
+
- [VaultKeyError](classes/VaultKeyError.md)
|
|
13
|
+
- [FileStore](classes/FileStore.md)
|
|
14
|
+
- [MemoryStore](classes/MemoryStore.md)
|
|
15
|
+
- [Vault](classes/Vault.md)
|
|
16
|
+
|
|
17
|
+
## Type Aliases
|
|
18
|
+
|
|
19
|
+
- [KeyProvider](type-aliases/KeyProvider.md)
|
|
20
|
+
- [HistoryEntry](type-aliases/HistoryEntry.md)
|
|
21
|
+
- [RotationPolicy](type-aliases/RotationPolicy.md)
|
|
22
|
+
- [SecretRecord](type-aliases/SecretRecord.md)
|
|
23
|
+
- [SecretSummary](type-aliases/SecretSummary.md)
|
|
24
|
+
- [PutOptions](type-aliases/PutOptions.md)
|
|
25
|
+
- [VaultStore](type-aliases/VaultStore.md)
|
|
26
|
+
- [VaultEvent](type-aliases/VaultEvent.md)
|
|
27
|
+
- [RotationContext](type-aliases/RotationContext.md)
|
|
28
|
+
- [Generator](type-aliases/Generator.md)
|
|
29
|
+
- [VaultOptions](type-aliases/VaultOptions.md)
|
|
30
|
+
- [RekeyReport](type-aliases/RekeyReport.md)
|
|
31
|
+
|
|
32
|
+
## Variables
|
|
33
|
+
|
|
34
|
+
- [DEFAULT\_PREFIX](variables/DEFAULT_PREFIX.md)
|
|
35
|
+
- [DEFAULT\_HISTORY\_LIMIT](variables/DEFAULT_HISTORY_LIMIT.md)
|
|
36
|
+
- [DEFAULT\_ALPHABET](variables/DEFAULT_ALPHABET.md)
|
|
37
|
+
|
|
38
|
+
## Functions
|
|
39
|
+
|
|
40
|
+
- [generateKey](functions/generateKey.md)
|
|
41
|
+
- [importKey](functions/importKey.md)
|
|
42
|
+
- [seal](functions/seal.md)
|
|
43
|
+
- [open](functions/open.md)
|
|
44
|
+
- [staticKey](functions/staticKey.md)
|
|
45
|
+
- [envKey](functions/envKey.md)
|
|
46
|
+
- [fileKey](functions/fileKey.md)
|
|
47
|
+
- [isKeyProvider](functions/isKeyProvider.md)
|
|
48
|
+
- [randomValue](functions/randomValue.md)
|