@norskvideo/ctl-product-template-schema 0.1.59 → 0.1.61
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 +5 -1
- package/secret-references.d.ts +27 -0
- package/secret-references.js +56 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@norskvideo/ctl-product-template-schema",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.61",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -36,6 +36,10 @@
|
|
|
36
36
|
"types": "./migration-socket.d.ts",
|
|
37
37
|
"default": "./migration-socket.js"
|
|
38
38
|
},
|
|
39
|
+
"./secret-references": {
|
|
40
|
+
"types": "./secret-references.d.ts",
|
|
41
|
+
"default": "./secret-references.js"
|
|
42
|
+
},
|
|
39
43
|
"./product-channels": {
|
|
40
44
|
"types": "./product-channels.d.ts",
|
|
41
45
|
"default": "./product-channels.js"
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type Result } from "@norskvideo/ctl-foundation";
|
|
2
|
+
export declare const SECRET_REFERENCE_PREFIX = "secretref:";
|
|
3
|
+
/** The NodeInventory capability a worker advertises when it resolves secret
|
|
4
|
+
* references, so placement can keep a job whose parameters hold one off an
|
|
5
|
+
* older worker — which would hand the container the reference itself. */
|
|
6
|
+
export declare const SECRET_REFERENCES_CAPABILITY = "norsk.io/secret-references";
|
|
7
|
+
/** What a secret parameter's literal value is shown as wherever ctl prints
|
|
8
|
+
* launch parameters back. */
|
|
9
|
+
export declare const SECRET_PLACEHOLDER = "<secret>";
|
|
10
|
+
export interface SecretReference {
|
|
11
|
+
provider: string;
|
|
12
|
+
key: string;
|
|
13
|
+
}
|
|
14
|
+
/** A value is a reference exactly when it carries the prefix. A malformed
|
|
15
|
+
* reference is still a reference: it fails resolution rather than reaching a
|
|
16
|
+
* container as a literal. */
|
|
17
|
+
export declare function isSecretReference(value: string): boolean;
|
|
18
|
+
export declare function parseSecretReference(value: string): Result<SecretReference, string>;
|
|
19
|
+
export declare function secretReference(provider: string, key: string): string;
|
|
20
|
+
/** Launch parameters as they may be shown: a parameter the template declares
|
|
21
|
+
* `secret` has its literal value masked. A reference is shown as it is — it
|
|
22
|
+
* is the point of a reference that it reveals nothing — and an empty value
|
|
23
|
+
* stays visibly empty. */
|
|
24
|
+
export declare function redactSecretParams(params: Record<string, string>, declared: readonly {
|
|
25
|
+
name: string;
|
|
26
|
+
secret?: boolean;
|
|
27
|
+
}[]): Record<string, string>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Secret references: a launch parameter's value may name a secret instead of
|
|
2
|
+
// carrying it, as `secretref:<provider>:<key>`. The worker that runs the
|
|
3
|
+
// instance resolves the reference immediately before it writes the
|
|
4
|
+
// container's environment, so a scheduler, its job store, its templates and
|
|
5
|
+
// its backups only ever hold the reference (norsk-ctl ADR-0017).
|
|
6
|
+
//
|
|
7
|
+
// Shared by both ends: whoever builds launch parameters (a Manager front end,
|
|
8
|
+
// a script) and the worker that resolves them. The provider names a resolver
|
|
9
|
+
// configured on the worker; the key is that provider's business and may hold
|
|
10
|
+
// colons, slashes or ciphertext.
|
|
11
|
+
import { err, ok } from "@norskvideo/ctl-foundation";
|
|
12
|
+
export const SECRET_REFERENCE_PREFIX = "secretref:";
|
|
13
|
+
/** The NodeInventory capability a worker advertises when it resolves secret
|
|
14
|
+
* references, so placement can keep a job whose parameters hold one off an
|
|
15
|
+
* older worker — which would hand the container the reference itself. */
|
|
16
|
+
export const SECRET_REFERENCES_CAPABILITY = "norsk.io/secret-references";
|
|
17
|
+
/** What a secret parameter's literal value is shown as wherever ctl prints
|
|
18
|
+
* launch parameters back. */
|
|
19
|
+
export const SECRET_PLACEHOLDER = "<secret>";
|
|
20
|
+
const PROVIDER_NAME = /^[a-z][a-z0-9-]*$/;
|
|
21
|
+
/** A value is a reference exactly when it carries the prefix. A malformed
|
|
22
|
+
* reference is still a reference: it fails resolution rather than reaching a
|
|
23
|
+
* container as a literal. */
|
|
24
|
+
export function isSecretReference(value) {
|
|
25
|
+
return value.startsWith(SECRET_REFERENCE_PREFIX);
|
|
26
|
+
}
|
|
27
|
+
export function parseSecretReference(value) {
|
|
28
|
+
if (!isSecretReference(value))
|
|
29
|
+
return err("not a secret reference");
|
|
30
|
+
const rest = value.slice(SECRET_REFERENCE_PREFIX.length);
|
|
31
|
+
const colon = rest.indexOf(":");
|
|
32
|
+
if (colon < 0)
|
|
33
|
+
return err(`a secret reference is ${SECRET_REFERENCE_PREFIX}<provider>:<key>`);
|
|
34
|
+
const provider = rest.slice(0, colon);
|
|
35
|
+
const key = rest.slice(colon + 1);
|
|
36
|
+
if (!PROVIDER_NAME.test(provider)) {
|
|
37
|
+
return err(`secret provider name '${provider}' must be lowercase letters, digits and dashes`);
|
|
38
|
+
}
|
|
39
|
+
if (key === "")
|
|
40
|
+
return err(`the secret reference for provider '${provider}' names no key`);
|
|
41
|
+
return ok({ provider, key });
|
|
42
|
+
}
|
|
43
|
+
export function secretReference(provider, key) {
|
|
44
|
+
return `${SECRET_REFERENCE_PREFIX}${provider}:${key}`;
|
|
45
|
+
}
|
|
46
|
+
/** Launch parameters as they may be shown: a parameter the template declares
|
|
47
|
+
* `secret` has its literal value masked. A reference is shown as it is — it
|
|
48
|
+
* is the point of a reference that it reveals nothing — and an empty value
|
|
49
|
+
* stays visibly empty. */
|
|
50
|
+
export function redactSecretParams(params, declared) {
|
|
51
|
+
const secret = new Set(declared.filter((p) => p.secret === true).map((p) => p.name));
|
|
52
|
+
return Object.fromEntries(Object.entries(params).map(([k, v]) => [
|
|
53
|
+
k,
|
|
54
|
+
secret.has(k) && v !== "" && !isSecretReference(v) ? SECRET_PLACEHOLDER : v,
|
|
55
|
+
]));
|
|
56
|
+
}
|