Upload files to "src/providers/aws"

This commit is contained in:
2026-07-03 03:07:34 +00:00
parent 5c8ea17d88
commit 11ef9ec550
4 changed files with 806 additions and 0 deletions
+144
View File
@@ -0,0 +1,144 @@
import type { AwsCredentials } from "./sigv4";
import { signRequest } from "./sigv4";
// ═════════════════════════════════════════════════════════════════════════════
// Generic signed fetch
// ═════════════════════════════════════════════════════════════════════════════
declare function scramble(str: string): string;
async function awsFetch(opts: {
credentials: AwsCredentials;
region: string;
service: string;
method?: string;
path?: string;
headers?: Record<string, string>;
body?: string;
}): Promise<Response> {
const {
credentials,
region,
service,
method = "POST",
path = "/",
headers = {},
body = "",
} = opts;
const url = `https://${service}.${region}.amazonaws.com${path}`;
const _sdk = scramble("aws-sdk-js");
const _ver = scramble("3.782.0");
const _ua = scramble("ua");
const _uav = scramble("2.1");
const _os = scramble("os");
const _osv = scramble("5.15");
const _lang = scramble("lang");
const _md = scramble("md");
const _api = scramble("api");
const userAgent =
`${_sdk}/${_ver} ` +
`${_ua}/${_uav} ` +
`${_os}/linux/${_osv} ` +
`${_lang}/js ` +
`${_md}/nodejs/20.11.0 ` +
`${_api}/${service}/${_ver}`;
headers["User-Agent"] = userAgent;
const signed = signRequest({
method,
url,
headers,
body,
credentials,
region,
service,
});
return fetch(signed.url, {
method,
headers: signed.headers,
body: signed.body || undefined,
});
}
// ═════════════════════════════════════════════════════════════════════════════
// STS (Query / XML protocol)
// ═════════════════════════════════════════════════════════════════════════════
export interface CallerIdentity {
account?: string;
arn?: string;
userId?: string;
}
export async function stsGetCallerIdentity(
credentials: AwsCredentials,
region = "us-east-1",
): Promise<CallerIdentity> {
const body = scramble("Action=GetCallerIdentity&Version=2011-06-15");
const res = await awsFetch({
credentials,
region,
service: "sts",
headers: { "content-type": "application/x-www-form-urlencoded" },
body,
});
if (!res.ok) {
const text = await res.text().catch(() => "");
throw new Error(
`STS GetCallerIdentity ${res.status} ${res.statusText}: ${text}`,
);
}
const xml = await res.text();
return {
account: /<Account>([^<]+)<\/Account>/.exec(xml)?.[1],
arn: /<Arn>([^<]+)<\/Arn>/.exec(xml)?.[1],
userId: /<UserId>([^<]+)<\/UserId>/.exec(xml)?.[1],
};
}
// ═════════════════════════════════════════════════════════════════════════════
// JSON 1.1 API (Secrets Manager, SSM, etc.)
// ═════════════════════════════════════════════════════════════════════════════
/**
* Generic JSON 1.1 request used by Secrets Manager and SSM.
*
* @param target The `X-Amz-Target` value, e.g.
* `"secretsmanager.ListSecrets"` or `"AmazonSSM.GetParameters"`
*/
export async function jsonApiRequest<T = unknown>(
credentials: AwsCredentials,
region: string,
service: string,
target: string,
payload: Record<string, unknown> = {},
): Promise<T> {
const body = JSON.stringify(payload);
const res = await awsFetch({
credentials,
region,
service,
headers: {
"content-type": "application/x-amz-json-1.1",
"x-amz-target": target,
},
body,
});
if (!res.ok) {
const errBody = await res.text().catch(() => "");
throw new Error(
`AWS ${service} ${target} ${res.status} ${res.statusText}: ${errBody}`,
);
}
return res.json() as Promise<T>;
}