fix: support generic SSH Git usernames
This commit is contained in:
parent
1e8a27b084
commit
e9bf2551ed
5 changed files with 39 additions and 9 deletions
|
|
@ -79,9 +79,9 @@ protected function canonicalManualWebhookRepository(?string $gitRepository): ?st
|
|||
|
||||
if (is_array($parts) && isset($parts['scheme'])) {
|
||||
$path = data_get($parts, 'path');
|
||||
} elseif (Str::startsWith($gitRepository, 'git@') && str_contains($gitRepository, ':')) {
|
||||
} elseif (preg_match('/^[A-Za-z0-9._-]+@[^:]+:/', $gitRepository) === 1) {
|
||||
$path = Str::after($gitRepository, ':');
|
||||
// scp-style SSH URLs embed a custom port as "git@host:2222/owner/repo".
|
||||
// scp-style SSH URLs embed a custom port as "user@host:2222/owner/repo".
|
||||
// Strip the leading numeric port segment so the path matches the webhook
|
||||
// payload's owner/repo, consistent with convertGitUrl() in shared.php.
|
||||
$path = preg_replace('#^\d+/#', '', $path) ?? $path;
|
||||
|
|
|
|||
|
|
@ -137,10 +137,8 @@ public function loadBranch()
|
|||
throw new \RuntimeException('Invalid repository URL: '.$validator->errors()->first('repository_url'));
|
||||
}
|
||||
|
||||
if (str($this->repository_url)->startsWith('git@')) {
|
||||
$github_instance = str($this->repository_url)->after('git@')->before(':');
|
||||
$repository = str($this->repository_url)->after(':')->before('.git');
|
||||
$this->repository_url = 'https://'.str($github_instance).'/'.$repository;
|
||||
if (preg_match('/^(?<user>[A-Za-z0-9._-]+)@(?<host>[^:]+):(?<repository>.+)$/', $this->repository_url, $matches) === 1) {
|
||||
$this->repository_url = 'https://'.$matches['host'].'/'.$matches['repository'];
|
||||
}
|
||||
if (
|
||||
(str($this->repository_url)->startsWith('https://') ||
|
||||
|
|
|
|||
|
|
@ -77,15 +77,15 @@ public function validate(string $attribute, mixed $value, Closure $fail): void
|
|||
}
|
||||
|
||||
// Validate based on URL type
|
||||
if (str_starts_with($value, 'git@')) {
|
||||
if (preg_match('/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+:/', $value)) {
|
||||
if (! $this->allowSSH) {
|
||||
$fail('SSH URLs are not allowed.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate SSH URL format (git@host:user/repo.git)
|
||||
if (! preg_match('/^git@[a-zA-Z0-9\.\-]+:[a-zA-Z0-9\-_\/\.~]+$/', $value)) {
|
||||
// Validate scp-style SSH URL format (user@host:user/repo.git)
|
||||
if (! preg_match('/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+:[a-zA-Z0-9\-_\/.~]+$/', $value)) {
|
||||
$fail('The :attribute is not a valid SSH repository URL.');
|
||||
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -542,6 +542,29 @@ function createApplicationWithWebhook(string $repo = 'test-org/test-repo', strin
|
|||
expect($response->getContent())->not->toContain('No applications found');
|
||||
});
|
||||
|
||||
test('github matches an ssh repository URL with a non-git username', function () {
|
||||
$app = createApplicationWithWebhook(overrides: [
|
||||
'git_repository' => 'custom-user@git.example.com:test-org/test-repo.git',
|
||||
]);
|
||||
$secret = $app->manual_webhook_secret_github;
|
||||
|
||||
$payload = json_encode([
|
||||
'ref' => 'refs/heads/main',
|
||||
'repository' => ['full_name' => 'test-org/test-repo'],
|
||||
'after' => 'abc123',
|
||||
'commits' => [],
|
||||
]);
|
||||
|
||||
$response = $this->call('POST', '/webhooks/source/github/events/manual', [], [], [], [
|
||||
'HTTP_X-GitHub-Event' => 'push',
|
||||
'HTTP_X-Hub-Signature-256' => 'sha256='.hash_hmac('sha256', $payload, $secret),
|
||||
'CONTENT_TYPE' => 'application/json',
|
||||
], $payload);
|
||||
|
||||
$response->assertOk();
|
||||
expect($response->getContent())->not->toContain('No applications found');
|
||||
});
|
||||
|
||||
test('gitlab matches scp-style ssh repository URL with custom port', function () {
|
||||
$app = createApplicationWithWebhook(overrides: [
|
||||
'git_repository' => 'git@gitlab.example.com:2222/services/xyz.git',
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@
|
|||
'git@github.com:user/repo.git',
|
||||
'git@gitlab.com:user/repo.git',
|
||||
'git@bitbucket.org:user/repo.git',
|
||||
'custom-user@git.example.com:organization/repository.git',
|
||||
];
|
||||
|
||||
foreach ($validUrls as $url) {
|
||||
|
|
@ -115,6 +116,14 @@
|
|||
}
|
||||
});
|
||||
|
||||
it('rejects non-SSH email-like repository URLs', function () {
|
||||
$rule = new ValidGitRepositoryUrl;
|
||||
|
||||
$validator = Validator::make(['url' => 'custom-user@git.example.com'], ['url' => $rule]);
|
||||
|
||||
expect($validator->fails())->toBeTrue();
|
||||
});
|
||||
|
||||
it('rejects SSH URLs when not allowed', function () {
|
||||
$rule = new ValidGitRepositoryUrl(allowSSH: false);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue