nextcloud26, nixos/web-apps/nextcloud: drop the autocreate db user patch and wire the default in the NixOS module

This commit is contained in:
Raito Bezarius 2023-03-21 17:34:23 +01:00
parent d7a27b38a2
commit dd96b7d8b4
3 changed files with 5 additions and 158 deletions

View file

@ -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" ];

View file

@ -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;

View file

@ -1,157 +0,0 @@
From 2e32658e52e196ef2e3ef671606da9131f0079d9 Mon Sep 17 00:00:00 2001
From: Raito Bezarius <masterancpp@gmail.com>
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 <maximilian@mbosch.me>
---
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