diff --git a/appinfo/info.xml b/appinfo/info.xml index 70ab3584..09b4607f 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -43,7 +43,7 @@ to join us in shaping a more versatile, stable, and secure app landscape. *Your insights, suggestions, and contributions are invaluable to us.* ]]> - 3.2.1 + 3.2.3 agpl Andrey Borysenko Alexander Piskun diff --git a/lib/Controller/DaemonConfigController.php b/lib/Controller/DaemonConfigController.php index e8624c9c..433a756e 100644 --- a/lib/Controller/DaemonConfigController.php +++ b/lib/Controller/DaemonConfigController.php @@ -19,6 +19,7 @@ use OCP\IConfig; use OCP\IL10N; use OCP\IRequest; +use OCP\Security\ICrypto; /** * DaemonConfig actions (for UI) @@ -33,6 +34,7 @@ public function __construct( private readonly AppAPIService $service, private readonly ExAppService $exAppService, private readonly IL10N $l10n, + private readonly ICrypto $crypto, ) { parent::__construct(Application::APP_ID, $request); } @@ -66,6 +68,9 @@ public function updateDaemonConfig(string $name, array $daemonConfigParams): Res // Restore the original password if "dummySecret123" is provided if ($haproxyPassword === 'dummySecret123') { $daemonConfigParams['deploy_config']['haproxy_password'] = $daemonConfig->getDeployConfig()['haproxy_password'] ?? ""; + } elseif (!empty($haproxyPassword)) { + // New password provided, encrypt it + $daemonConfigParams['deploy_config']['haproxy_password'] = $this->crypto->encrypt($haproxyPassword); } // Create and update DaemonConfig instance @@ -129,16 +134,22 @@ public function checkDaemonConnection(array $daemonParams): Response { $haproxyPassword = $daemonParams['deploy_config']['haproxy_password'] ?? null; if ($haproxyPassword === 'dummySecret123') { - // If the secret is "dummySecret123" we check if such record is present in DB + // For cases when the password itself is 'dummySecret123' + $daemonParams['deploy_config']['haproxy_password'] = $this->crypto->encrypt($haproxyPassword); + + // Check if such record is present in the DB $daemonConfig = $this->daemonConfigService->getDaemonConfigByName($daemonParams['name']); if ($daemonConfig !== null) { + // such Daemon config already present in the DB $haproxyPasswordDB = $daemonConfig->getDeployConfig()['haproxy_password'] ?? ""; if ($haproxyPasswordDB) { - // if there is a record in the DB and there is a password, - // then we request it from the DB instead of the “masked” one + // get password from the DB instead of the “masked” one $daemonParams['deploy_config']['haproxy_password'] = $haproxyPasswordDB; } } + } elseif (!empty($haproxyPassword)) { + // New password provided, encrypt it, as "initGuzzleClient" expects to receive encrypted password + $daemonParams['deploy_config']['haproxy_password'] = $this->crypto->encrypt($haproxyPassword); } $daemonConfig = new DaemonConfig([ diff --git a/lib/DeployActions/DockerActions.php b/lib/DeployActions/DockerActions.php index a1f33082..91c88e87 100644 --- a/lib/DeployActions/DockerActions.php +++ b/lib/DeployActions/DockerActions.php @@ -18,6 +18,7 @@ use OCP\ICertificateManager; use OCP\IConfig; use OCP\IURLGenerator; +use OCP\Security\ICrypto; use Psr\Log\LoggerInterface; class DockerActions implements IDeployActions { @@ -36,6 +37,7 @@ public function __construct( private readonly IURLGenerator $urlGenerator, private readonly AppAPICommonService $service, private readonly ExAppService $exAppService, + private readonly ICrypto $crypto, ) { } @@ -556,7 +558,8 @@ public function resolveExAppUrl( } if ($protocol == 'https' && isset($deployConfig['haproxy_password']) && $deployConfig['haproxy_password'] !== '') { // we only set haproxy auth for remote installations, when all requests come through HaProxy. - $auth = [self::APP_API_HAPROXY_USER, $deployConfig['haproxy_password']]; + $haproxyPass = $this->crypto->decrypt($deployConfig['haproxy_password']); + $auth = [self::APP_API_HAPROXY_USER, $haproxyPass]; } return sprintf('%s://%s:%s', $protocol, $exAppHost, $port); } @@ -620,7 +623,8 @@ public function initGuzzleClient(DaemonConfig $daemonConfig): void { $guzzleParams = $this->setupCerts($guzzleParams); } if (isset($daemonConfig->getDeployConfig()['haproxy_password']) && $daemonConfig->getDeployConfig()['haproxy_password'] !== '') { - $guzzleParams['auth'] = [self::APP_API_HAPROXY_USER, $daemonConfig->getDeployConfig()['haproxy_password']]; + $haproxyPass = $this->crypto->decrypt($daemonConfig->getDeployConfig()['haproxy_password']); + $guzzleParams['auth'] = [self::APP_API_HAPROXY_USER, $haproxyPass]; } $this->guzzleClient = new Client($guzzleParams); } diff --git a/lib/Migration/Version5000Date20241120135411.php b/lib/Migration/Version5000Date20241120135411.php new file mode 100644 index 00000000..820a4e65 --- /dev/null +++ b/lib/Migration/Version5000Date20241120135411.php @@ -0,0 +1,59 @@ +connection->getQueryBuilder(); + $qbSelect->select(['id', 'deploy_config']) + ->from('ex_apps_daemons') + ->where(1); + $req = $qbSelect->executeQuery(); + + while ($row = $req->fetch()) { + $deployConfig = $row['deploy_config']; + $deployConfig = json_decode($deployConfig, true); + if (!empty($deployConfig['haproxy_password'])) { + $deployConfig['haproxy_password'] = $this->crypto->encrypt($deployConfig['haproxy_password']); + $encodedDeployConfig = json_encode($deployConfig); + $qbUpdate = $this->connection->getQueryBuilder(); + $qbUpdate->update('ex_apps_daemons') + ->set('deploy_config', $qbUpdate->createNamedParameter($encodedDeployConfig)) + ->where( + $qbUpdate->expr()->eq('id', $qbUpdate->createNamedParameter($row['id'])) + ); + $qbUpdate->executeStatement(); + } + } + $req->closeCursor(); + return null; + } +} diff --git a/lib/Service/DaemonConfigService.php b/lib/Service/DaemonConfigService.php index d7938142..0938771a 100644 --- a/lib/Service/DaemonConfigService.php +++ b/lib/Service/DaemonConfigService.php @@ -10,6 +10,7 @@ use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\MultipleObjectsReturnedException; use OCP\DB\Exception; +use OCP\Security\ICrypto; use Psr\Log\LoggerInterface; /** @@ -20,6 +21,7 @@ public function __construct( private readonly LoggerInterface $logger, private readonly DaemonConfigMapper $mapper, private readonly ExAppService $exAppService, + private readonly ICrypto $crypto, ) { } @@ -38,6 +40,9 @@ public function registerDaemonConfig(array $params): ?DaemonConfig { } $params['deploy_config']['nextcloud_url'] = rtrim($params['deploy_config']['nextcloud_url'], '/'); try { + if (isset($params['deploy_config']['haproxy_password']) && $params['deploy_config']['haproxy_password'] !== '') { + $params['deploy_config']['haproxy_password'] = $this->crypto->encrypt($params['deploy_config']['haproxy_password']); + } return $this->mapper->insert(new DaemonConfig([ 'name' => $params['name'], 'display_name' => $params['display_name'],