@sponson/adapters 0.0.0-stage → 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/LICENSE +202 -0
- package/README.md +4 -2
- package/dist/algolia.d.ts +6 -0
- package/dist/algolia.js +151 -0
- package/dist/algolia.js.map +1 -0
- package/dist/clerk.d.ts +8 -0
- package/dist/clerk.js +107 -0
- package/dist/clerk.js.map +1 -0
- package/dist/cloudflare.d.ts +25 -0
- package/dist/cloudflare.js +310 -0
- package/dist/cloudflare.js.map +1 -0
- package/dist/common.d.ts +73 -0
- package/dist/common.js +140 -0
- package/dist/common.js.map +1 -0
- package/dist/digest.d.ts +46 -0
- package/dist/digest.js +129 -0
- package/dist/digest.js.map +1 -0
- package/dist/digitalocean.d.ts +5 -0
- package/dist/digitalocean.js +243 -0
- package/dist/digitalocean.js.map +1 -0
- package/dist/http-adapter-action.d.ts +63 -0
- package/dist/http-adapter-action.js +369 -0
- package/dist/http-adapter-action.js.map +1 -0
- package/dist/http-adapter-auth.d.ts +88 -0
- package/dist/http-adapter-auth.js +437 -0
- package/dist/http-adapter-auth.js.map +1 -0
- package/dist/http-adapter-client.d.ts +51 -0
- package/dist/http-adapter-client.js +156 -0
- package/dist/http-adapter-client.js.map +1 -0
- package/dist/http-adapter-graphql.d.ts +39 -0
- package/dist/http-adapter-graphql.js +157 -0
- package/dist/http-adapter-graphql.js.map +1 -0
- package/dist/http-adapter-list.d.ts +33 -0
- package/dist/http-adapter-list.js +421 -0
- package/dist/http-adapter-list.js.map +1 -0
- package/dist/http-adapter-resource.d.ts +29 -0
- package/dist/http-adapter-resource.js +462 -0
- package/dist/http-adapter-resource.js.map +1 -0
- package/dist/http-adapter-spec.d.ts +216 -0
- package/dist/http-adapter-spec.js +660 -0
- package/dist/http-adapter-spec.js.map +1 -0
- package/dist/http-adapter.d.ts +16 -0
- package/dist/http-adapter.js +28 -0
- package/dist/http-adapter.js.map +1 -0
- package/dist/http.d.ts +179 -0
- package/dist/http.js +352 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/launchdarkly.d.ts +15 -0
- package/dist/launchdarkly.js +337 -0
- package/dist/launchdarkly.js.map +1 -0
- package/dist/manual.d.ts +13 -0
- package/dist/manual.js +201 -0
- package/dist/manual.js.map +1 -0
- package/dist/neon.d.ts +8 -0
- package/dist/neon.js +167 -0
- package/dist/neon.js.map +1 -0
- package/dist/netlify.d.ts +18 -0
- package/dist/netlify.js +436 -0
- package/dist/netlify.js.map +1 -0
- package/dist/planetscale.d.ts +10 -0
- package/dist/planetscale.js +311 -0
- package/dist/planetscale.js.map +1 -0
- package/dist/providers.d.ts +26 -0
- package/dist/providers.js +36 -0
- package/dist/providers.js.map +1 -0
- package/dist/recipes.d.ts +167 -0
- package/dist/recipes.js +246 -0
- package/dist/recipes.js.map +1 -0
- package/dist/secrets.d.ts +72 -0
- package/dist/secrets.js +476 -0
- package/dist/secrets.js.map +1 -0
- package/dist/sigv4.d.ts +56 -0
- package/dist/sigv4.js +118 -0
- package/dist/sigv4.js.map +1 -0
- package/dist/supabase.d.ts +9 -0
- package/dist/supabase.js +385 -0
- package/dist/supabase.js.map +1 -0
- package/dist/vercel.d.ts +8 -0
- package/dist/vercel.js +475 -0
- package/dist/vercel.js.map +1 -0
- package/dist/xata.d.ts +8 -0
- package/dist/xata.js +142 -0
- package/dist/xata.js.map +1 -0
- package/dist/xml.d.ts +25 -0
- package/dist/xml.js +211 -0
- package/dist/xml.js.map +1 -0
- package/package.json +58 -3
- package/recipes/amplify.yaml +147 -0
- package/recipes/auth0.yaml +178 -0
- package/recipes/azure_swa.yaml +116 -0
- package/recipes/cloud_run.yaml +97 -0
- package/recipes/cloudflare.yaml +108 -0
- package/recipes/cockroachdb.yaml +132 -0
- package/recipes/configcat.yaml +123 -0
- package/recipes/datadog.yaml +136 -0
- package/recipes/firebase.yaml +84 -0
- package/recipes/flagsmith.yaml +98 -0
- package/recipes/fly.yaml +97 -0
- package/recipes/fly_machines.yaml +67 -0
- package/recipes/gcs.yaml +102 -0
- package/recipes/github.yaml +123 -0
- package/recipes/growthbook.yaml +124 -0
- package/recipes/heroku.yaml +98 -0
- package/recipes/honeycomb.yaml +89 -0
- package/recipes/inngest.yaml +97 -0
- package/recipes/kinde.yaml +120 -0
- package/recipes/mongodb_atlas.yaml +119 -0
- package/recipes/okta.yaml +177 -0
- package/recipes/posthog.yaml +127 -0
- package/recipes/postmark.yaml +105 -0
- package/recipes/postmark_server.yaml +93 -0
- package/recipes/prisma.yaml +150 -0
- package/recipes/qstash.yaml +134 -0
- package/recipes/railway.yaml +130 -0
- package/recipes/render.yaml +103 -0
- package/recipes/resend.yaml +130 -0
- package/recipes/s3.yaml +108 -0
- package/recipes/sendgrid.yaml +165 -0
- package/recipes/sentry.yaml +158 -0
- package/recipes/split.yaml +121 -0
- package/recipes/statsig.yaml +124 -0
- package/recipes/stripe.yaml +310 -0
- package/recipes/stytch.yaml +113 -0
- package/recipes/svix.yaml +109 -0
- package/recipes/turso.yaml +98 -0
- package/recipes/unleash.yaml +149 -0
- package/recipes/upstash.yaml +130 -0
- package/recipes/vercel.yaml +116 -0
- package/recipes/workos.yaml +70 -0
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How the generic `http` adapter authenticates to an API: the `auth` forms of a `providers.http.<api>` block,
|
|
3
|
+
* parsed (pure), and the credential each one sends at run time (ADR 0017 and its amendment).
|
|
4
|
+
*
|
|
5
|
+
* { bearer_env }, { header, value_env, prefix? }, { basic } a static header from environment variables
|
|
6
|
+
* { headers: [{ header, value_env, prefix? }, …] } several such headers at once (Datadog's API and application keys)
|
|
7
|
+
* { oauth2_client_credentials: { … } } a bearer token from an OAuth2 token endpoint (RFC 6749 §4.4)
|
|
8
|
+
* { command: [argv…] } a bearer token printed by a CLI (`gcloud auth print-access-token`)
|
|
9
|
+
* { aws_sigv4: { … } } every request signed with AWS Signature Version 4
|
|
10
|
+
* { digest: { user_env, password_env } } HTTP Digest (RFC 7616), answering the server's challenge
|
|
11
|
+
*
|
|
12
|
+
* Every form names environment variables, never values, so the block (the ledger identity of the API's resources)
|
|
13
|
+
* holds no secret. A credential obtained at run time (an access token, a printed token) is registered with the
|
|
14
|
+
* engine's redactor (`actx.secret`) the moment it exists and masked in this adapter's own error text too, so it never
|
|
15
|
+
* reaches output, receipts or errors. Tokens are fetched once per run per API block (cached in memory until shortly
|
|
16
|
+
* before they expire) and fetched again, once, when the API answers 401.
|
|
17
|
+
*/
|
|
18
|
+
import { createHash } from "node:crypto";
|
|
19
|
+
import { SponsonError, canonicalJson } from "@sponson/core";
|
|
20
|
+
import { optionalEnv, requireEnv } from "./common.js";
|
|
21
|
+
import { digestAuthorization, pickChallenge } from "./digest.js";
|
|
22
|
+
import { apiClient, isObject, ShapeError } from "./http.js";
|
|
23
|
+
import { defaultExec } from "./secrets.js";
|
|
24
|
+
import { signRequest } from "./sigv4.js";
|
|
25
|
+
const ADAPTER = "http";
|
|
26
|
+
// ---------------------------------------------------------------------------
|
|
27
|
+
// Parsing (pure)
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
/**
|
|
30
|
+
* Variable names the engine masks everywhere (packages/core/src/engine/run-context.ts, CREDENTIAL_NAME). A
|
|
31
|
+
* credential under another name would be masked only in this adapter's own error text, so it is refused.
|
|
32
|
+
*/
|
|
33
|
+
const CREDENTIAL_NAME = /(TOKEN|SECRET|PASSWORD|PASSWD|_KEY|APIKEY)$/i;
|
|
34
|
+
const ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
35
|
+
/** An HTTP header name (RFC 9110 token). */
|
|
36
|
+
export const HEADER_NAME = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/;
|
|
37
|
+
/** PLAN_INVALID naming where in the provider block the fault is. */
|
|
38
|
+
export function planError(message, where) {
|
|
39
|
+
return new SponsonError("PLAN_INVALID", `${ADAPTER}: ${where}: ${message}`, { adapter: ADAPTER, key: where });
|
|
40
|
+
}
|
|
41
|
+
/** The NAME of an environment variable; a credential's name must be one the engine masks. */
|
|
42
|
+
export function envName(v, where, credential) {
|
|
43
|
+
if (typeof v !== "string" || !ENV_NAME.test(v))
|
|
44
|
+
throw planError("must be the NAME of an environment variable, never a value", where);
|
|
45
|
+
if (credential && !CREDENTIAL_NAME.test(v))
|
|
46
|
+
throw planError(`\`${v}\` must end in TOKEN, SECRET, PASSWORD, PASSWD, _KEY or APIKEY, so that Sponson masks its value in every output`, where);
|
|
47
|
+
return v;
|
|
48
|
+
}
|
|
49
|
+
const AUTH_FORMS = "`{ bearer_env: NAME }`, `{ header: X-Api-Key, value_env: NAME, prefix?: \"Api-Key \" }`, `{ headers: [{ header, value_env }, …] }`, `{ basic: { user_env, password_env } }`, `{ oauth2_client_credentials: { token_url, client_id_env, client_secret_env } }` (`token_url` and `audience` may be paths on the base URL's origin), `{ command: [argv…] }`, `{ aws_sigv4: { region, service, access_key_id_env, secret_access_key_env } }` or `{ digest: { user_env, password_env } }`";
|
|
50
|
+
function subBlock(v, where, known) {
|
|
51
|
+
if (!isObject(v))
|
|
52
|
+
throw planError(`must be a map (${known.join(", ")})`, where);
|
|
53
|
+
const extra = Object.keys(v).find((k) => !known.includes(k));
|
|
54
|
+
if (extra)
|
|
55
|
+
throw planError(`unknown key \`${extra}\` (known: ${known.join(", ")})`, where);
|
|
56
|
+
return v;
|
|
57
|
+
}
|
|
58
|
+
function optionalString(v, where) {
|
|
59
|
+
if (v === undefined)
|
|
60
|
+
return undefined;
|
|
61
|
+
if (typeof v !== "string" || v === "")
|
|
62
|
+
throw planError("must be a non-empty string", where);
|
|
63
|
+
return v;
|
|
64
|
+
}
|
|
65
|
+
function httpUrl(v, where) {
|
|
66
|
+
if (typeof v !== "string" || !/^https?:\/\/[^\s]+$/.test(v))
|
|
67
|
+
throw planError("must be an http(s) URL", where);
|
|
68
|
+
return v;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* A value written as an absolute path (`/oauth/token`, `/api/v2/`) resolved against the origin of the block's own
|
|
72
|
+
* `base_url` (never its `base_url_env` override, so every runner and the ledger see one value); anything else as it
|
|
73
|
+
* is. A per-account API (an Auth0 tenant, a Kinde business) then names its account once, in `base_url`, and a
|
|
74
|
+
* recipe can say where the token endpoint and the audience are without knowing the account.
|
|
75
|
+
*/
|
|
76
|
+
function onBase(v, base, where) {
|
|
77
|
+
if (typeof v !== "string" || !v.startsWith("/"))
|
|
78
|
+
return v;
|
|
79
|
+
if (v.startsWith("//"))
|
|
80
|
+
throw planError('must be an http(s) URL, or a path starting with a single "/" (resolved against the origin of `base_url`)', where);
|
|
81
|
+
if (base === undefined)
|
|
82
|
+
throw planError("is a path, which needs the block's `base_url` to resolve against", where);
|
|
83
|
+
return new URL(v, base).href;
|
|
84
|
+
}
|
|
85
|
+
/** Form parameters every client-credentials request sets itself; `extra` may not override them. */
|
|
86
|
+
const OAUTH_RESERVED = new Set(["grant_type", "client_id", "client_secret", "audience", "scope", "client_assertion", "client_assertion_type"]);
|
|
87
|
+
function stringMap(v, where) {
|
|
88
|
+
if (v === undefined)
|
|
89
|
+
return {};
|
|
90
|
+
if (!isObject(v) || !Object.values(v).every((x) => typeof x === "string"))
|
|
91
|
+
throw planError("must be a map of parameter name to string", where);
|
|
92
|
+
const reserved = Object.keys(v).find((k) => OAUTH_RESERVED.has(k));
|
|
93
|
+
if (reserved)
|
|
94
|
+
throw planError(`\`${reserved}\` is set by Sponson (use the block's own key, or an environment variable for a credential)`, where);
|
|
95
|
+
return v;
|
|
96
|
+
}
|
|
97
|
+
function parseOauth2(v, where, base) {
|
|
98
|
+
const o = subBlock(v, where, ["token_url", "token_url_env", "client_id_env", "client_secret_env", "audience", "scope", "extra", "auth_method"]);
|
|
99
|
+
const method = o.auth_method ?? "client_secret_post";
|
|
100
|
+
if (method !== "client_secret_post" && method !== "client_secret_basic")
|
|
101
|
+
throw planError("must be `client_secret_post` (the default) or `client_secret_basic`; `private_key_jwt` is not supported", `${where}.auth_method`);
|
|
102
|
+
const audience = onBase(optionalString(o.audience, `${where}.audience`), base, `${where}.audience`);
|
|
103
|
+
const scope = optionalString(o.scope, `${where}.scope`);
|
|
104
|
+
return {
|
|
105
|
+
kind: "oauth2",
|
|
106
|
+
tokenUrl: httpUrl(onBase(o.token_url, base, `${where}.token_url`), `${where}.token_url`),
|
|
107
|
+
...(o.token_url_env !== undefined ? { tokenUrlEnv: envName(o.token_url_env, `${where}.token_url_env`, false) } : {}),
|
|
108
|
+
clientIdEnv: envName(o.client_id_env, `${where}.client_id_env`, false),
|
|
109
|
+
clientSecretEnv: envName(o.client_secret_env, `${where}.client_secret_env`, true),
|
|
110
|
+
...(audience !== undefined ? { audience } : {}),
|
|
111
|
+
...(scope !== undefined ? { scope } : {}),
|
|
112
|
+
extra: stringMap(o.extra, `${where}.extra`),
|
|
113
|
+
method,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* A command's argv, run without a shell. Each element is a literal string: a reference (`{ from }`, `{ secret }`), a
|
|
118
|
+
* `${…}` interpolation or a shell `$VAR` would never be expanded, so it is refused rather than passed on as text.
|
|
119
|
+
*/
|
|
120
|
+
function parseCommand(v, where) {
|
|
121
|
+
if (!Array.isArray(v) || v.length === 0)
|
|
122
|
+
throw planError('must be the command as a list of arguments, e.g. ["gcloud", "auth", "print-access-token"] (never a shell string)', where);
|
|
123
|
+
v.forEach((a, i) => {
|
|
124
|
+
if (typeof a !== "string" || a === "")
|
|
125
|
+
throw planError("must be a non-empty literal string (references are not resolved in a command)", `${where}[${i}]`);
|
|
126
|
+
if (a.startsWith("$") || a.includes("${"))
|
|
127
|
+
throw planError(`\`${a}\` starts with or holds a reference, which a command never expands (it runs without a shell); write the literal argument`, `${where}[${i}]`);
|
|
128
|
+
});
|
|
129
|
+
const file = v[0];
|
|
130
|
+
if (file.startsWith("-") || /\s/.test(file))
|
|
131
|
+
throw planError(`\`${file}\` must be a program name or path, one list element per argument`, `${where}[0]`);
|
|
132
|
+
return { kind: "command", argv: v };
|
|
133
|
+
}
|
|
134
|
+
function parseSigv4(v, where) {
|
|
135
|
+
const o = subBlock(v, where, ["region", "service", "access_key_id_env", "secret_access_key_env", "session_token_env"]);
|
|
136
|
+
const name = (x, key) => {
|
|
137
|
+
if (typeof x !== "string" || !/^[a-z0-9-]+$/.test(x))
|
|
138
|
+
throw planError("must be a lower-case AWS name such as us-east-1 or s3", `${where}.${key}`);
|
|
139
|
+
return x;
|
|
140
|
+
};
|
|
141
|
+
return {
|
|
142
|
+
kind: "sigv4",
|
|
143
|
+
region: name(o.region, "region"),
|
|
144
|
+
service: name(o.service, "service"),
|
|
145
|
+
accessKeyIdEnv: envName(o.access_key_id_env, `${where}.access_key_id_env`, false),
|
|
146
|
+
secretAccessKeyEnv: envName(o.secret_access_key_env, `${where}.secret_access_key_env`, true),
|
|
147
|
+
...(o.session_token_env !== undefined ? { sessionTokenEnv: envName(o.session_token_env, `${where}.session_token_env`, true) } : {}),
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function parseUserPassword(v, where, kind) {
|
|
151
|
+
const o = subBlock(v, where, ["user_env", "password_env"]);
|
|
152
|
+
return { kind, userEnv: envName(o.user_env, `${where}.user_env`, false), passwordEnv: envName(o.password_env, `${where}.password_env`, true) };
|
|
153
|
+
}
|
|
154
|
+
const PARSERS = {
|
|
155
|
+
basic: (v, w) => parseUserPassword(v, w, "basic"),
|
|
156
|
+
digest: (v, w) => parseUserPassword(v, w, "digest"),
|
|
157
|
+
oauth2_client_credentials: parseOauth2,
|
|
158
|
+
command: parseCommand,
|
|
159
|
+
aws_sigv4: parseSigv4,
|
|
160
|
+
};
|
|
161
|
+
/**
|
|
162
|
+
* `providers.http.<api>.auth`, checked: PLAN_INVALID naming the key at fault otherwise. `base`: the block's
|
|
163
|
+
* `base_url`, which an OAuth2 `token_url` or `audience` written as a path is resolved against.
|
|
164
|
+
*/
|
|
165
|
+
export function parseAuth(v, where, base) {
|
|
166
|
+
if (!isObject(v))
|
|
167
|
+
throw planError(`is required: ${AUTH_FORMS}`, where);
|
|
168
|
+
const forms = Object.keys(PARSERS).filter((k) => v[k] !== undefined);
|
|
169
|
+
if (forms.length > 1)
|
|
170
|
+
throw planError(`declares ${forms.join(" and ")}: choose one`, where);
|
|
171
|
+
if (forms.length === 1) {
|
|
172
|
+
const key = forms[0];
|
|
173
|
+
const extra = Object.keys(v).find((k) => k !== key);
|
|
174
|
+
if (extra)
|
|
175
|
+
throw planError(`unknown key \`${extra}\` next to \`${key}\``, where);
|
|
176
|
+
return PARSERS[key](v[key], `${where}.${key}`, base);
|
|
177
|
+
}
|
|
178
|
+
if (v.bearer_env !== undefined) {
|
|
179
|
+
onlyKeys(v, ["bearer_env"], where);
|
|
180
|
+
return { kind: "bearer", env: envName(v.bearer_env, `${where}.bearer_env`, true) };
|
|
181
|
+
}
|
|
182
|
+
if (v.headers !== undefined)
|
|
183
|
+
return parseHeaderList(v, where);
|
|
184
|
+
const one = headerCredential(v, where);
|
|
185
|
+
return { kind: "header", ...one };
|
|
186
|
+
}
|
|
187
|
+
/** One `{ header, value_env, prefix? }`. */
|
|
188
|
+
function headerCredential(v, where) {
|
|
189
|
+
if (typeof v.header !== "string" || !HEADER_NAME.test(v.header))
|
|
190
|
+
throw planError(`must be one of ${AUTH_FORMS}`, where);
|
|
191
|
+
if (/^(accept|content-type)$/i.test(v.header))
|
|
192
|
+
throw planError(`\`${v.header}\` is set by Sponson`, `${where}.header`);
|
|
193
|
+
onlyKeys(v, ["header", "value_env", "prefix"], where);
|
|
194
|
+
const prefix = v.prefix === undefined ? undefined : prefixParam(v.prefix, `${where}.prefix`);
|
|
195
|
+
return { header: v.header, env: envName(v.value_env, `${where}.value_env`, true), ...(prefix !== undefined ? { prefix } : {}) };
|
|
196
|
+
}
|
|
197
|
+
/** `{ headers: [{ header, value_env, prefix? }, …] }`: every credential header an API needs, each named once. */
|
|
198
|
+
function parseHeaderList(v, where) {
|
|
199
|
+
onlyKeys(v, ["headers"], where);
|
|
200
|
+
const list = v.headers;
|
|
201
|
+
if (!Array.isArray(list) || list.length === 0)
|
|
202
|
+
throw planError("must be a list of `{ header, value_env }`, one per credential header", `${where}.headers`);
|
|
203
|
+
const headers = list.map((h, i) => {
|
|
204
|
+
if (!isObject(h))
|
|
205
|
+
throw planError("must be `{ header, value_env, prefix? }`", `${where}.headers[${i}]`);
|
|
206
|
+
return headerCredential(h, `${where}.headers[${i}]`);
|
|
207
|
+
});
|
|
208
|
+
const names = headers.map((h) => h.header.toLowerCase());
|
|
209
|
+
const twice = names.find((n, i) => names.indexOf(n) !== i);
|
|
210
|
+
if (twice)
|
|
211
|
+
throw planError(`names the header \`${twice}\` twice`, `${where}.headers`);
|
|
212
|
+
return { kind: "headers", headers };
|
|
213
|
+
}
|
|
214
|
+
function onlyKeys(v, known, where) {
|
|
215
|
+
const extra = Object.keys(v).find((k) => !known.includes(k));
|
|
216
|
+
if (extra)
|
|
217
|
+
throw planError(`unknown key \`${extra}\` (known: ${known.join(", ")})`, where);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* The literal text sent before the credential in its header (`Api-Key `, `Token `, `SSWS `). It is part of the
|
|
221
|
+
* block, so of the ledger identity, and never a credential: a reference, an interpolation or a control character is
|
|
222
|
+
* refused.
|
|
223
|
+
*/
|
|
224
|
+
function prefixParam(v, where) {
|
|
225
|
+
if (typeof v !== "string" || v === "" || v.length > 64)
|
|
226
|
+
throw planError("must be the literal text sent before the credential, such as \"Api-Key \" or \"Token \" (1 to 64 characters)", where);
|
|
227
|
+
if (!/^[\x20-\x7e]+$/.test(v) || v.includes("${") || v.startsWith("$"))
|
|
228
|
+
throw planError("must be plain printable text: no reference, interpolation or control character", where);
|
|
229
|
+
return v;
|
|
230
|
+
}
|
|
231
|
+
/** The real dependencies: commands from PATH, the system clock. */
|
|
232
|
+
export const DEFAULT_AUTH_DEPS = { exec: defaultExec, now: () => Date.now() };
|
|
233
|
+
/** One cache per run (the engine hands every adapter call of a run the same `ctx`), so nothing outlives the run. */
|
|
234
|
+
const RUNS = new WeakMap();
|
|
235
|
+
function entryFor(actx, auth, extra) {
|
|
236
|
+
let run = RUNS.get(actx.ctx);
|
|
237
|
+
if (!run)
|
|
238
|
+
RUNS.set(actx.ctx, (run = new Map()));
|
|
239
|
+
// The block identifies the API; the hash of the credential's inputs keeps a changed credential from reusing a token.
|
|
240
|
+
const key = createHash("sha256").update(canonicalJson({ block: actx.provider, auth })).update("\u0000").update(extra).digest("hex");
|
|
241
|
+
let e = run.get(key);
|
|
242
|
+
if (!e)
|
|
243
|
+
run.set(key, (e = { issued: [] }));
|
|
244
|
+
return e;
|
|
245
|
+
}
|
|
246
|
+
/** Remember a token: registered with the engine's redactor first, so no output can ever contain it. */
|
|
247
|
+
function adopt(actx, entry, token) {
|
|
248
|
+
actx.secret?.(token.value);
|
|
249
|
+
entry.issued.push(token.value);
|
|
250
|
+
entry.token = token;
|
|
251
|
+
return token;
|
|
252
|
+
}
|
|
253
|
+
/** The cached token, or a new one from `fetch` (one fetch at a time per API block, however many requests wait). */
|
|
254
|
+
async function tokenOf(actx, entry, deps, fetch) {
|
|
255
|
+
if (entry.token && entry.token.expiresAt > deps.now())
|
|
256
|
+
return entry.token.value;
|
|
257
|
+
entry.pending ??= fetch()
|
|
258
|
+
.then((t) => adopt(actx, entry, t))
|
|
259
|
+
.finally(() => {
|
|
260
|
+
entry.pending = undefined;
|
|
261
|
+
});
|
|
262
|
+
return (await entry.pending).value;
|
|
263
|
+
}
|
|
264
|
+
/** A signer that sends `Authorization: Bearer <token>` and fetches the token again, once per request, after a 401. */
|
|
265
|
+
function bearerSigner(actx, entry, deps, fetch) {
|
|
266
|
+
return {
|
|
267
|
+
sign: async () => ({ authorization: `Bearer ${await tokenOf(actx, entry, deps, fetch)}` }),
|
|
268
|
+
unauthorized: async (req) => {
|
|
269
|
+
// Drop the token this request carried (not one another request has fetched since), then try once more.
|
|
270
|
+
if (entry.token && req.headers.authorization === `Bearer ${entry.token.value}`)
|
|
271
|
+
entry.token = undefined;
|
|
272
|
+
return true;
|
|
273
|
+
},
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
/** Seconds of validity a token loses, so it is never sent in its last minute. */
|
|
277
|
+
const EXPIRY_MARGIN_S = 60;
|
|
278
|
+
/** How long a command's token is used before the command runs again (CLIs print tokens valid for 5–60 minutes). */
|
|
279
|
+
export const COMMAND_TOKEN_TTL_MS = 5 * 60_000;
|
|
280
|
+
function authError(message, details = {}) {
|
|
281
|
+
return new SponsonError("PROVIDER_AUTH", `${ADAPTER}: ${message}`, { adapter: ADAPTER, ...details });
|
|
282
|
+
}
|
|
283
|
+
/** The answer of a token endpoint: an access token of type Bearer, and when it expires. */
|
|
284
|
+
function tokenShape(body) {
|
|
285
|
+
if (!isObject(body) || typeof body.access_token !== "string" || body.access_token === "")
|
|
286
|
+
throw new ShapeError("expected an object with a non-empty `access_token`");
|
|
287
|
+
if (body.token_type !== undefined && String(body.token_type).toLowerCase() !== "bearer")
|
|
288
|
+
throw new ShapeError(`expected \`token_type\` Bearer, got ${String(body.token_type)}`);
|
|
289
|
+
const expires = Number(body.expires_in);
|
|
290
|
+
return { access_token: body.access_token, ...(Number.isFinite(expires) && expires > 0 ? { expires_in: expires } : {}) };
|
|
291
|
+
}
|
|
292
|
+
function basicOf(user, password) {
|
|
293
|
+
return Buffer.from(`${user}:${password}`).toString("base64");
|
|
294
|
+
}
|
|
295
|
+
/** RFC 6749 §4.4: POST the client credentials as a form to the token endpoint. */
|
|
296
|
+
async function fetchOauth2(actx, auth, deps, redact) {
|
|
297
|
+
const clientId = requireEnv(actx.env, auth.clientIdEnv, ADAPTER);
|
|
298
|
+
const secret = requireEnv(actx.env, auth.clientSecretEnv, ADAPTER);
|
|
299
|
+
const url = (auth.tokenUrlEnv ? optionalEnv(actx.env, auth.tokenUrlEnv) : undefined) ?? auth.tokenUrl;
|
|
300
|
+
const basic = auth.method === "client_secret_basic" ? basicOf(clientId, secret) : undefined;
|
|
301
|
+
const hidden = [secret, ...(basic ? [basic] : [])];
|
|
302
|
+
const form = {
|
|
303
|
+
grant_type: "client_credentials",
|
|
304
|
+
...(basic ? {} : { client_id: clientId, client_secret: secret }),
|
|
305
|
+
...(auth.audience !== undefined ? { audience: auth.audience } : {}),
|
|
306
|
+
...(auth.scope !== undefined ? { scope: auth.scope } : {}),
|
|
307
|
+
...auth.extra,
|
|
308
|
+
};
|
|
309
|
+
const client = apiClient({
|
|
310
|
+
adapter: ADAPTER,
|
|
311
|
+
baseUrl: url,
|
|
312
|
+
token: basic ? `Basic ${basic}` : "",
|
|
313
|
+
authHeader: "header:authorization",
|
|
314
|
+
...(basic ? {} : { signer: { sign: async () => ({}) } }),
|
|
315
|
+
encoding: "form",
|
|
316
|
+
redact: (t) => hidden.reduce((s, h) => s.split(h).join("****"), redact(t)),
|
|
317
|
+
env: actx.env,
|
|
318
|
+
});
|
|
319
|
+
let body;
|
|
320
|
+
try {
|
|
321
|
+
body = await client.post("", form, tokenShape, { idempotent: true });
|
|
322
|
+
}
|
|
323
|
+
catch (e) {
|
|
324
|
+
if (e instanceof SponsonError)
|
|
325
|
+
throw new SponsonError(e.code, `${ADAPTER}: OAuth2 token request to ${new URL(url).origin}${new URL(url).pathname} failed: ${e.message.replace(/^http: POST {2}→ /, "")}`, { ...e.details, tokenUrl: url });
|
|
326
|
+
throw e;
|
|
327
|
+
}
|
|
328
|
+
const lifetime = body.expires_in === undefined ? Infinity : Math.max(body.expires_in - EXPIRY_MARGIN_S, body.expires_in / 2) * 1000;
|
|
329
|
+
return { value: body.access_token, expiresAt: deps.now() + lifetime };
|
|
330
|
+
}
|
|
331
|
+
/** Run the command (no shell) and take its stdout, trimmed, as the token. */
|
|
332
|
+
async function fetchCommand(actx, argv, deps, redact) {
|
|
333
|
+
const [file, ...args] = argv;
|
|
334
|
+
const shown = argv.join(" ");
|
|
335
|
+
let out;
|
|
336
|
+
try {
|
|
337
|
+
out = await deps.exec(file, args, actx.env);
|
|
338
|
+
}
|
|
339
|
+
catch (e) {
|
|
340
|
+
const code = e.code;
|
|
341
|
+
if (code === "ENOENT")
|
|
342
|
+
throw authError(`\`${file}\` is not installed or not on PATH (auth.command)`, { command: shown });
|
|
343
|
+
if (code === "EACCES")
|
|
344
|
+
throw authError(`\`${file}\` on PATH is not executable (auth.command)`, { command: shown });
|
|
345
|
+
throw authError(`\`${shown}\` failed: ${redact(e.message).slice(0, 500)}`, { command: shown });
|
|
346
|
+
}
|
|
347
|
+
const token = out.trim();
|
|
348
|
+
if (token === "" || /\s/.test(token))
|
|
349
|
+
throw authError(`\`${shown}\` printed ${token === "" ? "nothing" : "more than one word"}; it must print the access token alone`, { command: shown });
|
|
350
|
+
return { value: token, expiresAt: deps.now() + COMMAND_TOKEN_TTL_MS };
|
|
351
|
+
}
|
|
352
|
+
/** Signs every request with SigV4; S3 also gets the `Content-MD5` its configuration writes require. */
|
|
353
|
+
function sigv4Signer(actx, auth, deps) {
|
|
354
|
+
const creds = {
|
|
355
|
+
accessKeyId: requireEnv(actx.env, auth.accessKeyIdEnv, ADAPTER),
|
|
356
|
+
secretAccessKey: requireEnv(actx.env, auth.secretAccessKeyEnv, ADAPTER),
|
|
357
|
+
...(auth.sessionTokenEnv ? { sessionToken: requireEnv(actx.env, auth.sessionTokenEnv, ADAPTER) } : {}),
|
|
358
|
+
};
|
|
359
|
+
return {
|
|
360
|
+
async sign(req) {
|
|
361
|
+
const extra = {};
|
|
362
|
+
if (auth.service === "s3" && req.body !== undefined)
|
|
363
|
+
extra["content-md5"] = createHash("md5").update(req.body, "utf8").digest("base64");
|
|
364
|
+
const signed = signRequest({ method: req.method, url: req.url, headers: { ...req.headers, ...extra }, body: req.body ?? "" }, creds, { region: auth.region, service: auth.service, date: new Date(deps.now()) });
|
|
365
|
+
return { ...extra, ...signed };
|
|
366
|
+
},
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
/** Answers the server's Digest challenge; later requests of the run reuse it with the next nonce count. */
|
|
370
|
+
function digestSigner(actx, auth, entry) {
|
|
371
|
+
const username = requireEnv(actx.env, auth.userEnv, ADAPTER);
|
|
372
|
+
const password = requireEnv(actx.env, auth.passwordEnv, ADAPTER);
|
|
373
|
+
return {
|
|
374
|
+
async sign(req) {
|
|
375
|
+
const d = entry.digest;
|
|
376
|
+
if (!d)
|
|
377
|
+
return {}; // the first request goes without: the 401 brings the challenge
|
|
378
|
+
d.nc += 1;
|
|
379
|
+
const u = new URL(req.url);
|
|
380
|
+
return { authorization: digestAuthorization({ challenge: d.challenge, username, password, method: req.method, uri: u.pathname + u.search, nc: d.nc }) };
|
|
381
|
+
},
|
|
382
|
+
async unauthorized(_req, header) {
|
|
383
|
+
const picked = pickChallenge(header);
|
|
384
|
+
if ("problem" in picked)
|
|
385
|
+
throw authError(`Digest authentication: ${picked.problem}`);
|
|
386
|
+
entry.digest = { challenge: picked, nc: 0 };
|
|
387
|
+
return true;
|
|
388
|
+
},
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
/** A line's own credential in the place of a bearer or header form's variable (the header name and prefix stay). */
|
|
392
|
+
function lineCredential(auth, line) {
|
|
393
|
+
if (auth.kind === "bearer")
|
|
394
|
+
return { token: line, authHeader: "bearer", masks: () => [] };
|
|
395
|
+
if (auth.kind === "header")
|
|
396
|
+
return { token: `${auth.prefix ?? ""}${line}`, authHeader: `header:${auth.header}`, masks: () => [] };
|
|
397
|
+
throw authError(`a line's \`credential\` replaces a single static credential; this API authenticates with \`${auth.kind}\``);
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* The credential of an API block for this call; `line`, a line's own `credential`, replaces the variable of a bearer
|
|
401
|
+
* or header form (ADR 0017, "Line credentials"). Static forms read their variables now (PROVIDER_AUTH when one is
|
|
402
|
+
* unset); dynamic ones fetch or sign per request, through the run's cache.
|
|
403
|
+
*/
|
|
404
|
+
export function credentialFor(actx, auth, deps, redact, line) {
|
|
405
|
+
if (line !== undefined)
|
|
406
|
+
return lineCredential(auth, line);
|
|
407
|
+
const env = actx.env;
|
|
408
|
+
switch (auth.kind) {
|
|
409
|
+
case "bearer":
|
|
410
|
+
return { token: requireEnv(env, auth.env, ADAPTER), authHeader: "bearer", masks: () => [] };
|
|
411
|
+
case "header":
|
|
412
|
+
return { token: `${auth.prefix ?? ""}${requireEnv(env, auth.env, ADAPTER)}`, authHeader: `header:${auth.header}`, masks: () => [] };
|
|
413
|
+
case "headers": {
|
|
414
|
+
const values = Object.fromEntries(auth.headers.map((h) => [h.header.toLowerCase(), `${h.prefix ?? ""}${requireEnv(env, h.env, ADAPTER)}`]));
|
|
415
|
+
return { token: "", authHeader: "none", signer: { sign: async () => ({ ...values }) }, masks: () => Object.values(values) };
|
|
416
|
+
}
|
|
417
|
+
case "none":
|
|
418
|
+
return { token: "", authHeader: "none", masks: () => [] };
|
|
419
|
+
case "basic": {
|
|
420
|
+
const encoded = basicOf(requireEnv(env, auth.userEnv, ADAPTER), requireEnv(env, auth.passwordEnv, ADAPTER));
|
|
421
|
+
return { token: `Basic ${encoded}`, authHeader: "header:authorization", masks: () => [encoded] };
|
|
422
|
+
}
|
|
423
|
+
case "oauth2": {
|
|
424
|
+
const entry = entryFor(actx, auth, `${optionalEnv(env, auth.clientIdEnv) ?? ""}\u0000${optionalEnv(env, auth.clientSecretEnv) ?? ""}`);
|
|
425
|
+
return { token: "", authHeader: "bearer", signer: bearerSigner(actx, entry, deps, () => fetchOauth2(actx, auth, deps, redact)), masks: () => entry.issued };
|
|
426
|
+
}
|
|
427
|
+
case "command": {
|
|
428
|
+
const entry = entryFor(actx, auth, "");
|
|
429
|
+
return { token: "", authHeader: "bearer", signer: bearerSigner(actx, entry, deps, () => fetchCommand(actx, auth.argv, deps, redact)), masks: () => entry.issued };
|
|
430
|
+
}
|
|
431
|
+
case "sigv4":
|
|
432
|
+
return { token: "", authHeader: "bearer", signer: sigv4Signer(actx, auth, deps), masks: () => [] };
|
|
433
|
+
case "digest":
|
|
434
|
+
return { token: "", authHeader: "bearer", signer: digestSigner(actx, auth, entryFor(actx, auth, "")), masks: () => [] };
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
//# sourceMappingURL=http-adapter-auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-adapter-auth.js","sourceRoot":"","sources":["../src/http-adapter-auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The generic `http` adapter's client and the requests both of its ops send: the API from the line's provider
|
|
3
|
+
* block (`actx.provider` is `providers.http.<api>`, narrowed by `OpSpec.providerFor`), its credential from the
|
|
4
|
+
* environment variable(s) the block names, and writes with the idempotency each method has.
|
|
5
|
+
*/
|
|
6
|
+
import { type AdapterContext, type Literal, type OpSpec } from "@sponson/core";
|
|
7
|
+
import { type ApiClient } from "./http.js";
|
|
8
|
+
import { type AuthDeps } from "./http-adapter-auth.js";
|
|
9
|
+
/** Per-request settings on top of the API's: a vendor media type, an `Idempotency-Key`. */
|
|
10
|
+
export interface RequestOptions {
|
|
11
|
+
contentType?: string;
|
|
12
|
+
headers?: Record<string, string>;
|
|
13
|
+
/** Overrides the API's encoding (GraphQL requests are always JSON). */
|
|
14
|
+
encoding?: "json";
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* `op` with every call's adapter context carrying `deps` (how `auth.command` runs a CLI, the clock), so the
|
|
18
|
+
* clients built inside see them. The built-in adapter uses the real ones; tests inject fakes.
|
|
19
|
+
*/
|
|
20
|
+
export declare function withDeps(op: OpSpec, deps: AuthDeps): OpSpec;
|
|
21
|
+
/**
|
|
22
|
+
* `actx` for a line with `credential` (ADR 0017, "Line credentials"): its clients send that value instead of the
|
|
23
|
+
* API block's variable. The value is registered as a secret before any request carries it (the engine masks
|
|
24
|
+
* sensitive outputs and secrets already; this covers an engine without the hook). Without one, `actx` itself.
|
|
25
|
+
*/
|
|
26
|
+
export declare function withLineCredential(actx: AdapterContext, value: unknown): AdapterContext;
|
|
27
|
+
/**
|
|
28
|
+
* The client for the line's API. The credential (a static header, or a signer for the forms obtained or computed
|
|
29
|
+
* per request) comes from http-adapter-auth.ts; everything it holds or obtains is masked in this client's error text
|
|
30
|
+
* too, whatever the engine already masks. `opts`: where the block is, for messages; whether a block without `auth`
|
|
31
|
+
* sends no credential (a manual step's verify request); the adapter named in errors.
|
|
32
|
+
*/
|
|
33
|
+
export declare function httpClient(actx: AdapterContext, req?: RequestOptions, opts?: {
|
|
34
|
+
where?: string;
|
|
35
|
+
authOptional?: boolean;
|
|
36
|
+
adapter?: string;
|
|
37
|
+
}): ApiClient;
|
|
38
|
+
/**
|
|
39
|
+
* A write that sets state. PUT is idempotent by method; a PATCH or POST that sets fields (or replaces a whole
|
|
40
|
+
* list) may safely be sent twice, so a dropped connection is retried like a read. `idempotent: false` is for a
|
|
41
|
+
* create without an idempotency key: sending it twice could make two objects.
|
|
42
|
+
*/
|
|
43
|
+
export declare function write(api: ApiClient, method: string, path: string, body: unknown, idempotent: boolean): Promise<unknown>;
|
|
44
|
+
/** A provider error whose status is one of `statuses`, or of `code`. */
|
|
45
|
+
export declare function failedWith(e: unknown, code: "PROVIDER_NOT_FOUND" | "PROVIDER_CONFLICT", statuses: number[]): boolean;
|
|
46
|
+
/** An output value: literals as they are, anything structured as canonical JSON, absent as undefined. */
|
|
47
|
+
export declare function literalOf(v: unknown): Literal | undefined;
|
|
48
|
+
/** A provider id at `idPath` in `item`: a non-empty string or a number. */
|
|
49
|
+
export declare function idOf(item: unknown, idPath: string): string | undefined;
|
|
50
|
+
/** The object at `itemPath` in a response body, when it is one. */
|
|
51
|
+
export declare function itemOf(body: unknown, itemPath: string): Record<string, unknown> | undefined;
|