fix(git-import): ensure ssh key is used for fetch, submodule, and lfs operations (#8933)
This commit is contained in:
commit
4f1fe824e5
2 changed files with 73 additions and 9 deletions
|
|
@ -1087,12 +1087,16 @@ public function dirOnServer()
|
||||||
return application_configuration_dir()."/{$this->uuid}";
|
return application_configuration_dir()."/{$this->uuid}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setGitImportSettings(string $deployment_uuid, string $git_clone_command, bool $public = false, ?string $commit = null)
|
public function setGitImportSettings(string $deployment_uuid, string $git_clone_command, bool $public = false, ?string $commit = null, ?string $git_ssh_command = null)
|
||||||
{
|
{
|
||||||
$baseDir = $this->generateBaseDir($deployment_uuid);
|
$baseDir = $this->generateBaseDir($deployment_uuid);
|
||||||
$escapedBaseDir = escapeshellarg($baseDir);
|
$escapedBaseDir = escapeshellarg($baseDir);
|
||||||
$isShallowCloneEnabled = $this->settings?->is_git_shallow_clone_enabled ?? false;
|
$isShallowCloneEnabled = $this->settings?->is_git_shallow_clone_enabled ?? false;
|
||||||
|
|
||||||
|
// Use the full GIT_SSH_COMMAND (including -i for SSH key and port options) when provided,
|
||||||
|
// so that git fetch, submodule update, and lfs pull can authenticate the same way as git clone.
|
||||||
|
$sshCommand = $git_ssh_command ?? 'GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"';
|
||||||
|
|
||||||
// Use the explicitly passed commit (e.g. from rollback), falling back to the application's git_commit_sha.
|
// Use the explicitly passed commit (e.g. from rollback), falling back to the application's git_commit_sha.
|
||||||
// Invalid refs will cause the git checkout/fetch command to fail on the remote server.
|
// Invalid refs will cause the git checkout/fetch command to fail on the remote server.
|
||||||
$commitToUse = $commit ?? $this->git_commit_sha;
|
$commitToUse = $commit ?? $this->git_commit_sha;
|
||||||
|
|
@ -1102,9 +1106,9 @@ public function setGitImportSettings(string $deployment_uuid, string $git_clone_
|
||||||
// If shallow clone is enabled and we need a specific commit,
|
// If shallow clone is enabled and we need a specific commit,
|
||||||
// we need to fetch that specific commit with depth=1
|
// we need to fetch that specific commit with depth=1
|
||||||
if ($isShallowCloneEnabled) {
|
if ($isShallowCloneEnabled) {
|
||||||
$git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && GIT_SSH_COMMAND=\"ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null\" git fetch --depth=1 origin {$escapedCommit} && git -c advice.detachedHead=false checkout {$escapedCommit} >/dev/null 2>&1";
|
$git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && {$sshCommand} git fetch --depth=1 origin {$escapedCommit} && git -c advice.detachedHead=false checkout {$escapedCommit} >/dev/null 2>&1";
|
||||||
} else {
|
} else {
|
||||||
$git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && GIT_SSH_COMMAND=\"ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null\" git -c advice.detachedHead=false checkout {$escapedCommit} >/dev/null 2>&1";
|
$git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && {$sshCommand} git -c advice.detachedHead=false checkout {$escapedCommit} >/dev/null 2>&1";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($this->settings->is_git_submodules_enabled) {
|
if ($this->settings->is_git_submodules_enabled) {
|
||||||
|
|
@ -1115,10 +1119,10 @@ public function setGitImportSettings(string $deployment_uuid, string $git_clone_
|
||||||
}
|
}
|
||||||
// Add shallow submodules flag if shallow clone is enabled
|
// Add shallow submodules flag if shallow clone is enabled
|
||||||
$submoduleFlags = $isShallowCloneEnabled ? '--depth=1' : '';
|
$submoduleFlags = $isShallowCloneEnabled ? '--depth=1' : '';
|
||||||
$git_clone_command = "{$git_clone_command} git submodule sync && GIT_SSH_COMMAND=\"ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null\" git submodule update --init --recursive {$submoduleFlags}; fi";
|
$git_clone_command = "{$git_clone_command} git submodule sync && {$sshCommand} git submodule update --init --recursive {$submoduleFlags}; fi";
|
||||||
}
|
}
|
||||||
if ($this->settings->is_git_lfs_enabled) {
|
if ($this->settings->is_git_lfs_enabled) {
|
||||||
$git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && GIT_SSH_COMMAND=\"ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null\" git lfs pull";
|
$git_clone_command = "{$git_clone_command} && cd {$escapedBaseDir} && {$sshCommand} git lfs pull";
|
||||||
}
|
}
|
||||||
|
|
||||||
return $git_clone_command;
|
return $git_clone_command;
|
||||||
|
|
@ -1407,11 +1411,12 @@ public function generateGitImportCommands(string $deployment_uuid, int $pull_req
|
||||||
$private_key = base64_encode($private_key);
|
$private_key = base64_encode($private_key);
|
||||||
$gitlabPort = $gitlabSource->custom_port ?? 22;
|
$gitlabPort = $gitlabSource->custom_port ?? 22;
|
||||||
$escapedCustomRepository = escapeshellarg($customRepository);
|
$escapedCustomRepository = escapeshellarg($customRepository);
|
||||||
$git_clone_command_base = "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$gitlabPort} -o Port={$gitlabPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" {$git_clone_command} {$escapedCustomRepository} {$escapedBaseDir}";
|
$gitlabSshCommand = "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$gitlabPort} -o Port={$gitlabPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\"";
|
||||||
|
$git_clone_command_base = "{$gitlabSshCommand} {$git_clone_command} {$escapedCustomRepository} {$escapedBaseDir}";
|
||||||
if ($only_checkout) {
|
if ($only_checkout) {
|
||||||
$git_clone_command = $git_clone_command_base;
|
$git_clone_command = $git_clone_command_base;
|
||||||
} else {
|
} else {
|
||||||
$git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command_base, commit: $commit);
|
$git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command_base, commit: $commit, git_ssh_command: $gitlabSshCommand);
|
||||||
}
|
}
|
||||||
if ($exec_in_docker) {
|
if ($exec_in_docker) {
|
||||||
$commands = collect([
|
$commands = collect([
|
||||||
|
|
@ -1477,11 +1482,12 @@ public function generateGitImportCommands(string $deployment_uuid, int $pull_req
|
||||||
}
|
}
|
||||||
$private_key = base64_encode($private_key);
|
$private_key = base64_encode($private_key);
|
||||||
$escapedCustomRepository = escapeshellarg($customRepository);
|
$escapedCustomRepository = escapeshellarg($customRepository);
|
||||||
$git_clone_command_base = "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" {$git_clone_command} {$escapedCustomRepository} {$escapedBaseDir}";
|
$deployKeySshCommand = "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\"";
|
||||||
|
$git_clone_command_base = "{$deployKeySshCommand} {$git_clone_command} {$escapedCustomRepository} {$escapedBaseDir}";
|
||||||
if ($only_checkout) {
|
if ($only_checkout) {
|
||||||
$git_clone_command = $git_clone_command_base;
|
$git_clone_command = $git_clone_command_base;
|
||||||
} else {
|
} else {
|
||||||
$git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command_base, commit: $commit);
|
$git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command_base, commit: $commit, git_ssh_command: $deployKeySshCommand);
|
||||||
}
|
}
|
||||||
if ($exec_in_docker) {
|
if ($exec_in_docker) {
|
||||||
$commands = collect([
|
$commands = collect([
|
||||||
|
|
|
||||||
|
|
@ -85,4 +85,62 @@
|
||||||
|
|
||||||
expect($result)->not->toContain('advice.detachedHead=false checkout');
|
expect($result)->not->toContain('advice.detachedHead=false checkout');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('setGitImportSettings uses provided git_ssh_command for fetch', function () {
|
||||||
|
$this->application->settings->is_git_shallow_clone_enabled = true;
|
||||||
|
$rollbackCommit = 'abc123def456abc123def456abc123def456abc1';
|
||||||
|
$sshCommand = 'GIT_SSH_COMMAND="ssh -o ConnectTimeout=30 -p 22222 -o Port=22222 -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa"';
|
||||||
|
|
||||||
|
$result = $this->application->setGitImportSettings(
|
||||||
|
deployment_uuid: 'test-uuid',
|
||||||
|
git_clone_command: 'git clone',
|
||||||
|
commit: $rollbackCommit,
|
||||||
|
git_ssh_command: $sshCommand,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect($result)
|
||||||
|
->toContain('-i /root/.ssh/id_rsa" git fetch --depth=1 origin')
|
||||||
|
->toContain($rollbackCommit);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('setGitImportSettings uses provided git_ssh_command for submodule update', function () {
|
||||||
|
$this->application->settings->is_git_submodules_enabled = true;
|
||||||
|
$sshCommand = 'GIT_SSH_COMMAND="ssh -o ConnectTimeout=30 -p 22 -o Port=22 -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa"';
|
||||||
|
|
||||||
|
$result = $this->application->setGitImportSettings(
|
||||||
|
deployment_uuid: 'test-uuid',
|
||||||
|
git_clone_command: 'git clone',
|
||||||
|
git_ssh_command: $sshCommand,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect($result)
|
||||||
|
->toContain('-i /root/.ssh/id_rsa" git submodule update --init --recursive');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('setGitImportSettings uses provided git_ssh_command for lfs pull', function () {
|
||||||
|
$this->application->settings->is_git_lfs_enabled = true;
|
||||||
|
$sshCommand = 'GIT_SSH_COMMAND="ssh -o ConnectTimeout=30 -p 22 -o Port=22 -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa"';
|
||||||
|
|
||||||
|
$result = $this->application->setGitImportSettings(
|
||||||
|
deployment_uuid: 'test-uuid',
|
||||||
|
git_clone_command: 'git clone',
|
||||||
|
git_ssh_command: $sshCommand,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect($result)->toContain('-i /root/.ssh/id_rsa" git lfs pull');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('setGitImportSettings uses default ssh command when git_ssh_command not provided', function () {
|
||||||
|
$this->application->settings->is_git_lfs_enabled = true;
|
||||||
|
|
||||||
|
$result = $this->application->setGitImportSettings(
|
||||||
|
deployment_uuid: 'test-uuid',
|
||||||
|
git_clone_command: 'git clone',
|
||||||
|
public: true,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect($result)
|
||||||
|
->toContain('GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" git lfs pull')
|
||||||
|
->not->toContain('-i /root/.ssh/id_rsa');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue