Mike Nason nsarrazin HF Staff commited on
Commit
cc0d6c5
·
unverified ·
1 Parent(s): 1f8ab3d

Dynamic credential resolution for AWS endpoints (#1419)

Browse files

* Dynamic credential resolution for AWS endpoints

If AWS credentials are provided, they will continue to be used. With this
change, they become optional parameters and the AWS SDK will attempt to
use the default resolution chain if they are not provided.

* cleanup deps

* restore optional aws region in endpointAwsParametersSchema

---------

Co-authored-by: Nathan Sarrazin <[email protected]>

package-lock.json CHANGED
@@ -18,6 +18,7 @@
18
  "@playwright/browser-chromium": "^1.43.1",
19
  "@resvg/resvg-js": "^2.6.2",
20
  "autoprefixer": "^10.4.14",
 
21
  "aws4": "^1.13.0",
22
  "browser-image-resizer": "^2.4.1",
23
  "date-fns": "^2.29.3",
@@ -5316,6 +5317,38 @@
5316
  "postcss": "^8.1.0"
5317
  }
5318
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5319
  "node_modules/aws4": {
5320
  "version": "1.13.1",
5321
  "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.1.tgz",
 
18
  "@playwright/browser-chromium": "^1.43.1",
19
  "@resvg/resvg-js": "^2.6.2",
20
  "autoprefixer": "^10.4.14",
21
+ "aws-sigv4-fetch": "^4.0.1",
22
  "aws4": "^1.13.0",
23
  "browser-image-resizer": "^2.4.1",
24
  "date-fns": "^2.29.3",
 
5317
  "postcss": "^8.1.0"
5318
  }
5319
  },
