1
0
Fork 0

Merge pull request #10748 from glaubinix/f/gitlab-auth

GitLab: handle infinite loop during composer install
pull/10766/head
Jordi Boggiano 2022-04-29 12:07:01 +02:00 committed by GitHub
commit 1cdc43d9de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 1 deletions

View File

@ -137,6 +137,7 @@ class AuthHelper
$message = "\n".'Could not fetch '.$url.', enter your ' . $origin . ' credentials ' .($statusCode === 401 ? 'to access private repos' : 'to go over the API rate limit');
$gitLabUtil = new GitLab($this->io, $this->config, null);
$auth = null;
if ($this->io->hasAuthentication($origin)) {
$auth = $this->io->getAuthentication($origin);
if (in_array($auth['password'], array('gitlab-ci-token', 'private-token', 'oauth2'), true)) {
@ -149,6 +150,12 @@ class AuthHelper
) {
throw new TransportException('Could not authenticate against '.$origin, 401);
}
if ($auth !== null && $this->io->hasAuthentication($origin)) {
if ($auth === $this->io->getAuthentication($origin)) {
throw new TransportException("Invalid credentials for '" . $url . "', aborting.", $statusCode);
}
}
} elseif ($origin === 'bitbucket.org' || $origin === 'api.bitbucket.org') {
$askForOAuthToken = true;
$origin = 'bitbucket.org';

View File

@ -92,7 +92,14 @@ class GitLab
if (isset($token)) {
$username = is_array($token) && array_key_exists("username", $token) ? $token["username"] : $token;
$password = is_array($token) && array_key_exists("token", $token) ? $token["token"] : 'private-token';
// Composer expects the GitLab token to be stored as username and 'private-token' or 'gitlab-ci-token' to be stored as password
// Detect cases where this is reversed and resolve automatically resolve it
if (in_array($username, array('private-token', 'gitlab-ci-token', 'oauth2'), true)) {
$this->io->setAuthentication($originUrl, $password, $username);
} else {
$this->io->setAuthentication($originUrl, $username, $password);
}
return true;
}

View File

@ -12,6 +12,7 @@
namespace Composer\Test\Util;
use Composer\Downloader\TransportException;
use Composer\IO\IOInterface;
use Composer\Test\TestCase;
use Composer\Util\AuthHelper;
@ -473,6 +474,9 @@ class AuthHelperTest extends TestCase
$this->authHelper->storeAuth($origin, $storeAuth);
}
/**
* @return void
*/
public function testStoreAuthWithPromptInvalidAnswer()
{
$this->setExpectedException('RuntimeException');
@ -513,6 +517,44 @@ class AuthHelperTest extends TestCase
$this->authHelper->storeAuth($origin, $storeAuth);
}
/**
* @return void
*/
public function testPromptAuthIfNeededGitLabNoAuthChange()
{
$this->setExpectedException('Composer\Downloader\TransportException');
$origin = 'gitlab.com';
$this->io
->method('hasAuthentication')
->with($origin)
->willReturn(true);
$this->io
->method('getAuthentication')
->with($origin)
->willReturn(array(
'username' => 'gitlab-user',
'password' => 'gitlab-password',
));
$this->io
->expects($this->once())
->method('setAuthentication')
->with('gitlab.com', 'gitlab-user', 'gitlab-password');
$this->config
->method('get')
->willReturnMap(array(
array('github-domains', 0, array()),
array('gitlab-domains', 0, array('gitlab.com')),
array('gitlab-token', 0, array('gitlab.com' => array('username' => 'gitlab-user', 'token' => 'gitlab-password'))),
));
$this->authHelper->promptAuthIfNeeded('https://gitlab.com/acme/archive.zip', $origin, 404, 'GitLab requires authentication and it was not provided');
}
/**
* @param string $origin
* @param array<string, string|null> $auth