From f3ef1739d5bb04c579d379d8baba68245eaee2ef Mon Sep 17 00:00:00 2001 From: Aleksandr Mezin Date: Sat, 20 Jul 2024 14:16:01 +0300 Subject: [PATCH] fix(git/auth): fix `insteadOf` for bitbucket-server (#29951) --- lib/util/git/auth.spec.ts | 41 +++++++++++++++++++++++++++++++++++++++ lib/util/git/auth.ts | 25 +++++++++++++++++++++--- 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/lib/util/git/auth.spec.ts b/lib/util/git/auth.spec.ts index d7e0d8b2d4..7d9b4a5068 100644 --- a/lib/util/git/auth.spec.ts +++ b/lib/util/git/auth.spec.ts @@ -350,6 +350,27 @@ describe('util/git/auth', () => { GIT_CONFIG_VALUE_2: 'https://github.com:89/org/repo.git', }); }); + + it('returns url with token for bitbucket-server', () => { + expect( + getGitAuthenticatedEnvironmentVariables('https://git.mycompany.com/', { + token: 'token1234', + hostType: 'bitbucket-server', + matchHost: 'git.mycompany.com', + }), + ).toStrictEqual({ + GIT_CONFIG_COUNT: '3', + GIT_CONFIG_KEY_0: + 'url.https://ssh:token1234@git.mycompany.com/scm/.insteadOf', + GIT_CONFIG_KEY_1: + 'url.https://git:token1234@git.mycompany.com/scm/.insteadOf', + GIT_CONFIG_KEY_2: + 'url.https://token1234@git.mycompany.com/scm/.insteadOf', + GIT_CONFIG_VALUE_0: 'ssh://git@git.mycompany.com:7999/', + GIT_CONFIG_VALUE_1: 'ssh://git@git.mycompany.com:7999/', + GIT_CONFIG_VALUE_2: 'https://git.mycompany.com/scm/', + }); + }); }); describe('getGitEnvironmentVariables()', () => { @@ -538,5 +559,25 @@ describe('util/git/auth', () => { }); expect(getGitEnvironmentVariables(['custom'])).toStrictEqual({}); }); + + it('returns environment variables for bitbucket-server', () => { + add({ + hostType: 'bitbucket-server', + matchHost: 'git.mycompany.com', + token: 'token123', + }); + expect(getGitEnvironmentVariables()).toStrictEqual({ + GIT_CONFIG_COUNT: '3', + GIT_CONFIG_KEY_0: + 'url.https://ssh:token123@git.mycompany.com/scm/.insteadOf', + GIT_CONFIG_KEY_1: + 'url.https://git:token123@git.mycompany.com/scm/.insteadOf', + GIT_CONFIG_KEY_2: + 'url.https://token123@git.mycompany.com/scm/.insteadOf', + GIT_CONFIG_VALUE_0: 'ssh://git@git.mycompany.com:7999/', + GIT_CONFIG_VALUE_1: 'ssh://git@git.mycompany.com:7999/', + GIT_CONFIG_VALUE_2: 'https://git.mycompany.com/scm/', + }); + }); }); }); diff --git a/lib/util/git/auth.ts b/lib/util/git/auth.ts index c776b3c483..9bbffcbc4c 100644 --- a/lib/util/git/auth.ts +++ b/lib/util/git/auth.ts @@ -71,6 +71,7 @@ export function getGitAuthenticatedEnvironmentVariables( authenticationRules = getAuthenticationRules( originalGitUrl, + hostType, `${encodedUsername}:${encodedPassword}`, ); } @@ -106,20 +107,38 @@ function getAuthenticationRulesWithToken( if (type === 'gitlab') { token = `gitlab-ci-token:${authToken}`; } - return getAuthenticationRules(url, token); + return getAuthenticationRules(url, type, token); } /** * Generates the authentication rules for later git usage for the given host * @link https://coolaj86.com/articles/vanilla-devops-git-credentials-cheatsheet/ + * @param gitUrl Git repository URL + * @param hostType Git host type + * @param token Authentication token or `username:password` string */ export function getAuthenticationRules( gitUrl: string, + hostType: string | undefined | null, token: string, ): AuthenticationRule[] { const authenticationRules = []; const hasUser = token.split(':').length > 1; const insteadUrl = parseGitUrl(gitUrl); + let sshPort = insteadUrl.port; + + if (hostType === 'bitbucket-server') { + // For Bitbucket Server/Data Center, `source` must be `bitbucket-server` + // to generate HTTP(s) URLs correctly. + // https://github.com/IonicaBizau/git-url-parse/blob/28828546c148d58bbcff61409915a4e1e8f7eb11/lib/index.js#L304 + insteadUrl.source = 'bitbucket-server'; + + if (!sshPort) { + // By default, bitbucket-server SSH port is 7999. + // For non-default port, the generated auth config will likely be incorrect. + sshPort = 7999; + } + } const url = { ...insteadUrl }; const protocol = regEx(/^https?$/).test(url.protocol) @@ -133,7 +152,7 @@ export function getAuthenticationRules( // only edge case, need to stringify ourself because the exact syntax is not supported by the library // https://github.com/IonicaBizau/git-url-parse/blob/246c9119fb42c2ea1c280028fe77c53eb34c190c/lib/index.js#L246 insteadOf: `ssh://git@${insteadUrl.resource}${ - insteadUrl.port ? `:${insteadUrl.port}` : '' + sshPort ? `:${sshPort}` : '' }/${insteadUrl.full_name}${insteadUrl.git_suffix ? '.git' : ''}`, }); @@ -141,7 +160,7 @@ export function getAuthenticationRules( url.token = hasUser ? token : `git:${token}`; authenticationRules.push({ url: url.toString(protocol), - insteadOf: insteadUrl.toString('ssh'), + insteadOf: { ...insteadUrl, port: sshPort }.toString('ssh'), }); // https protocol with no user as default fallback