From dd96b7d8b4791474e9a14ce1947db1b0d75e8dbc Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Tue, 21 Mar 2023 17:34:23 +0100 Subject: [PATCH] nextcloud26, nixos/web-apps/nextcloud: drop the autocreate db user patch and wire the default in the NixOS module --- nixos/modules/services/web-apps/nextcloud.nix | 3 + pkgs/servers/nextcloud/default.nix | 3 +- ...move-custom-dbuser-creation-behavior.patch | 157 ------------------ 3 files changed, 5 insertions(+), 158 deletions(-) delete mode 100644 pkgs/servers/nextcloud/patches/v26/0001-Setup-remove-custom-dbuser-creation-behavior.patch diff --git a/nixos/modules/services/web-apps/nextcloud.nix b/nixos/modules/services/web-apps/nextcloud.nix index 02d47749a1c0..4bc6f8fe8525 100644 --- a/nixos/modules/services/web-apps/nextcloud.nix +++ b/nixos/modules/services/web-apps/nextcloud.nix @@ -982,6 +982,9 @@ in { ''; serviceConfig.Type = "oneshot"; serviceConfig.User = "nextcloud"; + # On Nextcloud ≥ 26, it is not necessary to patch the database files to prevent + # an automatic creation of the database user. + environment.NC_setup_create_db_user = lib.mkIf (nextcloudGreaterOrEqualThan "26") "false"; }; nextcloud-cron = { after = [ "nextcloud-setup.service" ]; diff --git a/pkgs/servers/nextcloud/default.nix b/pkgs/servers/nextcloud/default.nix index fabf4864be2d..c70f7f678932 100644 --- a/pkgs/servers/nextcloud/default.nix +++ b/pkgs/servers/nextcloud/default.nix @@ -15,7 +15,8 @@ let inherit sha256; }; - patches = [ (./patches + "/v${major}/0001-Setup-remove-custom-dbuser-creation-behavior.patch") ]; + # This patch is only necessary for NC version <26. + patches = lib.optional (lib.versionOlder major "26") (./patches + "/v${major}/0001-Setup-remove-custom-dbuser-creation-behavior.patch"); passthru.tests = nixosTests.nextcloud; diff --git a/pkgs/servers/nextcloud/patches/v26/0001-Setup-remove-custom-dbuser-creation-behavior.patch b/pkgs/servers/nextcloud/patches/v26/0001-Setup-remove-custom-dbuser-creation-behavior.patch deleted file mode 100644 index 63177d3162f7..000000000000 --- a/pkgs/servers/nextcloud/patches/v26/0001-Setup-remove-custom-dbuser-creation-behavior.patch +++ /dev/null @@ -1,157 +0,0 @@ -From 2e32658e52e196ef2e3ef671606da9131f0079d9 Mon Sep 17 00:00:00 2001 -From: Raito Bezarius -Date: Tue, 21 Mar 2023 16:38:29 +0100 -Subject: [PATCH] Setup: remove custom dbuser creation behavior - -Both PostgreSQL and MySQL can be authenticated against from Nextcloud by -supplying a database password. Now, during setup the following things -happen: - -* When using postgres and the db user has elevated permissions, a new - unprivileged db user is created and the settings `dbuser`/`dbpass` are - altered in `config.php`. - -* When using MySQL, the password is **always** regenerated since - 24.0.5/23.0.9[1]. - -I consider both cases problematic: the reason why people do configuration -management is to have it as single source of truth! So, IMHO any -application that silently alters config and thus causes deployed -nodes to diverge from the configuration is harmful for that. - -I guess it was sheer luck that it worked for so long in NixOS because -nobody has apparently used password authentication with a privileged -user to operate Nextcloud (which is a good thing in fact). - -[1] https://github.com/nextcloud/server/pull/33513 - -Original-Author: Maximilian Bosch ---- - lib/private/Setup/MySQL.php | 61 +++----------------------------- - lib/private/Setup/PostgreSQL.php | 39 -------------------- - 2 files changed, 4 insertions(+), 96 deletions(-) - -diff --git a/lib/private/Setup/MySQL.php b/lib/private/Setup/MySQL.php -index 50f566728a9..ce721415e30 100644 ---- a/lib/private/Setup/MySQL.php -+++ b/lib/private/Setup/MySQL.php -@@ -145,62 +145,9 @@ class MySQL extends AbstractDatabase { - * @param IDBConnection $connection - */ - private function createSpecificUser($username, $connection): void { -- $rootUser = $this->dbUser; -- $rootPassword = $this->dbPassword; -- -- //create a random password so we don't need to store the admin password in the config file -- $saveSymbols = str_replace(['\"', '\\', '\'', '`'], '', ISecureRandom::CHAR_SYMBOLS); -- $password = $this->random->generate(22, ISecureRandom::CHAR_ALPHANUMERIC . $saveSymbols) -- . $this->random->generate(2, ISecureRandom::CHAR_UPPER) -- . $this->random->generate(2, ISecureRandom::CHAR_LOWER) -- . $this->random->generate(2, ISecureRandom::CHAR_DIGITS) -- . $this->random->generate(2, $saveSymbols); -- $this->dbPassword = str_shuffle($password); -- -- try { -- //user already specified in config -- $oldUser = $this->config->getValue('dbuser', false); -- -- //we don't have a dbuser specified in config -- if ($this->dbUser !== $oldUser) { -- //add prefix to the admin username to prevent collisions -- $adminUser = substr('oc_' . $username, 0, 16); -- -- $i = 1; -- while (true) { -- //this should be enough to check for admin rights in mysql -- $query = 'SELECT user FROM mysql.user WHERE user=?'; -- $result = $connection->executeQuery($query, [$adminUser]); -- -- //current dbuser has admin rights -- $data = $result->fetchAll(); -- $result->closeCursor(); -- //new dbuser does not exist -- if (count($data) === 0) { -- //use the admin login data for the new database user -- $this->dbUser = $adminUser; -- $this->createDBUser($connection); -- -- break; -- } else { -- //repeat with different username -- $length = strlen((string)$i); -- $adminUser = substr('oc_' . $username, 0, 16 - $length) . $i; -- $i++; -- } -- } -- } else { -- // Reuse existing password if a database config is already present -- $this->dbPassword = $rootPassword; -- } -- } catch (\Exception $ex) { -- $this->logger->info('Can not create a new MySQL user, will continue with the provided user.', [ -- 'exception' => $ex, -- 'app' => 'mysql.setup', -- ]); -- // Restore the original credentials -- $this->dbUser = $rootUser; -- $this->dbPassword = $rootPassword; -- } -+ $this->config->setValues([ -+ 'dbuser' => $this->dbUser, -+ 'dbpassword' => $this->dbPassword, -+ ]); - } - } -diff --git a/lib/private/Setup/PostgreSQL.php b/lib/private/Setup/PostgreSQL.php -index 490cbba69a9..48e7f24f260 100644 ---- a/lib/private/Setup/PostgreSQL.php -+++ b/lib/private/Setup/PostgreSQL.php -@@ -45,45 +45,6 @@ class PostgreSQL extends AbstractDatabase { - $connection = $this->connect([ - 'dbname' => 'postgres' - ]); -- if ($this->tryCreateDbUser) { -- //check for roles creation rights in postgresql -- $builder = $connection->getQueryBuilder(); -- $builder->automaticTablePrefix(false); -- $query = $builder -- ->select('rolname') -- ->from('pg_roles') -- ->where($builder->expr()->eq('rolcreaterole', new Literal('TRUE'))) -- ->andWhere($builder->expr()->eq('rolname', $builder->createNamedParameter($this->dbUser))); -- -- try { -- $result = $query->execute(); -- $canCreateRoles = $result->rowCount() > 0; -- } catch (DatabaseException $e) { -- $canCreateRoles = false; -- } -- -- if ($canCreateRoles) { -- $connectionMainDatabase = $this->connect(); -- //use the admin login data for the new database user -- -- //add prefix to the postgresql user name to prevent collisions -- $this->dbUser = 'oc_' . strtolower($username); -- //create a new password so we don't need to store the admin config in the config file -- $this->dbPassword = \OC::$server->getSecureRandom()->generate(30, ISecureRandom::CHAR_ALPHANUMERIC); -- -- $this->createDBUser($connection); -- -- // Go to the main database and grant create on the public schema -- // The code below is implemented to make installing possible with PostgreSQL version 15: -- // https://www.postgresql.org/docs/release/15.0/ -- // From the release notes: For new databases having no need to defend against insider threats, granting CREATE permission will yield the behavior of prior releases -- // Therefore we assume that the database is only used by one user/service which is Nextcloud -- // Additional services should get installed in a separate database in order to stay secure -- // Also see https://www.postgresql.org/docs/15/ddl-schemas.html#DDL-SCHEMAS-PATTERNS -- $connectionMainDatabase->executeQuery('GRANT CREATE ON SCHEMA public TO "' . addslashes($this->dbUser) . '"'); -- $connectionMainDatabase->close(); -- } -- } - - $this->config->setValues([ - 'dbuser' => $this->dbUser, --- -2.39.2 -