diff --git a/change-secret.py b/change-secret.py deleted file mode 100755 index 255e74c9a7..0000000000 --- a/change-secret.py +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env python - -import click -from time import sleep - -from flask import current_app -from flask.cli import FlaskGroup - -from sqlalchemy import Table, MetaData -from sqlalchemy.exc import OperationalError -from sqlalchemy.sql import select -from sqlalchemy_utils.types.encrypted.encrypted_type import FernetEngine - -from redash import create_app -from redash.models import db -from redash.models.base import Column -from redash.models.types import EncryptedConfiguration -from redash.utils.configuration import ConfigurationContainer - - -# setup application and db. -def create(group): - app = current_app or create_app() - return app - - -def setup_db(): - db.app = current_app - isConnected = True - for i in range(6): - isConnected = True - try: - conn = db.engine.connect() - except OperationalError: - isConnected = False - if isConnected: - conn.close() - break - sleep(10) - if not(isConnected): - raise RuntimeError('fail to connect db.') - - -@click.group(cls=FlaskGroup, create_app=create) -def cli(): - """This is a script to chage secret key.""" - - -@cli.command() -@click.argument('old_secret') -@click.argument('new_secret') -@click.option('--show-sql/--no-show-sql', default=False) -def data_source(old_secret, new_secret, show_sql): - setup_db() - - if show_sql: - import logging - logging.basicConfig() - logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO) - - table_for_select = Table('data_sources', MetaData(), - Column('id', db.Integer, primary_key=True), - Column('encrypted_options', - ConfigurationContainer.as_mutable( - EncryptedConfiguration( - db.Text, old_secret, FernetEngine)))) - table_for_update = Table('data_sources', MetaData(), - Column('id', db.Integer, primary_key=True), - Column('encrypted_options', - ConfigurationContainer.as_mutable( - EncryptedConfiguration( - db.Text, new_secret, FernetEngine)))) - - update = table_for_update.update() - data_sources = db.session.execute(select([table_for_select])) - for ds in data_sources: - stmt = update.where(table_for_update.c.id==ds['id']).values(encrypted_options=ds['encrypted_options']) - db.session.execute(stmt) - - data_sources.close() - db.session.commit() - - -if __name__ == '__main__': - cli() diff --git a/redash/cli/database.py b/redash/cli/database.py index e3084d3bd9..b8946f0aef 100644 --- a/redash/cli/database.py +++ b/redash/cli/database.py @@ -1,11 +1,18 @@ import time +from click import argument, option from flask.cli import AppGroup from flask_migrate import stamp import sqlalchemy from sqlalchemy.exc import DatabaseError +from sqlalchemy.sql import select +from sqlalchemy_utils.types.encrypted.encrypted_type import FernetEngine -manager = AppGroup(help="Manage the database (create/drop tables).") +from redash.models.base import Column +from redash.models.types import EncryptedConfiguration +from redash.utils.configuration import ConfigurationContainer + +manager = AppGroup(help="Manage the database (create/drop tables. reencrypt data.).") def _wait_for_db_connection(db): @@ -41,3 +48,42 @@ def drop_tables(): _wait_for_db_connection(db) db.drop_all() + + +@manager.command() +@argument('old_secret') +@argument('new_secret') +@option('--show-sql/--no-show-sql', default=False, + help="show sql for debug") +def reencrypt(old_secret, new_secret, show_sql): + """Reencrypt data encrypted by OLD_SECRET with NEW_SECRET.""" + from redash.models import db + + _wait_for_db_connection(db) + + if show_sql: + import logging + logging.basicConfig() + logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO) + + table_for_select = sqlalchemy.Table('data_sources', sqlalchemy.MetaData(), + Column('id', db.Integer, primary_key=True), + Column('encrypted_options', + ConfigurationContainer.as_mutable( + EncryptedConfiguration( + db.Text, old_secret, FernetEngine)))) + table_for_update = sqlalchemy.Table('data_sources', sqlalchemy.MetaData(), + Column('id', db.Integer, primary_key=True), + Column('encrypted_options', + ConfigurationContainer.as_mutable( + EncryptedConfiguration( + db.Text, new_secret, FernetEngine)))) + + update = table_for_update.update() + data_sources = db.session.execute(select([table_for_select])) + for ds in data_sources: + stmt = update.where(table_for_update.c.id == ds['id']).values(encrypted_options=ds['encrypted_options']) + db.session.execute(stmt) + + data_sources.close() + db.session.commit()