From 45d7d40952e354050afaace85c5789610dd94426 Mon Sep 17 00:00:00 2001 From: Etienne Date: Wed, 1 Jul 2020 15:48:22 +0200 Subject: [PATCH] fix: remove authorization header from core.windows.net requests for Azure docker registries (#6641) Co-authored-by: Michael Kriese --- lib/util/http/auth.spec.ts | 108 +++++++++++++++++++++++++++++++++++++ lib/util/http/auth.ts | 36 +++++++++++++ lib/util/http/index.ts | 21 +------- 3 files changed, 146 insertions(+), 19 deletions(-) create mode 100644 lib/util/http/auth.spec.ts diff --git a/lib/util/http/auth.spec.ts b/lib/util/http/auth.spec.ts new file mode 100644 index 00000000000000..42fc1473c7d2e8 --- /dev/null +++ b/lib/util/http/auth.spec.ts @@ -0,0 +1,108 @@ +import { getName } from '../../../test/util'; +import { removeAuthorization } from './auth'; + +describe(getName(__filename), () => { + it('removeAuthorization no authorization', () => { + const opts = { + hostname: 'amazon.com', + href: 'https://amazon.com', + search: 'something X-Amz-Algorithm something', + }; + + removeAuthorization(opts); + + expect(opts).toEqual({ + hostname: 'amazon.com', + href: 'https://amazon.com', + search: 'something X-Amz-Algorithm something', + }); + }); + + it('removeAuthorization Amazon', () => { + const opts = { + auth: 'auth', + headers: { + authorization: 'auth', + }, + hostname: 'amazon.com', + href: 'https://amazon.com', + search: 'something X-Amz-Algorithm something', + }; + + removeAuthorization(opts); + + expect(opts).toEqual({ + headers: {}, + hostname: 'amazon.com', + href: 'https://amazon.com', + search: 'something X-Amz-Algorithm something', + }); + }); + + it('removeAuthorization Amazon ports', () => { + const opts = { + auth: 'auth', + headers: { + authorization: 'auth', + }, + hostname: 'amazon.com', + href: 'https://amazon.com', + port: 3000, + search: 'something X-Amz-Algorithm something', + }; + + removeAuthorization(opts); + + expect(opts).toEqual({ + headers: {}, + hostname: 'amazon.com', + href: 'https://amazon.com', + search: 'something X-Amz-Algorithm something', + }); + }); + + it('removeAuthorization Azure blob', () => { + const opts = { + auth: 'auth', + headers: { + authorization: 'auth', + }, + hostname: 'store123.blob.core.windows.net', + href: + 'https://.blob.core.windows.net///docker/registry/v2/blobs', + }; + + removeAuthorization(opts); + + expect(opts).toEqual({ + headers: {}, + hostname: 'store123.blob.core.windows.net', + href: + 'https://.blob.core.windows.net///docker/registry/v2/blobs', + }); + }); + + it('removeAuthorization keep auth', () => { + const opts = { + auth: 'auth', + headers: { + authorization: 'auth', + }, + hostname: 'renovate.com', + href: 'https://renovate.com', + search: 'something', + }; + + removeAuthorization(opts); + + expect(opts).toEqual({ + auth: 'auth', + headers: { + authorization: 'auth', + }, + hostname: 'renovate.com', + href: 'https://renovate.com', + search: 'something', + }); + }); +}); diff --git a/lib/util/http/auth.ts b/lib/util/http/auth.ts index f9bdc50e1e3950..31d3f523579fa2 100644 --- a/lib/util/http/auth.ts +++ b/lib/util/http/auth.ts @@ -24,3 +24,39 @@ export function applyAuthorization(inOptions: any): any { } return options; } + +// isAmazon return true if request options contains Amazon related headers +function isAmazon(options: any): boolean { + return options.search?.includes('X-Amz-Algorithm'); +} + +// isAzureBlob return true if request options contains Azure container registry related data +function isAzureBlob(options: any): boolean { + return ( + options.hostname?.endsWith('.blob.core.windows.net') && // lgtm [js/incomplete-url-substring-sanitization] + options.href?.includes('/docker/registry') + ); +} + +// removeAuthorization from the redirect options +export function removeAuthorization(options: any): void { + if (!options.auth && !options.headers?.authorization) { + return; + } + + // Check if request has been redirected to Amazon or an Azure blob (ACR) + if (isAmazon(options) || isAzureBlob(options)) { + // if there is no port in the redirect URL string, then delete it from the redirect options. + // This can be evaluated for removal after upgrading to Got v10 + const portInUrl = options.href.split('/')[2].split(':')[1]; + if (!portInUrl) { + // eslint-disable-next-line no-param-reassign + delete options.port; // Redirect will instead use 80 or 443 for HTTP or HTTPS respectively + } + + // registry is hosted on Amazon or Azure blob, redirect url includes + // authentication which is not required and should be removed + delete options.headers.authorization; // eslint-disable-line no-param-reassign + delete options.auth; // eslint-disable-line no-param-reassign + } +} diff --git a/lib/util/http/index.ts b/lib/util/http/index.ts index c140432f724c77..78a57d43e088e3 100644 --- a/lib/util/http/index.ts +++ b/lib/util/http/index.ts @@ -4,7 +4,7 @@ import got from 'got'; import { ExternalHostError } from '../../types/errors/external-host-error'; import * as memCache from '../cache/memory'; import { clone } from '../clone'; -import { applyAuthorization } from './auth'; +import { applyAuthorization, removeAuthorization } from './auth'; import { applyHostRules } from './host-rules'; interface OutgoingHttpHeaders { @@ -79,24 +79,7 @@ export class Http { options.retry = 0; } options.hooks = { - beforeRedirect: [ - (opts: any): void => { - // Check if request has been redirected to Amazon - if (opts.search?.includes('X-Amz-Algorithm')) { - // if there is no port in the redirect URL string, then delete it from the redirect options. - // This can be evaluated for removal after upgrading to Got v10 - const portInUrl = opts.href.split('/')[2].split(':')[1]; - if (!portInUrl) { - // eslint-disable-next-line no-param-reassign - delete opts.port; // Redirect will instead use 80 or 443 for HTTP or HTTPS respectively - } - - // registry is hosted on amazon, redirect url includes authentication. - delete opts.headers.authorization; // eslint-disable-line no-param-reassign - delete opts.auth; // eslint-disable-line no-param-reassign - } - }, - ], + beforeRedirect: [removeAuthorization], }; options.headers = { ...options.headers,