diff --git a/.changeset/warm-moments-repeat.md b/.changeset/warm-moments-repeat.md new file mode 100644 index 0000000000..a72387d720 --- /dev/null +++ b/.changeset/warm-moments-repeat.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-defaults': patch +--- + +Fix #31348 issue where BitbucketUrlReader ignored provided token and instead always used integration credentials diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.test.ts index 29217ea1f5..f06bf41953 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.test.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.test.ts @@ -130,6 +130,27 @@ describe('BitbucketUrlReader', () => { expect(buffer.toString()).toBe('foo'); }); + it('should be able to readUrl using provided token', async () => { + worker.use( + rest.get( + 'https://api.bitbucket.org/2.0/repositories/backstage-verification/test-template/src/master/template.yaml', + (req, res, ctx) => { + expect(req.headers.get('authorization')).toBe( + 'Bearer manual-token', + ); + return res(ctx.status(200), ctx.body('foo')); + }, + ), + ); + + const result = await bitbucketProcessor.readUrl( + 'https://bitbucket.org/backstage-verification/test-template/src/master/template.yaml', + { token: 'manual-token' }, + ); + const buffer = await result.buffer(); + expect(buffer.toString()).toBe('foo'); + }); + it('should be able to readUrl via stream without ETag', async () => { worker.use( rest.get( diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.ts index 4c6de31aa4..913c24c69f 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.ts @@ -93,13 +93,27 @@ export class BitbucketUrlReader implements UrlReaderService { return response.buffer(); } + private getCredentials = async (options?: { + token?: string; + }): Promise<{ headers: Record }> => { + if (options?.token) { + return { + headers: { + Authorization: `Bearer ${options.token}`, + }, + }; + } + + return await getBitbucketRequestOptions(this.integration.config); + }; + async readUrl( url: string, options?: UrlReaderServiceReadUrlOptions, ): Promise { const { etag, lastModifiedAfter, signal } = options ?? {}; const bitbucketUrl = getBitbucketFileFetchUrl(url, this.integration.config); - const requestOptions = getBitbucketRequestOptions(this.integration.config); + const requestOptions = await this.getCredentials(options); let response: Response; try {