5320
+ "node_modules/aws-sigv4-fetch": {
5321
+ "version": "4.0.1",
5322
+ "resolved": "https://registry.npmjs.org/aws-sigv4-fetch/-/aws-sigv4-fetch-4.0.1.tgz",
5323
+ "integrity": "sha512-sd5TbxbOB82Y3mFoux6XbRn/QbNR9hTO7Dv+y8Y0G4+xlS6rP8OJCJwtgANnB4yYAshVqvLbTo6aqTrQUpthvA==",
5324
+ "dependencies": {
5325
+ "@aws-crypto/sha256-js": "^5.2.0",
5326
+ "@aws-sdk/credential-provider-node": "^3.609.0",
5327
+ "@aws-sdk/types": "^3.609.0",
5328
+ "@smithy/protocol-http": "^4.0.3",
5329
+ "@smithy/signature-v4": "^3.1.2"
5330
+ },
5331
+ "engines": {
5332
+ "node": ">=18"
5333
+ }
5334
+ },
5335
+ "node_modules/aws-sigv4-fetch/node_modules/@smithy/signature-v4": {
5336
+ "version": "3.1.2",
5337
+ "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-3.1.2.tgz",
5338
+ "integrity": "sha512-3BcPylEsYtD0esM4Hoyml/+s7WP2LFhcM3J2AGdcL2vx9O60TtfpDOL72gjb4lU8NeRPeKAwR77YNyyGvMbuEA==",
5339
+ "dependencies": {
5340
+ "@smithy/is-array-buffer": "^3.0.0",
5341
+ "@smithy/types": "^3.3.0",
5342
+ "@smithy/util-hex-encoding": "^3.0.0",
5343
+ "@smithy/util-middleware": "^3.0.3",
5344
+ "@smithy/util-uri-escape": "^3.0.0",
5345
+ "@smithy/util-utf8": "^3.0.0",
5346
+ "tslib": "^2.6.2"
5347
+ },
5348
+ "engines": {
5349
+ "node": ">=16.0.0"
5350
+ }
5351
+ },
5352
  "node_modules/aws4": {
5353
  "version": "1.13.1",
5354
  "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.1.tgz",
package.json CHANGED
@@ -69,6 +69,7 @@
69
  "@resvg/resvg-js": "^2.6.2",
70
  "autoprefixer": "^10.4.14",
71
  "aws4": "^1.13.0",
 
72
  "browser-image-resizer": "^2.4.1",
73
  "date-fns": "^2.29.3",
74
  "dotenv": "^16.0.3",
 
69
  "@resvg/resvg-js": "^2.6.2",
70
  "autoprefixer": "^10.4.14",
71
  "aws4": "^1.13.0",
72
+ "aws-sigv4-fetch": "^4.0.1",
73
  "browser-image-resizer": "^2.4.1",
74
  "date-fns": "^2.29.3",
75
  "dotenv": "^16.0.3",
src/lib/server/endpoints/aws/endpointAws.ts CHANGED
@@ -8,8 +8,20 @@ export const endpointAwsParametersSchema = z.object({
8
  model: z.any(),
9
  type: z.literal("aws"),
10
  url: z.string().url(),
11
- accessKey: z.string().min(1),
12
- secretKey: z.string().min(1),
 
 
 
 
 
 
 
 
 
 
 
 
13
  sessionToken: z.string().optional(),
14
  service: z.union([z.literal("sagemaker"), z.literal("lambda")]).default("sagemaker"),
15
  region: z.string().optional(),
@@ -18,22 +30,23 @@ export const endpointAwsParametersSchema = z.object({
18
  export async function endpointAws(
19
  input: z.input<typeof endpointAwsParametersSchema>
20
  ): Promise<Endpoint> {
21
- let AwsClient;
22
  try {
23
- AwsClient = (await import("aws4fetch")).AwsClient;
24
  } catch (e) {
25
- throw new Error("Failed to import aws4fetch");
26
  }
27
 
28
  const { url, accessKey, secretKey, sessionToken, model, region, service } =
29
  endpointAwsParametersSchema.parse(input);
30
 
31
- const aws = new AwsClient({
32
- accessKeyId: accessKey,
33
- secretAccessKey: secretKey,
34
- sessionToken,
35
  service,
36
  region,
 
 
 
 
37
  });
38
 
39
  return async ({ messages, preprompt, continueMessage, generateSettings }) => {
@@ -52,7 +65,7 @@ export async function endpointAws(
52
  },
53
  {
54
  use_cache: false,
55
- fetch: aws.fetch.bind(aws) as typeof fetch,
56
  }
57
  );
58
  };
 
8
  model: z.any(),
9
  type: z.literal("aws"),
10
  url: z.string().url(),
11
+ accessKey: z
12
+ .string({
13
+ description:
14
+ "An AWS Access Key ID. If not provided, the default AWS identity resolution will be used",
15
+ })
16
+ .min(1)
17
+ .optional(),
18
+ secretKey: z
19
+ .string({
20
+ description:
21
+ "An AWS Access Key Secret. If not provided, the default AWS identity resolution will be used",
22
+ })
23
+ .min(1)
24
+ .optional(),
25
  sessionToken: z.string().optional(),
26
  service: z.union([z.literal("sagemaker"), z.literal("lambda")]).default("sagemaker"),
27
  region: z.string().optional(),
 
30
  export async function endpointAws(
31
  input: z.input<typeof endpointAwsParametersSchema>
32
  ): Promise<Endpoint> {
33
+ let createSignedFetcher;
34
  try {
35
+ createSignedFetcher = (await import("aws-sigv4-fetch")).createSignedFetcher;
36
  } catch (e) {
37
+ throw new Error("Failed to import aws-sigv4-fetch");
38
  }
39
 
40
  const { url, accessKey, secretKey, sessionToken, model, region, service } =
41
  endpointAwsParametersSchema.parse(input);
42
 
43
+ const signedFetch = createSignedFetcher({
 
 
 
44
  service,
45
  region,
46
+ credentials:
47
+ accessKey && secretKey
48
+ ? { accessKeyId: accessKey, secretAccessKey: secretKey, sessionToken }
49
+ : undefined,
50
  });
51
 
52
  return async ({ messages, preprompt, continueMessage, generateSettings }) => {
 
65
  },
66
  {
67
  use_cache: false,
68
+ fetch: signedFetch,
69
  }
70
  );
71
  };