diff --git a/libraries/deno-commons-mod.ts b/libraries/deno-commons-mod.ts index 4fec99b..140d665 100644 --- a/libraries/deno-commons-mod.ts +++ b/libraries/deno-commons-mod.ts @@ -1255,14 +1255,23 @@ interface AlibabaCloudInstanceIdentityAudienceMeta { iat: number; exp: number; aud: string; + jti?: string; + scope?: string; + args?: string[]; } export type AlibabaCloudInstanceIdentityMode = "normal" | "secured"; +export interface AlibabaCloudInstanceIdentityOptions { + scope?: string; + args?: string[]; +} + // https://help.aliyun.com/zh/ecs/user-guide/use-instance-identities export async function fetchAlibabaCloudInstanceIdentityV1( audience: string, mode?: AlibabaCloudInstanceIdentityMode, + options?: AlibabaCloudInstanceIdentityOptions, ): Promise { let metaDataToken = null; if (!mode) { @@ -1290,7 +1299,14 @@ export async function fetchAlibabaCloudInstanceIdentityV1( iat: Math.floor(Date.now() / 1000), exp: Math.floor(Date.now() / 1000) + 60, aud: audience, + jti: "jti-" + Date.now() + "-" + Math.random(), } as AlibabaCloudInstanceIdentityAudienceMeta; + + if (options) { + if (options.scope) audienceMeta.scope = options.scope; + if (options.args) audienceMeta.args = options.args; + } + const pkcs7Options = {}; if (metaDataToken) { pkcs7Options["X-aliyun-ecs-metadata-token"] = metaDataToken; @@ -1332,7 +1348,7 @@ export async function getSecretValueViaAlibabaCloudInstanceIdentity( mode, ); const httpSecretResponse = await fetchDataWithTimeout( - `https://global.hatter.ink//secret/get.json?name=${ + `https://global.hatter.ink/secret/get.json?name=${ encodeURIComponent(key) }`, { @@ -1379,3 +1395,56 @@ export async function getSecretValue( } return await getSecretValueViaHatterCli(key); } + +interface StsToken { + mode: string; + expiration: string; + access_key_id: string; + access_key_secret: string; + sts_token: string; +} + +interface AssumeRoleByKeyResponse { + status: number; + message: string; + data: StsToken; +} + +export async function assumeRoleByKeyViaAlibabaCloudInstanceIdentity( + roleArn: string, + policy?: string, + mode?: AlibabaCloudInstanceIdentityMode, +): Promise { + const pkcs7 = await fetchAlibabaCloudInstanceIdentityV1( + "hatter.ink", + mode, + { + scope: "assume_role", + args: [roleArn, policy ?? null], + }, + ); + const httpAssumeRoleResponse = await fetchDataWithTimeout( + `https://global.hatter.ink/cloud/alibaba_cloud/assume_role_by_key.json`, + { + headers: { + "Authorization": `PKCS7 ${pkcs7}`, + }, + }, + ); + if (httpAssumeRoleResponse.status != 200) { + throw new Error( + `Assume role by key failed: ${httpAssumeRoleResponse.status}`, + ); + } + const assumeRoleResponse = await httpAssumeRoleResponse + .json() as AssumeRoleByKeyResponse; + log.debug("assumeRoleResponse", assumeRoleResponse); + if (assumeRoleResponse.status != 200) { + throw new Error( + `Assume role by key failed: ${assumeRoleResponse.status}, raw: ${ + JSON.stringify(assumeRoleResponse) + }`, + ); + } + return assumeRoleResponse.data; +} diff --git a/script-meta-v2.json b/script-meta-v2.json index a52876c..de7faa5 100644 --- a/script-meta-v2.json +++ b/script-meta-v2.json @@ -162,12 +162,12 @@ }, "openclaw-secret.ts": { "script_name": "openclaw-secret.ts", - "script_length": 3052, - "script_sha256": "47ba743e2045e7d8cdef1ba5834cc8bccdc257387dacce0d9be0d1c465f08252", + "script_length": 2750, + "script_sha256": "c43de9ceccac25bf3dbdb2a9e88dadeb3b0d1ea2ff5d365183041338ec9cebde", "script_full_url": "https://git.hatter.ink/hatter/ts-scripts/raw/branch/main/single-scripts/openclaw-secret.ts", "single_script_file": true, "publish_time": 1772860170553, - "update_time": 1772982710771 + "update_time": 1773496786102 }, "post-note.ts": { "script_name": "post-note.ts",