@better-forge/vault 0.1.0 → 0.1.1
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 +21 -21
- package/README.md +5 -5
- package/dist/migrations.js +21 -21
- package/package.json +56 -56
- package/src/createVault.ts +45 -45
- package/src/hashicorp.ts +466 -466
- package/src/index.ts +9 -9
- package/src/migrations.ts +29 -29
- package/src/module.ts +6 -6
- package/src/resolveSecret.ts +96 -96
- package/src/sealed.ts +38 -38
- package/src/secretBox.ts +72 -72
- package/src/secretFields.ts +177 -177
- package/src/tables.ts +23 -23
- package/src/vaultRoutes.ts +422 -422
- package/src/vaultUse.ts +41 -41
package/src/vaultUse.ts
CHANGED
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
import { tokenAllows, VAULT_USE_SCOPE } from '@better-forge/contracts'
|
|
2
|
-
|
|
3
|
-
type Json = Record<string, unknown>
|
|
4
|
-
const isObject = (value: unknown): value is Json => !!value && typeof value === 'object' && !Array.isArray(value)
|
|
5
|
-
|
|
6
|
-
/** Whether anything under a `vault` key is set, whatever its shape: a reference that is malformed is still treated as one. */
|
|
7
|
-
function holdsVault(value: unknown): boolean {
|
|
8
|
-
if (Array.isArray(value)) return value.some(holdsVault)
|
|
9
|
-
if (!isObject(value)) return false
|
|
10
|
-
return Object.entries(value).some(([key, inner]) => (key === 'vault' && inner !== undefined && inner !== null && inner !== false) || holdsVault(inner))
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/** The same text for the same value, whatever the order of keys. */
|
|
14
|
-
export function canonical(value: unknown): string {
|
|
15
|
-
if (Array.isArray(value)) return `[${value.map(canonical).join(',')}]`
|
|
16
|
-
if (isObject(value)) return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`).join(',')}}`
|
|
17
|
-
return JSON.stringify(value) ?? 'null'
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* The check that keeps a token without the permission to use vault secrets away from them. `target` names what a
|
|
22
|
-
* vault reference sits in, in the application's words (for example "job or channel"), for the refusal message.
|
|
23
|
-
*/
|
|
24
|
-
export function createVaultUseGuard(options: { target: string }) {
|
|
25
|
-
const refused =
|
|
26
|
-
`This token does not have the "${VAULT_USE_SCOPE}" permission, which it needs to add a vault reference or to change the configuration of a ${options.target} that has one`
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* A vault secret is sent wherever the configuration that references it points, and what the target answers (a query
|
|
30
|
-
* result, an error message) comes back to the caller. A token that may edit such a configuration but may not use vault
|
|
31
|
-
* secrets therefore can neither add a reference nor change anything in a configuration that has one: it can edit the
|
|
32
|
-
* rest or remove the reference. `stored` is the configuration as it is saved now, or undefined for a new one.
|
|
33
|
-
* Returns a message, or null if fine.
|
|
34
|
-
*/
|
|
35
|
-
function vaultUseProblem(token: { scopes: readonly string[] } | undefined, incoming: unknown, stored: unknown): string | null {
|
|
36
|
-
if (!token || tokenAllows(token.scopes, VAULT_USE_SCOPE) || !holdsVault(incoming)) return null
|
|
37
|
-
return stored !== undefined && canonical(incoming) === canonical(stored) ? null : refused
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return { refused, vaultUseProblem }
|
|
41
|
-
}
|
|
1
|
+
import { tokenAllows, VAULT_USE_SCOPE } from '@better-forge/contracts'
|
|
2
|
+
|
|
3
|
+
type Json = Record<string, unknown>
|
|
4
|
+
const isObject = (value: unknown): value is Json => !!value && typeof value === 'object' && !Array.isArray(value)
|
|
5
|
+
|
|
6
|
+
/** Whether anything under a `vault` key is set, whatever its shape: a reference that is malformed is still treated as one. */
|
|
7
|
+
function holdsVault(value: unknown): boolean {
|
|
8
|
+
if (Array.isArray(value)) return value.some(holdsVault)
|
|
9
|
+
if (!isObject(value)) return false
|
|
10
|
+
return Object.entries(value).some(([key, inner]) => (key === 'vault' && inner !== undefined && inner !== null && inner !== false) || holdsVault(inner))
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** The same text for the same value, whatever the order of keys. */
|
|
14
|
+
export function canonical(value: unknown): string {
|
|
15
|
+
if (Array.isArray(value)) return `[${value.map(canonical).join(',')}]`
|
|
16
|
+
if (isObject(value)) return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`).join(',')}}`
|
|
17
|
+
return JSON.stringify(value) ?? 'null'
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The check that keeps a token without the permission to use vault secrets away from them. `target` names what a
|
|
22
|
+
* vault reference sits in, in the application's words (for example "job or channel"), for the refusal message.
|
|
23
|
+
*/
|
|
24
|
+
export function createVaultUseGuard(options: { target: string }) {
|
|
25
|
+
const refused =
|
|
26
|
+
`This token does not have the "${VAULT_USE_SCOPE}" permission, which it needs to add a vault reference or to change the configuration of a ${options.target} that has one`
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* A vault secret is sent wherever the configuration that references it points, and what the target answers (a query
|
|
30
|
+
* result, an error message) comes back to the caller. A token that may edit such a configuration but may not use vault
|
|
31
|
+
* secrets therefore can neither add a reference nor change anything in a configuration that has one: it can edit the
|
|
32
|
+
* rest or remove the reference. `stored` is the configuration as it is saved now, or undefined for a new one.
|
|
33
|
+
* Returns a message, or null if fine.
|
|
34
|
+
*/
|
|
35
|
+
function vaultUseProblem(token: { scopes: readonly string[] } | undefined, incoming: unknown, stored: unknown): string | null {
|
|
36
|
+
if (!token || tokenAllows(token.scopes, VAULT_USE_SCOPE) || !holdsVault(incoming)) return null
|
|
37
|
+
return stored !== undefined && canonical(incoming) === canonical(stored) ? null : refused
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return { refused, vaultUseProblem }
|
|
41
|
+
}
|