fix(git/auth): fix insteadOf for bitbucket-server (#29951)

This commit is contained in:
Aleksandr Mezin 2024-07-20 14:16:01 +03:00 committed by GitHub
parent 702ffbc9c2
commit f3ef1739d5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 63 additions and 3 deletions

View file

@ -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/',
});
});
});
});

View file

@ -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