···
1
-
From e01014a745b7f4dbdde2ee0e293c25c4e5eeaabb Mon Sep 17 00:00:00 2001
2
-
From: Maximilian Bosch <maximilian@mbosch.me>
3
-
Date: Sat, 10 Sep 2022 15:18:05 +0200
4
-
Subject: [PATCH] Setup: remove custom dbuser creation behavior
6
-
Both PostgreSQL and MySQL can be authenticated against from Nextcloud by
7
-
supplying a database password. Now, during setup the following things
10
-
* When using postgres and the db user has elevated permissions, a new
11
-
unprivileged db user is created and the settings `dbuser`/`dbpass` are
12
-
altered in `config.php`.
14
-
* When using MySQL, the password is **always** regenerated since
17
-
I consider both cases problematic: the reason why people do configuration
18
-
management is to have it as single source of truth! So, IMHO any
19
-
application that silently alters config and thus causes deployed
20
-
nodes to diverge from the configuration is harmful for that.
22
-
I guess it was sheer luck that it worked for so long in NixOS because
23
-
nobody has apparently used password authentication with a privileged
24
-
user to operate Nextcloud (which is a good thing in fact).
26
-
[1] https://github.com/nextcloud/server/pull/33513
28
-
lib/private/Setup/MySQL.php | 56 --------------------------------
29
-
lib/private/Setup/PostgreSQL.php | 26 ---------------
30
-
2 files changed, 82 deletions(-)
32
-
diff --git a/lib/private/Setup/MySQL.php b/lib/private/Setup/MySQL.php
33
-
index fbce31b0f57..9b2265091f0 100644
34
-
--- a/lib/private/Setup/MySQL.php
35
-
+++ b/lib/private/Setup/MySQL.php
36
-
@@ -142,62 +142,6 @@ class MySQL extends AbstractDatabase {
37
-
$rootUser = $this->dbUser;
38
-
$rootPassword = $this->dbPassword;
40
-
- //create a random password so we don't need to store the admin password in the config file
41
-
- $saveSymbols = str_replace(['\"', '\\', '\'', '`'], '', ISecureRandom::CHAR_SYMBOLS);
42
-
- $password = $this->random->generate(22, ISecureRandom::CHAR_ALPHANUMERIC . $saveSymbols)
43
-
- . $this->random->generate(2, ISecureRandom::CHAR_UPPER)
44
-
- . $this->random->generate(2, ISecureRandom::CHAR_LOWER)
45
-
- . $this->random->generate(2, ISecureRandom::CHAR_DIGITS)
46
-
- . $this->random->generate(2, $saveSymbols)
48
-
- $this->dbPassword = str_shuffle($password);
51
-
- //user already specified in config
52
-
- $oldUser = $this->config->getValue('dbuser', false);
54
-
- //we don't have a dbuser specified in config
55
-
- if ($this->dbUser !== $oldUser) {
56
-
- //add prefix to the admin username to prevent collisions
57
-
- $adminUser = substr('oc_' . $username, 0, 16);
61
-
- //this should be enough to check for admin rights in mysql
62
-
- $query = 'SELECT user FROM mysql.user WHERE user=?';
63
-
- $result = $connection->executeQuery($query, [$adminUser]);
65
-
- //current dbuser has admin rights
66
-
- $data = $result->fetchAll();
67
-
- $result->closeCursor();
68
-
- //new dbuser does not exist
69
-
- if (count($data) === 0) {
70
-
- //use the admin login data for the new database user
71
-
- $this->dbUser = $adminUser;
72
-
- $this->createDBUser($connection);
76
-
- //repeat with different username
77
-
- $length = strlen((string)$i);
78
-
- $adminUser = substr('oc_' . $username, 0, 16 - $length) . $i;
83
-
- // Reuse existing password if a database config is already present
84
-
- $this->dbPassword = $rootPassword;
86
-
- } catch (\Exception $ex) {
87
-
- $this->logger->info('Can not create a new MySQL user, will continue with the provided user.', [
88
-
- 'exception' => $ex,
89
-
- 'app' => 'mysql.setup',
91
-
- // Restore the original credentials
92
-
- $this->dbUser = $rootUser;
93
-
- $this->dbPassword = $rootPassword;
96
-
$this->config->setValues([
97
-
'dbuser' => $this->dbUser,
98
-
'dbpassword' => $this->dbPassword,
99
-
diff --git a/lib/private/Setup/PostgreSQL.php b/lib/private/Setup/PostgreSQL.php
100
-
index bc24909dc3d..e49e5508e15 100644
101
-
--- a/lib/private/Setup/PostgreSQL.php
102
-
+++ b/lib/private/Setup/PostgreSQL.php
103
-
@@ -45,32 +45,6 @@ class PostgreSQL extends AbstractDatabase {
104
-
$connection = $this->connect([
105
-
'dbname' => 'postgres'
107
-
- //check for roles creation rights in postgresql
108
-
- $builder = $connection->getQueryBuilder();
109
-
- $builder->automaticTablePrefix(false);
110
-
- $query = $builder
111
-
- ->select('rolname')
112
-
- ->from('pg_roles')
113
-
- ->where($builder->expr()->eq('rolcreaterole', new Literal('TRUE')))
114
-
- ->andWhere($builder->expr()->eq('rolname', $builder->createNamedParameter($this->dbUser)));
117
-
- $result = $query->execute();
118
-
- $canCreateRoles = $result->rowCount() > 0;
119
-
- } catch (DatabaseException $e) {
120
-
- $canCreateRoles = false;
123
-
- if ($canCreateRoles) {
124
-
- //use the admin login data for the new database user
126
-
- //add prefix to the postgresql user name to prevent collisions
127
-
- $this->dbUser = 'oc_' . strtolower($username);
128
-
- //create a new password so we don't need to store the admin config in the config file
129
-
- $this->dbPassword = \OC::$server->getSecureRandom()->generate(30, ISecureRandom::CHAR_ALPHANUMERIC);
131
-
- $this->createDBUser($connection);
134
-
$this->config->setValues([
135
-
'dbuser' => $this->dbUser,