public inbox for [email protected]  
help / color / mirror / Atom feed
From: Ashesh Vashi <[email protected]>
To: Dave Page <[email protected]>
Cc: pgadmin-hackers <[email protected]>
Cc: Josh Berkus <[email protected]>
Cc: Devrim GÜNDÜZ <[email protected]>
Subject: Re: RM1849: Auto-generating security keys
Date: Thu, 13 Oct 2016 19:46:56 +0530
Message-ID: <CAG7mmoyhJXXrLv+fgjmgd-Z5GFSaJfHTC89MWQ8LQX3Atw-04A@mail.gmail.com> (raw)
In-Reply-To: <CA+OCxownxfR2eDEaXNkgSdFqat6+AQgukrzcYOyoFX0V-zs_VA@mail.gmail.com>
References: <CA+OCxownxfR2eDEaXNkgSdFqat6+AQgukrzcYOyoFX0V-zs_VA@mail.gmail.com>
List-Unsubscribe:  <mailto:[email protected]?body=unsub%20pgadmin-hackers>

Hi Dave,

On Tue, Oct 11, 2016 at 9:10 PM, Dave Page <[email protected]> wrote:

> Hi Ashesh,
>
> Can you please review the attached patch, and apply if you're happy with
> it?
>
Overall the patch looked good to me.
But - I encounter an issue in 'web' mode, which wont happen with 'runtime'.

Steps for reproduction on existing pgAdmin 4 environment with 'web' mode.
- Apply the patch
- Start the pgAdmin4 application (stand alone application).
- Open pgAdmin home page.
- Log out (if already login).

And, you will see an exception.

I have figure out the issue with the patch.
We were setting the SECURITY_PASSWORD_SALT, after initializing the Security
object.
Hence - it could not set the SECURITY_KEY, and SECURITY_PASSWORD_SALT
properly.

I had moved the Security object initialization after fetching these
configurations from the database.
I have attached a addon patch for the same.

Now - I run into another issue.
Because - the existing password was hashed using the old
SECURITY_PASSWORD_SALT, I am no more able to login to pgAdmin 4.

I think - we need to think about different strategy for upgrading the
configuration file in the 'web' mode.
I was thinking - we can store the existing security configurations in the
database during upgrade process in 'web' mode.

I was not able to spend much time on it due to some other priorities.

--
Thanks & Regards,
Ashesh Vashi


> The purpose is to auto-generate the various security keys that are
> currently in the configuration file, and store them in the SQLite database.
> This allows us to remove the checks for config_local.py and the hard-coded
> default keys which are causing some problems with packaging:
>
> - Hard coded defaults are fine for Desktop mode, and packages generally
> aim to make that work primarily.
> - Hard coded defaults are a security risk for Server mode, hence we
> currently require the user to manually setup keys, which is currently being
> overridden by packagers for Desktop mode.
>
> This change ensures that we have unique security keys for every
> installation, whether running in desktop or server mode (generated from
> os.urandom).
>
> Thanks!
>
>
> --
> Dave Page
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>
> EnterpriseDB UK: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>
>


-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers


Attachments:

  [application/octet-stream] add_auto_generate_security_keys.patch (3.7K, 3-add_auto_generate_security_keys.patch)
  download | inline diff:
diff --git a/web/pgadmin/__init__.py b/web/pgadmin/__init__.py
index 21fe636..b9d1cb4 100644
--- a/web/pgadmin/__init__.py
+++ b/web/pgadmin/__init__.py
@@ -201,7 +201,7 @@ def create_app(app_name=config.APP_NAME):
 
     # Setup Flask-Security
     user_datastore = SQLAlchemyUserDatastore(db, User, Role)
-    security = Security(app, user_datastore)
+    security = Security(None, user_datastore)
 
     # Upgrade the schema (if required)
     with app.app_context():
