summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Dony <odo@openerp.com>2017-10-03 12:34:50 +0200
committerOlivier Dony <odo@openerp.com>2017-10-03 12:46:03 +0200
commitb02dea768814f878bffe9ff1f42304a45d3189de (patch)
treed2cddec54814240c9c1e31493450f14d2aaa4d49
parent7d16769263b9cdefadb5059c04c0fc8892353c54 (diff)
[IMP] config: allow blocking access to db manager
- The `--no-database-list` option will now also block access to database management functions and screens. Presumably this flag should only be used in production when all databases have been provisioned, so the admin should like to block access to the db manager at the same time. - If no `--database` or `-d` parameter is provided, the system will be unable to fetch a list of databases at all, so users will be blocked with an error message. - Hide the link on the login screen to the DB manager when it is disabled, to prevent sending users to an error page. - Weak attempt at updating the documentation Note: the security check for RPC methods could have been done in the RPC dispatcher, however that would not have protected service methods when called directly, e.g. by a controller (e.g. the dump method).
-rw-r--r--addons/web/controllers/main.py3
-rw-r--r--addons/web/views/database_manager.html10
-rw-r--r--doc/setup/deploy.rst29
-rw-r--r--odoo/service/db.py23
-rw-r--r--odoo/tools/config.py4
5 files changed, 55 insertions, 14 deletions
diff --git a/addons/web/controllers/main.py b/addons/web/controllers/main.py
index cc2ef4201df..17ca031a48f 100644
--- a/addons/web/controllers/main.py
+++ b/addons/web/controllers/main.py
@@ -491,6 +491,9 @@ class Home(http.Controller):
if 'login' not in values and request.session.get('auth_login'):
values['login'] = request.session.get('auth_login')
+ if not odoo.tools.config['list_db']:
+ values['disable_database_manager'] = True
+
response = request.render('web.login', values)
response.headers['X-Frame-Options'] = 'DENY'
return response
diff --git a/addons/web/views/database_manager.html b/addons/web/views/database_manager.html
index 7f0d2fc04ff..f59cca973f9 100644
--- a/addons/web/views/database_manager.html
+++ b/addons/web/views/database_manager.html
@@ -116,7 +116,11 @@
<div class="text-center">
<img src="/web/static/src/img/logo2.png" class="img-responsive center-block"/>
</div>
- {% if insecure and databases %}
+ {% if not list_db %}
+ <div class="alert alert-danger text-center">
+ The database manager has been disabled by the administrator
+ </div>
+ {% elif insecure and databases %}
<div class="alert alert-warning">
Warning, your Odoo database manager is not protected.
Please <a href="#" data-toggle="modal" data-target=".o_database_master">set a master password</a>
@@ -126,7 +130,7 @@
{% if error %}
<div class="alert alert-danger">{{ error }}</div>
{% endif %}
- {% if databases %}
+ {% if list_db and databases %}
<div class="list-group">
{% for db in databases %}
<a href="/web?db={{ db }}" class="list-group-item" >
@@ -161,7 +165,7 @@
<a href="/web/database/manager">Manage databases</a>
</div>
{% endif %}
- {% else %}
+ {% elif list_db %}
<form role="form" action="/web/database/create" method="post">
{{ create_form() }}
<input type="submit" value="Create database" class="btn btn-primary pull-left"/>
diff --git a/doc/setup/deploy.rst b/doc/setup/deploy.rst
index 9879117b607..6e54815496a 100644
--- a/doc/setup/deploy.rst
+++ b/doc/setup/deploy.rst
@@ -71,7 +71,8 @@ in ``/etc/odoo.conf`` set:
Once it is correctly working and only matching a single database per hostname, it
is strongly recommended to block access to the database manager screens,
and to use the ``--no-database-list`` startup paramater to prevent listing
- your databases. See also security_.
+ your databases, and to block access to the database management screens.
+ See also security_.
PostgreSQL
@@ -427,10 +428,14 @@ security-related topics:
- Use appropriate database filters ( :option:`--db-filter <odoo-bin --db-filter>`)
to restrict the visibility of your databases according to the hostname.
See :ref:`db_filter`.
-
-- Once your ``db_filter`` is configured and only matches a single database per hostname,
- you should set ``list_db`` configuration option to ``False``, to prevent listing databases
- entirely (this is also exposed as the :option:`--no-database-list <odoo-bin --no-database-list>`
+ You may also use :option:`-d <odoo-bin -d>` to provide your own (comma-separated)
+ list of available databases to filter from, instead of letting the system fetch
+ them all from the database backend.
+
+- Once your ``db_name`` and ``db_filter`` are configured and only match a single database
+ per hostname, you should set ``list_db`` configuration option to ``False``, to prevent
+ listing databases entirely, and to block access to the database management screens
+ (this is also exposed as the :option:`--no-database-list <odoo-bin --no-database-list>`
command-line option)
- Make sure the PostgreSQL user (:option:`--db_user <odoo-bin --db_user>`) is *not* a super-user,
@@ -473,10 +478,16 @@ Database Manager Security
This setting is used on all database management screens (to create, delete,
dump or restore databases).
-If the management screens must not be accessible, or must only be accessible
-from a selected set of machines, use the proxy server's features to block
-access to all routes starting with ``/web/database`` except (maybe)
-``/web/database/selector`` which displays the database-selection screen.
+If the management screens must not be accessible at all, you should set ``list_db``
+configuration option to ``False``, to block access to all the database selection and
+management screens. But be sure to setup an appropriate ``db_name`` parameter
+(and optionally, ``db_filter`` too) so that the system can determine the target database
+for each request, otherwise users will be blocked as they won't be allowed to choose the
+database themselves.
+
+If the management screens must only be accessible from a selected set of machines,
+use the proxy server's features to block access to all routes starting with ``/web/database``
+except (maybe) ``/web/database/selector`` which displays the database-selection screen.
If the database-management screen should be left accessible, the
``admin_passwd`` setting must be changed from its ``admin`` default: this
diff --git a/odoo/service/db.py b/odoo/service/db.py
index 045afc9f0d8..505f86ec50e 100644
--- a/odoo/service/db.py
+++ b/odoo/service/db.py
@@ -12,12 +12,13 @@ import zipfile
from functools import wraps
from contextlib import closing
+from decorator import decorator
import psycopg2
import odoo
from odoo import SUPERUSER_ID
-from odoo.exceptions import UserError
+from odoo.exceptions import AccessDenied
import odoo.release
import odoo.sql_db
import odoo.tools
@@ -30,6 +31,15 @@ _logger = logging.getLogger(__name__)
class DatabaseExists(Warning):
pass
+
+def check_db_management_enabled(method):
+ def if_db_mgt_enabled(method, self, *args, **kwargs):
+ if not odoo.tools.config['list_db']:
+ _logger.error('Database management functions blocked, admin disabled database listing')
+ raise AccessDenied()
+ return method(self, *args, **kwargs)
+ return decorator(if_db_mgt_enabled, method)
+
#----------------------------------------------------------
# Master password required
#----------------------------------------------------------
@@ -89,6 +99,7 @@ def _create_empty_database(name):
cr.autocommit(True) # avoid transaction block
cr.execute("""CREATE DATABASE "%s" ENCODING 'unicode' TEMPLATE "%s" """ % (name, chosen_template))
+@check_db_management_enabled
def exp_create_database(db_name, demo, lang, user_password='admin', login='admin', country_code=None):
""" Similar to exp_create but blocking."""
_logger.info('Create database `%s`.', db_name)
@@ -96,6 +107,7 @@ def exp_create_database(db_name, demo, lang, user_password='admin', login='admin
_initialize_db(id, db_name, demo, lang, user_password, login, country_code)
return True
+@check_db_management_enabled
def exp_duplicate_database(db_original_name, db_name):
_logger.info('Duplicate database `%s` to `%s`.', db_original_name, db_name)
odoo.sql_db.close_db(db_original_name)
@@ -133,6 +145,7 @@ def _drop_conn(cr, db_name):
except Exception:
pass
+@check_db_management_enabled
def exp_drop(db_name):
if db_name not in list_dbs(True):
return False
@@ -157,12 +170,14 @@ def exp_drop(db_name):
shutil.rmtree(fs)
return True
+@check_db_management_enabled
def exp_dump(db_name, format):
with tempfile.TemporaryFile(mode='w+b') as t:
dump_db(db_name, t, format)
t.seek(0)
return base64.b64encode(t.read()).decode()
+@check_db_management_enabled
def dump_db_manifest(cr):
pg_version = "%d.%d" % divmod(cr._obj.connection.server_version / 100, 100)
cr.execute("SELECT name, latest_version FROM ir_module_module WHERE state = 'installed'")
@@ -178,6 +193,7 @@ def dump_db_manifest(cr):
}
return manifest
+@check_db_management_enabled
def dump_db(db_name, stream, backup_format='zip'):
"""Dump database `db` into file-like object `stream` if stream is None
return a file object with the dump """
@@ -213,6 +229,7 @@ def dump_db(db_name, stream, backup_format='zip'):
else:
return stdout
+@check_db_management_enabled
def exp_restore(db_name, data, copy=False):
data_file = tempfile.NamedTemporaryFile(delete=False)
try:
@@ -223,6 +240,7 @@ def exp_restore(db_name, data, copy=False):
os.unlink(data_file.name)
return True
+@check_db_management_enabled
def restore_db(db, dump_file, copy=False):
assert isinstance(db, pycompat.string_types)
if exp_db_exist(db):
@@ -277,6 +295,7 @@ def restore_db(db, dump_file, copy=False):
_logger.info('RESTORE DB: %s', db)
+@check_db_management_enabled
def exp_rename(old_name, new_name):
odoo.modules.registry.Registry.delete(old_name)
odoo.sql_db.close_db(old_name)
@@ -298,11 +317,13 @@ def exp_rename(old_name, new_name):
shutil.move(old_fs, new_fs)
return True
+@check_db_management_enabled
def exp_change_admin_password(new_password):
odoo.tools.config.set_admin_password(new_password)
odoo.tools.config.save()
return True
+@check_db_management_enabled
def exp_migrate_databases(databases):
for db in databases:
_logger.info('migrate database %s', db)
diff --git a/odoo/tools/config.py b/odoo/tools/config.py
index ba7121e7ca8..1901620cf4e 100644
--- a/odoo/tools/config.py
+++ b/odoo/tools/config.py
@@ -245,7 +245,9 @@ class configmanager(object):
security = optparse.OptionGroup(parser, 'Security-related options')
security.add_option('--no-database-list', action="store_false", dest='list_db', my_default=True,
- help="disable the ability to return the list of databases")
+ help="Disable the ability to obtain or view the list of databases. "
+ "Also disable access to the database manager and selector, "
+ "so be sure to set a proper --database parameter first")
parser.add_option_group(security)
# Advanced options