From b923310580e7f488aa55ddda5c7bea788309e381 Mon Sep 17 00:00:00 2001 From: Robin Appelman Date: Sun, 29 Jan 2023 15:54:39 +0100 Subject: [PATCH] add option to disable db user creation trough environment variable Signed-off-by: Robin Appelman --- lib/private/Setup/AbstractDatabase.php | 6 +++ lib/private/Setup/MySQL.php | 17 +++--- lib/private/Setup/PostgreSQL.php | 74 +++++++++++++------------- 3 files changed, 53 insertions(+), 44 deletions(-) diff --git a/lib/private/Setup/AbstractDatabase.php b/lib/private/Setup/AbstractDatabase.php index 94719a742e2..9ec4137cdef 100644 --- a/lib/private/Setup/AbstractDatabase.php +++ b/lib/private/Setup/AbstractDatabase.php @@ -57,6 +57,8 @@ abstract class AbstractDatabase { protected $logger; /** @var ISecureRandom */ protected $random; + /** @var bool */ + protected $tryCreateDbUser; public function __construct(IL10N $trans, SystemConfig $config, LoggerInterface $logger, ISecureRandom $random) { $this->trans = $trans; @@ -88,6 +90,10 @@ abstract class AbstractDatabase { $dbPort = !empty($config['dbport']) ? $config['dbport'] : ''; $dbTablePrefix = isset($config['dbtableprefix']) ? $config['dbtableprefix'] : 'oc_'; + $createUserConfig = $this->config->getValue("setup_create_db_user", true); + // accept `false` both as bool and string, since setting config values from env will result in a string + $this->tryCreateDbUser = $createUserConfig !== false && $createUserConfig !== "false"; + $this->config->setValues([ 'dbname' => $dbName, 'dbhost' => $dbHost, diff --git a/lib/private/Setup/MySQL.php b/lib/private/Setup/MySQL.php index caa73edccec..50f566728a9 100644 --- a/lib/private/Setup/MySQL.php +++ b/lib/private/Setup/MySQL.php @@ -49,7 +49,14 @@ class MySQL extends AbstractDatabase { $connection = $this->connect(['dbname' => null]); } - $this->createSpecificUser($username, new ConnectionAdapter($connection)); + if ($this->tryCreateDbUser) { + $this->createSpecificUser($username, new ConnectionAdapter($connection)); + } + + $this->config->setValues([ + 'dbuser' => $this->dbUser, + 'dbpassword' => $this->dbPassword, + ]); //create the database $this->createDatabase($connection); @@ -147,8 +154,7 @@ class MySQL extends AbstractDatabase { . $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->random->generate(2, $saveSymbols); $this->dbPassword = str_shuffle($password); try { @@ -196,10 +202,5 @@ class MySQL extends AbstractDatabase { $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 af816c7ad04..8359f7b7563 100644 --- a/lib/private/Setup/PostgreSQL.php +++ b/lib/private/Setup/PostgreSQL.php @@ -45,42 +45,44 @@ class PostgreSQL extends AbstractDatabase { $connection = $this->connect([ 'dbname' => 'postgres' ]); - //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(); + 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([ -- 2.39.5