sysutils/git-backup: update the shell execution code

1. Use explicit commands here for better tracing even if it requires
   spelling out '/usr/local/bin/git' a number of times.
2. Use the functionality that the Shell class has to offer now.
3. Use -C for changing the git working directory.
4. A bit of style left and right.
This commit is contained in:
Franco Fichtner 2025-11-19 11:03:17 -05:00
parent 840714060e
commit 9f23d0fb80
2 changed files with 48 additions and 39 deletions

View file

@ -1,6 +1,6 @@
PLUGIN_NAME= git-backup
PLUGIN_VERSION= 1.1
PLUGIN_REVISION= 1
PLUGIN_REVISION= 2
PLUGIN_COMMENT= Track config changes using git
PLUGIN_DEPENDS= git
PLUGIN_MAINTAINER= ad@opnsense.org

View file

@ -1,38 +1,37 @@
<?php
/**
* Copyright (C) 2020 Deciso B.V.
/*
* Copyright (C) 2020 Deciso B.V.
* All rights reserved.
*
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
namespace OPNsense\Backup;
use OPNsense\Backup\GitSettings;
use OPNsense\Core\Backend;
use OPNsense\Core\Config;
use OPNsense\Backup\GitSettings;
use OPNsense\Core\Shell;
/**
* Class Git backup
@ -136,29 +135,35 @@ class Git extends Base implements IBackupProvider
*/
public function backup()
{
$targetdir = "/conf/backup/git";
$git = "/usr/local/bin/git";
$targetdir = '/conf/backup/git';
$mdl = new GitSettings();
if (!is_dir($targetdir)) {
mkdir($targetdir);
}
if (!is_dir('{$targetdir}/.git')) {
exec("{$git} init {$targetdir}");
Shell::run_safe('/usr/local/bin/git init %s', $targetdir);
}
// XXX: since our git backup is plain text and already contains the private key, it doesn't really matter
// to keep the same key in the git directory (we're not going to push it)
$ident_file = "{$targetdir}/identity";
$privkey = trim(str_replace("\r", "", (string)$mdl->privkey)) . "\n";
file_put_contents($ident_file, $privkey);
chmod("{$targetdir}/identity", 0600);
// When there are unprocessed config backups, flush them out.
(new Backend())->configdRun("system event config_changed");
(new Backend())->configdRun('system event config_changed');
// configure upstream
exec("cd {$targetdir} && " .
"{$git} config core.sshCommand " .
"\"ssh -i {$ident_file} -o StrictHostKeyChecking=accept-new -o PasswordAuthentication=no\"");
Shell::run_safe('/usr/local/bin/git -C %s config core.sshCommand %s', [
$targetdir, "ssh -i {$ident_file} -o StrictHostKeyChecking=accept-new -o PasswordAuthentication=no",
]);
$url = (string)$mdl->url;
$pos = strpos($url, '//');
// inject credentials in url (either username or username:password, depending on transport)
if (stripos(trim((string)$mdl->url), 'http') === 0) {
$cred = urlencode((string)$mdl->user) . ":" . urlencode((string)$mdl->password);
@ -166,13 +171,16 @@ class Git extends Base implements IBackupProvider
} else {
$url = substr($url, 0, $pos + 2) . urlencode((string)$mdl->user) . "@" . substr($url, $pos + 2);
}
exec("cd {$targetdir} && {$git} remote remove origin");
exec("cd {$targetdir} && {$git} remote add origin " . escapeshellarg($url));
$force_flag = (string)$mdl->force_push === "1" ? "--force " : "";
$pushtxt = shell_exec(
"(cd {$targetdir} && {$git} push {$force_flag}origin " . escapeshellarg("master:{$mdl->branch}") .
" && echo '__exit_ok__') 2>&1"
);
Shell::run_safe('/usr/local/bin/git -C %s remote remove origin', $targetdir);
Shell::run_safe('/usr/local/bin/git -C %s remote add origin %s', [$targetdir, $url]);
$gitfrmt = ['(/usr/local/bin/git -C %s push'];
if ($mdl->force_push->isEqual('1')) {
$gitfrmt[] = '--force';
}
$gitfrmt[] = 'origin %s && echo "__exit_ok__") 2>&1';
$pushtxt = Shell::shell_safe($gitfrmt, "master:{$mdl->branch}");
if (strpos($pushtxt, '__exit_ok__')) {
$error_type = null;
} elseif (strpos($pushtxt, 'Permission denied') || strpos($pushtxt, 'Authentication failed ')) {
@ -184,12 +192,13 @@ class Git extends Base implements IBackupProvider
} else {
$error_type = "unknown error, check log for details";
}
if (!empty($error_type)) {
syslog(LOG_ERR, "git-backup {$error_type} (" . str_replace("\n", " ", $pushtxt) . ")");
throw new \Exception($error_type);
} else {
// return filelist in git
return explode("\n", shell_exec("cd {$targetdir} && git ls-files"));
return Shell::shell_safe('/usr/local/bin/git -C %s ls-files', $targetdir, true);
}
}