From 3626118eefc224f680b147b314b00c3982ad156a Mon Sep 17 00:00:00 2001 From: Stevche Radevski Date: Wed, 11 Dec 2024 18:30:37 +0800 Subject: [PATCH] feat(file-s3): Add support for IAM role authentication to file-s3 provider (#10528) --- packages/core/types/src/file/providers/s3.ts | 5 +-- .../modules/providers/file-s3/package.json | 2 +- .../providers/file-s3/src/services/s3-file.ts | 34 ++++++++++++++----- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/packages/core/types/src/file/providers/s3.ts b/packages/core/types/src/file/providers/s3.ts index 750bdadcdb221..afd1aff5b691f 100644 --- a/packages/core/types/src/file/providers/s3.ts +++ b/packages/core/types/src/file/providers/s3.ts @@ -1,7 +1,8 @@ export interface S3FileServiceOptions { file_url: string - access_key_id: string - secret_access_key: string + access_key_id?: string + secret_access_key?: string + authentication_method?: "access-key" | "s3-iam-role" region: string bucket: string prefix?: string diff --git a/packages/modules/providers/file-s3/package.json b/packages/modules/providers/file-s3/package.json index 80d3e8db9be54..f981d957899c8 100644 --- a/packages/modules/providers/file-s3/package.json +++ b/packages/modules/providers/file-s3/package.json @@ -21,7 +21,7 @@ "license": "MIT", "scripts": { "test": "jest --passWithNoTests src", - "test:integration": "jest --forceExit -- integration-tests/**/__tests__/**/*.spec.ts", + "test:integration": "jest --forceExit -- integration-tests/__tests__/*.spec.ts", "build": "rimraf dist && tsc --build ./tsconfig.json", "watch": "tsc --watch" }, diff --git a/packages/modules/providers/file-s3/src/services/s3-file.ts b/packages/modules/providers/file-s3/src/services/s3-file.ts index 152ca60b6f947..2f4dbf387baa7 100644 --- a/packages/modules/providers/file-s3/src/services/s3-file.ts +++ b/packages/modules/providers/file-s3/src/services/s3-file.ts @@ -23,10 +23,10 @@ type InjectedDependencies = { } interface S3FileServiceConfig { - // TODO: We probably don't need this as either the service should return it or we should be able to calculate it. fileUrl: string - accessKeyId: string - secretAccessKey: string + accessKeyId?: string + secretAccessKey?: string + authenticationMethod?: "access-key" | "s3-iam-role" region: string bucket: string prefix?: string @@ -36,7 +36,6 @@ interface S3FileServiceConfig { additionalClientConfig?: Record } -// FUTURE: At one point we will probably need to support authenticating with IAM roles instead. export class S3FileService extends AbstractFileProviderService { static identifier = "s3" protected config_: S3FileServiceConfig @@ -46,10 +45,23 @@ export class S3FileService extends AbstractFileProviderService { constructor({ logger }: InjectedDependencies, options: S3FileServiceOptions) { super() + const authenticationMethod = options.authentication_method ?? "access-key" + + if ( + authenticationMethod === "access-key" && + (!options.access_key_id || !options.secret_access_key) + ) { + throw new MedusaError( + MedusaError.Types.INVALID_DATA, + `Access key ID and secret access key are required when using access key authentication` + ) + } + this.config_ = { fileUrl: options.file_url, accessKeyId: options.access_key_id, secretAccessKey: options.secret_access_key, + authenticationMethod: authenticationMethod, region: options.region, bucket: options.bucket, prefix: options.prefix ?? "", @@ -63,11 +75,17 @@ export class S3FileService extends AbstractFileProviderService { } protected getClient() { + // If none is provided, the SDK will use the default credentials provider chain, see https://docs.aws.amazon.com/cli/v1/userguide/cli-configure-envvars.html + const credentials = + this.config_.authenticationMethod === "access-key" + ? { + accessKeyId: this.config_.accessKeyId!, + secretAccessKey: this.config_.secretAccessKey!, + } + : undefined + const config: S3ClientConfigType = { - credentials: { - accessKeyId: this.config_.accessKeyId, - secretAccessKey: this.config_.secretAccessKey, - }, + credentials, region: this.config_.region, endpoint: this.config_.endpoint, ...this.config_.additionalClientConfig,