@@ -225,6 +225,14 @@ def create_app(app_name=config.APP_NAME):
         config.SECRET_KEY = Keys.query.filter_by(name = 'SECRET_KEY').first().value
         config.SECURITY_PASSWORD_SALT = Keys.query.filter_by(name = 'SECURITY_PASSWORD_SALT').first().value
 
+    # Update the app.config with proper security keyes for signing CSRF data,
+    # signing cookies, and the SALT for hashing the passwords.
+    app.config.update(dict(CSRF_SESSION_KEY=config.CSRF_SESSION_KEY))
+    app.config.update(dict(SECRET_KEY=config.SECRET_KEY))
+    app.config.update(dict(SECURITY_PASSWORD_SALT=config.SECURITY_PASSWORD_SALT))
+
+    security.init_app(app)
+
     app.session_interface = create_session_interface(app)
 
     ##########################################################################
diff --git a/web/setup.py b/web/setup.py
index 90697fa..eaa3235 100755
--- a/web/setup.py
+++ b/web/setup.py
@@ -42,15 +42,6 @@ if hasattr(__builtins__, 'raw_input'):
 def do_setup(app):
     """Create a new settings database from scratch"""
 
-    # Get some defaults for the various keys
-    with app.app_context():
-        config.CSRF_SESSION_KEY = base64.urlsafe_b64encode(os.urandom(32))
-        app.jinja_env.globals['config']['CSRF_SESSION_KEY'] = config.CSRF_SESSION_KEY
-        config.SECRET_KEY = base64.urlsafe_b64encode(os.urandom(32))
-        app.jinja_env.globals['config']['SECRET_KEY'] = config.SECRET_KEY
-        config.SECURITY_PASSWORD_SALT = base64.urlsafe_b64encode(os.urandom(32))
-        app.jinja_env.globals['config']['SECURITY_PASSWORD_SALT'] = config.SECURITY_PASSWORD_SALT
-
     if config.SERVER_MODE is False:
         print("NOTE: Configuring authentication for DESKTOP mode.")
         email = config.DESKTOP_USER
@@ -150,7 +141,7 @@ def do_setup(app):
     )
 
 
-def do_upgrade(app, datastore, security, version):
+def do_upgrade(app, datastore, version):
     """Upgrade an existing settings database"""
     #######################################################################
     # Run whatever is required to update the database schema to the current
@@ -386,6 +377,12 @@ CREATE TABLE keys (
 ###############################################################################
 if __name__ == '__main__':
     app = Flask(__name__)
+
+    # Get some defaults for the various keys
+    config.CSRF_SESSION_KEY = base64.urlsafe_b64encode(os.urandom(32))
+    config.SECRET_KEY = base64.urlsafe_b64encode(os.urandom(32))
+    config.SECURITY_PASSWORD_SALT = base64.urlsafe_b64encode(os.urandom(32))
+
     app.config.from_object(config)
 
     if config.TESTING_MODE:
@@ -411,7 +408,6 @@ Entering upgrade mode...""" % config.SQLITE_PATH)
 
         # Setup Flask-Security
         user_datastore = SQLAlchemyUserDatastore(db, User, Role)
-        security = Security(app, user_datastore)
 
         # Always use "< REQUIRED_VERSION" as the test for readability
         with app.app_context():
@@ -433,7 +429,7 @@ Exiting...""" % (version.value))
             print("NOTE: Upgrading database schema from version %d to %d." % (
                 version.value, config.SETTINGS_SCHEMA_VERSION
             ))
-            do_upgrade(app, user_datastore, security, version)
+            do_upgrade(app, user_datastore, version)
     else:
         directory = os.path.dirname(config.SQLITE_PATH)
         if not os.path.exists(directory):


view thread (33+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected], [email protected], [email protected]
  Subject: Re: RM1849: Auto-generating security keys
  In-Reply-To: <CAG7mmoyhJXXrLv+fgjmgd-Z5GFSaJfHTC89MWQ8LQX3Atw-04A@mail.gmail.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox