diff --git a/.changeset/fix-aws-s3-url-reader-custom-endpoints.md b/.changeset/fix-aws-s3-url-reader-custom-endpoints.md new file mode 100644 index 0000000000..c9fe3923ba --- /dev/null +++ b/.changeset/fix-aws-s3-url-reader-custom-endpoints.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-defaults': patch +--- + +Fixed `AwsS3UrlReader` failing to read files from S3 buckets configured with custom endpoint hosts. When an integration was configured with a specific endpoint like `https://bucket-1.s3.eu-central-1.amazonaws.com`, the URL parser incorrectly fell through to the non-AWS code path, always defaulting the region to `us-east-1` instead of extracting it from the hostname. diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/AwsS3UrlReader.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/AwsS3UrlReader.test.ts index dc3d1e5b8e..3592b3d72b 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/AwsS3UrlReader.test.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/AwsS3UrlReader.test.ts @@ -128,6 +128,55 @@ describe('parseUrl', () => { }); }); + it('supports aws formats with custom endpoint hosts', () => { + expect( + parseUrl( + 'https://bucket-1.s3.eu-central-1.amazonaws.com/path/to/file.yaml', + { + host: 'bucket-1.s3.eu-central-1.amazonaws.com', + }, + ), + ).toEqual({ + path: 'path/to/file.yaml', + bucket: 'bucket-1', + region: 'eu-central-1', + }); + expect( + parseUrl('https://my-bucket.s3.cn-north-1.amazonaws.com.cn/data.json', { + host: 'my-bucket.s3.cn-north-1.amazonaws.com.cn', + }), + ).toEqual({ + path: 'data.json', + bucket: 'my-bucket', + region: 'cn-north-1', + }); + expect( + parseUrl( + 'https://s3.eu-central-1.amazonaws.com/my-bucket/path/to/file.yaml', + { + host: 's3.eu-central-1.amazonaws.com', + }, + ), + ).toEqual({ + path: 'path/to/file.yaml', + bucket: 'my-bucket', + region: 'eu-central-1', + }); + expect( + parseUrl( + 'https://s3.eu-central-1.amazonaws.com/my-bucket/path/to/file.yaml', + { + host: 's3.eu-central-1.amazonaws.com', + s3ForcePathStyle: true, + }, + ), + ).toEqual({ + path: 'path/to/file.yaml', + bucket: 'my-bucket', + region: 'eu-central-1', + }); + }); + it('supports all non-aws formats', () => { expect( parseUrl('https://my-host.com/my.bucket-3/a/puppy.jpg', { diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/AwsS3UrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/AwsS3UrlReader.ts index cb776fc977..802397d526 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/AwsS3UrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/AwsS3UrlReader.ts @@ -74,7 +74,10 @@ export function parseUrl( const host = parsedUrl.host; // Treat Amazon hosted separately because it has special region logic - if (config.host === 'amazonaws.com' || config.host === 'amazonaws.com.cn') { + if ( + config.host.endsWith('amazonaws.com') || + config.host.endsWith('amazonaws.com.cn') + ) { const match = host.match( /^(?:([a-z0-9.-]+)\.)?s3(?:[.-]([a-z0-9-]+))?\.amazonaws\.com(\.cn)?$/, );