diff options
author | Simon Rettberg | 2020-11-16 14:03:21 +0100 |
---|---|---|
committer | Simon Rettberg | 2020-11-16 14:03:21 +0100 |
commit | 11c488215620d12c1f79fc9b05deb9928d2cab39 (patch) | |
tree | d6d546f5c1729325482976587a232e1e7a0378fc /modules-available/sysconfig/inc | |
parent | [statistics] Honor filters for clients with special mode (diff) | |
download | slx-admin-11c488215620d12c1f79fc9b05deb9928d2cab39.tar.gz slx-admin-11c488215620d12c1f79fc9b05deb9928d2cab39.tar.xz slx-admin-11c488215620d12c1f79fc9b05deb9928d2cab39.zip |
[sysconfig] SSH: Split pubkey and rest of config, add more options
Now we can have exactly one SSH-Config per sysconfig, which avoids
confusion due to config mismatch regarding "allow pw" and "port".
The install include takes care of splitting the key into a new module
for existing modules, but doesn't remove duplicate SshConfig modules
from sysconfigs, as this might lead to additional confusion. Next time
the user edits a sysconfig, they are forced to pick exactly one
SshConfig module.
The "allow password login" option was extended to allow password login
for non-root users only in addition to simply being "yes" or "no".
There's an additional option that can entirely limit the group of users
allowed to log in via SSH.
Diffstat (limited to 'modules-available/sysconfig/inc')
4 files changed, 95 insertions, 19 deletions
diff --git a/modules-available/sysconfig/inc/configmodule.inc.php b/modules-available/sysconfig/inc/configmodule.inc.php index a9035d78..f3906378 100644 --- a/modules-available/sysconfig/inc/configmodule.inc.php +++ b/modules-available/sysconfig/inc/configmodule.inc.php @@ -321,23 +321,25 @@ abstract class ConfigModule * * @return boolean true on success, false otherwise */ - public final function update($title) + public final function update($title = '') { if ($this->moduleId === 0) Util::traceError('ConfigModule::update called when moduleId == 0'); - if (empty($title)) - $title = $this->moduleTitle; + if (!empty($title)) { + $this->moduleTitle = $title; + } if (!$this->validateConfig()) return false; // Update Database::exec("UPDATE configtgz_module SET title = :title, contents = :contents, status = :status, dateline = :now " . " WHERE moduleid = :moduleid LIMIT 1", array( 'moduleid' => $this->moduleId, - 'title' => $title, + 'title' => $this->moduleTitle, 'contents' => json_encode($this->moduleData), 'status' => 'OUTDATED', 'now' => time(), )); + $this->moduleStatus = 'OUTDATED'; return true; } diff --git a/modules-available/sysconfig/inc/configmodule/sshconfig.inc.php b/modules-available/sysconfig/inc/configmodule/sshconfig.inc.php index 9975f789..b5ab20e4 100644 --- a/modules-available/sysconfig/inc/configmodule/sshconfig.inc.php +++ b/modules-available/sysconfig/inc/configmodule/sshconfig.inc.php @@ -5,7 +5,7 @@ ConfigModule::registerModule( Dictionary::translateFileModule('sysconfig', 'config-module', 'sshconfig_title'), // Title Dictionary::translateFileModule('sysconfig', 'config-module', 'sshconfig_description'), // Description Dictionary::translateFileModule('sysconfig', 'config-module', 'group_sshconfig'), // Group - false, // Only one per config? + true, // Only one per config? 500 ); @@ -23,7 +23,6 @@ class ConfigModule_SshConfig extends ConfigModule 'failOnParentFail' => false, 'parent' => $parent ); - // Create config module, which will also check if the pubkey is valid return Taskmanager::submit('SshdConfigGenerator', $config); } @@ -34,25 +33,40 @@ class ConfigModule_SshConfig extends ConfigModule protected function validateConfig() { - return isset($this->moduleData['publicKey']) && isset($this->moduleData['allowPasswordLogin']) && isset($this->moduleData['listenPort']); + // UPGRADE + if (isset($this->moduleData['allowPasswordLogin']) && !isset($this->moduleData['allowedUsersLogin'])) { + $this->moduleData['allowPasswordLogin'] = strtoupper($this->moduleData['allowPasswordLogin']); + if (!in_array($this->moduleData['allowPasswordLogin'], ['NO', 'USER_ONLY', 'YES'])) { + $this->moduleData['allowPasswordLogin'] = 'NO'; + } + $this->moduleData['allowedUsersLogin'] = 'ALL'; + } + return isset($this->moduleData['allowPasswordLogin']) && isset($this->moduleData['allowedUsersLogin']) + && isset($this->moduleData['listenPort']); } public function setData($key, $value) { switch ($key) { case 'publicKey': - break; + if ($value === false) { + error_log('Unsetting publicKey'); + unset($this->moduleData[$key]); + return true; + } + return false; case 'allowPasswordLogin': - if ($value === true || $value === 'yes') - $value = 'yes'; - elseif ($value === false || $value === 'no') - $value = 'no'; - else + if (!in_array($value, ['NO', 'USER_ONLY', 'YES'])) + return false; + break; + case 'allowedUsersLogin'; + if (!in_array($value, ['ROOT_ONLY', 'USER_ONLY', 'ALL'])) return false; break; case 'listenPort': if (!is_numeric($value) || $value < 1 || $value > 65535) return false; + $value = (int)$value; break; default: return false; diff --git a/modules-available/sysconfig/inc/configmodule/sshkey.inc.php b/modules-available/sysconfig/inc/configmodule/sshkey.inc.php new file mode 100644 index 00000000..2d212d25 --- /dev/null +++ b/modules-available/sysconfig/inc/configmodule/sshkey.inc.php @@ -0,0 +1,55 @@ +<?php + +ConfigModule::registerModule( + ConfigModule_SshKey::MODID, // ID + Dictionary::translateFileModule('sysconfig', 'config-module', 'sshkey_title'), // Title + Dictionary::translateFileModule('sysconfig', 'config-module', 'sshkey_description'), // Description + Dictionary::translateFileModule('sysconfig', 'config-module', 'group_sshkey'), // Group + false, // Only one per config? + 510 +); + +class ConfigModule_SshKey extends ConfigModule +{ + const MODID = 'SshKey'; + const VERSION = 1; + + protected function generateInternal($tgz, $parent) + { + if (!$this->validateConfig()) + return false; + $config = array( + 'files' => [ + '/root/.ssh/authorized_keys.d/sshkey_' . $this->id() . '_' . Util::sanitizeFilename($this->title()) . '.pub' + => $this->moduleData['publicKey']], + 'destination' => $tgz, + 'failOnParentFail' => false, + 'parent' => $parent + ); + // Create config module, which will also check if the pubkey is valid + return Taskmanager::submit('MakeTarball', $config); + } + + protected function moduleVersion() + { + return self::VERSION; + } + + protected function validateConfig() + { + return isset($this->moduleData['publicKey']); + } + + public function setData($key, $value) + { + switch ($key) { + case 'publicKey': + break; + default: + return false; + } + $this->moduleData[$key] = $value; + return true; + } + +} diff --git a/modules-available/sysconfig/inc/configtgz.inc.php b/modules-available/sysconfig/inc/configtgz.inc.php index ff9e306d..98f29753 100644 --- a/modules-available/sysconfig/inc/configtgz.inc.php +++ b/modules-available/sysconfig/inc/configtgz.inc.php @@ -56,7 +56,9 @@ class ConfigTgz { if (!is_array($moduleIds)) return false; - $this->configTitle = $title; + if (!empty($title)) { + $this->configTitle = $title; + } $this->modules = array(); // Get all modules to put in config $idstr = '0'; // Passed directly in query. Make sure no SQL injection is possible @@ -77,7 +79,7 @@ class ConfigTgz // Update name Database::exec("UPDATE configtgz SET title = :title, status = :status, dateline = :now WHERE configid = :configid LIMIT 1", array( 'configid' => $this->configId, - 'title' => $title, + 'title' => $this->configTitle, 'status' => 'OUTDATED', 'now' => time(), )); @@ -88,9 +90,10 @@ class ConfigTgz * * @param bool $deleteOnError * @param int $timeoutMs + * @param string|null $parentTask parent task to order this rebuild after * @return string|bool true=success, false=error, string=taskid, still running */ - public function generate($deleteOnError = false, $timeoutMs = 0) + public function generate($deleteOnError = false, $timeoutMs = 0, $parentTask = null) { if (!($this->configId > 0) || !is_array($this->modules) || $this->file === false) Util::traceError ('configId <= 0 or modules not array in ConfigTgz::rebuild()'); @@ -103,7 +106,7 @@ class ConfigTgz } } - $task = self::recompress($files, $this->file); + $task = self::recompress($files, $this->file, $parentTask); // Wait for completion if ($timeoutMs > 0 && !Taskmanager::isFailed($task) && !Taskmanager::isFinished($task)) { @@ -215,7 +218,7 @@ class ConfigTgz * @param string $destFile where to store final result * @return false|array taskmanager task */ - private static function recompress($files, $destFile) + private static function recompress($files, $destFile, $parentTask = null) { // Get stuff other modules want to inject $handler = function($hook) { @@ -232,7 +235,9 @@ class ConfigTgz // Hand over to tm return Taskmanager::submit('RecompressArchive', array( 'inputFiles' => $files, - 'outputFile' =>$destFile + 'outputFile' =>$destFile, + 'parentTask' => $parentTask, + 'failOnParentFail' => false, )); } |