From f4f2f0ff3e808bc2c85b914aa750ad68770ed334 Mon Sep 17 00:00:00 2001 From: Bruno Wagner Date: Wed, 3 Jun 2015 17:10:08 -0300 Subject: Creating a leap session is now part of leap init We've moved the init soledad method to the leap_initialization module and gave it a meaningful name, because it was initializing the whole leap session instead of only soledad, because of that we removed some of the uneeded config files and deduplicated some code on maintenance to use the same facilities. Some arguments had non-meaningful variable names and args was being passed everywhere (it was unclear who was using which variables in the args) We changed the initialization to pass those arguments explicitly, then we can factor them out sometime when it makes sense --- service/pixelated/config/__init__.py | 59 +++++++++++++++------------- service/pixelated/config/app_factory.py | 35 +++++++++-------- service/pixelated/config/args.py | 4 +- service/pixelated/config/events_server.py | 21 ---------- service/pixelated/config/initialize_leap.py | 26 ++++++++---- service/pixelated/config/loading_page.py | 4 -- service/pixelated/config/soledad.py | 29 -------------- service/pixelated/maintenance.py | 21 +++++----- service/test/unit/config/test_app_factory.py | 9 +++-- 9 files changed, 86 insertions(+), 122 deletions(-) delete mode 100644 service/pixelated/config/events_server.py delete mode 100644 service/pixelated/config/soledad.py diff --git a/service/pixelated/config/__init__.py b/service/pixelated/config/__init__.py index 871a7925..125ee1cb 100644 --- a/service/pixelated/config/__init__.py +++ b/service/pixelated/config/__init__.py @@ -19,51 +19,54 @@ import sys from pixelated.config import app_factory from pixelated.config.args import parse_user_agent_args -from pixelated.config.events_server import init_events_server -from pixelated.config.loading_page import loading +from pixelated.config.loading_page import LoadingResource from pixelated.config.register import register from pixelated.config.logging_setup import init_logging -from pixelated.config.soledad import init_soledad_and_user_key from twisted.internet import reactor from twisted.internet.threads import deferToThread -from pixelated.support.error_handler import error_handler +from twisted.internet import defer +from twisted.web.server import Site from pixelated.config.initialize_leap import initialize_leap +@defer.inlineCallbacks +def start_user_agent(loading_app, host, port, sslkey, sslcert, leap_home, leap_session): + yield loading_app.stopListening() + + app_factory.create_app(leap_home, + leap_session, + host, + port, + sslkey=sslkey, + sslcert=sslcert) + + def initialize(): args = parse_user_agent_args() init_logging(debug=args.debug) - app = initialize_leap(args.leap_provider_cert, - args.leap_provider_cert_fingerprint, - args.config, - args.dispatcher, - args.dispatcher_stdin) - if args.register: register(*args.register) sys.exit(0) - init_events_server() - - def load_app(): - # welcome to deferred hell. Or maybe you'll be welcomed later, who knows. - loading_app = loading(args) - - def init_soledad(): - return init_soledad_and_user_key(app, args.home) - - def stop_loading_app(leap_session): - d = loading_app.stopListening() - d.addCallback(partial(start_user_agent_app, leap_session)) + loading_app = reactor.listenTCP(args.port, Site(LoadingResource()), interface=args.host) - def start_user_agent_app(leap_session, _): - app_factory.create_app(app, args, leap_session) + deferred = deferToThread( + lambda: initialize_leap(args.leap_provider_cert, + args.leap_provider_cert_fingerprint, + args.config_file, + args.dispatcher, + args.dispatcher_stdin, + args.leap_home)) - d = deferToThread(init_soledad) - d.addCallback(stop_loading_app) - d.addErrback(error_handler) + deferred.addCallback( + lambda leap_session: start_user_agent(loading_app, + args.host, + args.port, + args.sslkey, + args.sslcert, + args.leap_home, + leap_session)) - reactor.callWhenRunning(load_app) reactor.run() diff --git a/service/pixelated/config/app_factory.py b/service/pixelated/config/app_factory.py index d02472ec..c74a46f7 100644 --- a/service/pixelated/config/app_factory.py +++ b/service/pixelated/config/app_factory.py @@ -93,7 +93,7 @@ def stop_incoming_mail_fetcher(reactor_stop_function, leap_session): return wrapper -def init_app(app, leap_home, leap_session): +def init_app(resource, leap_home, leap_session): leap_session.start_background_jobs() keymanager = leap_session.nicknym.keymanager @@ -110,7 +110,7 @@ def init_app(app, leap_home, leap_session): MailboxIndexerListener.SEARCH_ENGINE = search_engine InputMail.FROM_EMAIL_ADDRESS = leap_session.account_email() - app.resource.initialize(soledad_querier, keymanager, search_engine, mail_service, draft_service) + resource.initialize(soledad_querier, keymanager, search_engine, mail_service, draft_service) register(signal=proto.SOLEDAD_DONE_DATA_SYNC, uid=INIT_INDEX_AND_REMOVE_DUPES_CALLBACK, @@ -130,33 +130,36 @@ def init_app(app, leap_home, leap_session): reactor.stop = stop_incoming_mail_fetcher(reactor.stop, leap_session) -def create_app(app, args, leap_session): - app.resource = RootResource() - init_app(app, args.home, leap_session) - if args.sslkey and args.sslcert: - listen_with_ssl(app, args) +def create_app(leap_home, leap_session, host, port, sslkey=None, sslcert=None): + resource = RootResource() + init_app(resource, leap_home, leap_session) + if sslkey and sslcert: + listen_with_ssl(resource, host, port, sslkey, sslcert) else: - listen_without_ssl(app, args) + listen_without_ssl(resource, host, port) -def listen_without_ssl(app, args): - reactor.listenTCP(args.port, Site(app.resource), interface=args.host) +def listen_without_ssl(resource, host, port): + reactor.listenTCP(port, Site(resource), interface=host) -def _ssl_options(args): - with open(args.sslkey) as keyfile: +def _ssl_options(sslkey, sslcert): + with open(sslkey) as keyfile: pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, keyfile.read()) - with open(args.sslcert) as certfile: + with open(sslcert) as certfile: cert = crypto.load_certificate(crypto.FILETYPE_PEM, certfile.read()) + acceptable = ssl.AcceptableCiphers.fromOpenSSLCipherString( u'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:!RC4:HIGH:!MD5:!aNULL:!EDH') - options = ssl.CertificateOptions(privateKey=pkey, certificate=cert, method=SSL.TLSv1_2_METHOD, + options = ssl.CertificateOptions(privateKey=pkey, + certificate=cert, + method=SSL.TLSv1_2_METHOD, acceptableCiphers=acceptable) return options -def listen_with_ssl(app, args): - reactor.listenSSL(args.port, Site(app.resource), _ssl_options(args), interface=args.host) +def listen_with_ssl(resource, host, port, sslkey, sslcert): + reactor.listenSSL(port, Site(resource), _ssl_options(sslkey, sslcert), interface=host) class RedirectToSSL(resource.Resource): diff --git a/service/pixelated/config/args.py b/service/pixelated/config/args.py index f3549df1..dd3b715d 100644 --- a/service/pixelated/config/args.py +++ b/service/pixelated/config/args.py @@ -51,7 +51,7 @@ def parser_add_default_arguments(parser): parser.add_argument('--debug', action='store_true', help='DEBUG mode.') parser.add_argument('--dispatcher', help='run in organization mode, the credentials will be read from specified file', metavar='file') parser.add_argument('--dispatcher-stdin', help='run in organization mode, the credentials will be read from stdin', default=False, action='store_true', dest='dispatcher_stdin') - parser.add_argument('-c', '--config', metavar='', default=None, help='use specified file for credentials (for test purposes only)') - parser.add_argument('--home', help='The folder where the user agent stores its data. Defaults to ~/.leap', default=DEFAULT_LEAP_HOME) + parser.add_argument('-c', '--config', dest='config_file', metavar='', default=None, help='use specified file for credentials (for test purposes only)') + parser.add_argument('--leap-home', help='The folder where the user agent stores its data. Defaults to ~/.leap', dest='leap_home', default=DEFAULT_LEAP_HOME) parser.add_argument('-lc', '--leap-provider-cert', metavar='', default=None, help='use specified file for LEAP provider cert authority certificate (url https:///ca.crt)') parser.add_argument('-lf', '--leap-provider-cert-fingerprint', metavar='', default=None, help='use specified fingerprint to validate connection with LEAP provider', dest='leap_provider_cert_fingerprint') diff --git a/service/pixelated/config/events_server.py b/service/pixelated/config/events_server.py deleted file mode 100644 index 121ebcab..00000000 --- a/service/pixelated/config/events_server.py +++ /dev/null @@ -1,21 +0,0 @@ -# -# Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see . - -from leap.common.events import server as events_server - - -def init_events_server(): - events_server.ensure_server(port=8090) diff --git a/service/pixelated/config/initialize_leap.py b/service/pixelated/config/initialize_leap.py index df7b8412..a4610622 100644 --- a/service/pixelated/config/initialize_leap.py +++ b/service/pixelated/config/initialize_leap.py @@ -1,6 +1,7 @@ from pixelated.config.config import Config from pixelated.config.config_ua import config_user_agent from pixelated.config.dispatcher import config_dispatcher +from leap.common.events import server as events_server import pixelated.bitmask_libraries.certs as certs from pixelated.bitmask_libraries.session import open_leap_session @@ -9,7 +10,8 @@ def initialize_leap(leap_provider_cert, leap_provider_cert_fingerprint, config_file, dispatcher, - dispatcher_stdin): + dispatcher_stdin, + leap_home): init_monkeypatches() @@ -17,14 +19,13 @@ def initialize_leap(leap_provider_cert, dispatcher_stdin, config_file) - config = Config() - config.provider = provider - config.username = user - config.password = password - init_leap_cert(leap_provider_cert, leap_provider_cert_fingerprint) - return config + events_server.ensure_server(port=8090) + + leap_session = create_leap_session(provider, user, password, leap_home) + + return leap_session def gather_credentials(dispatcher, dispatcher_stdin, config_file): @@ -34,6 +35,17 @@ def gather_credentials(dispatcher, dispatcher_stdin, config_file): return config_user_agent(config_file) +def create_leap_session(provider, username, password, leap_home): + leap_session = open_leap_session(username, + password, + provider, + leap_home) + + leap_session.soledad_session.soledad.sync(defer_decryption=False) + leap_session.nicknym.generate_openpgp_key() + return leap_session + + def init_leap_cert(leap_provider_cert, leap_provider_cert_fingerprint): if leap_provider_cert_fingerprint is None: certs.LEAP_CERT = leap_provider_cert or True diff --git a/service/pixelated/config/loading_page.py b/service/pixelated/config/loading_page.py index b8a95f57..473f675e 100644 --- a/service/pixelated/config/loading_page.py +++ b/service/pixelated/config/loading_page.py @@ -48,7 +48,3 @@ class LoadingResource(Resource): if path == '': return self return Resource.getChild(self, path, request) - - -def loading(args): - return reactor.listenTCP(args.port, Site(LoadingResource()), interface=args.host) diff --git a/service/pixelated/config/soledad.py b/service/pixelated/config/soledad.py deleted file mode 100644 index 6f03d02b..00000000 --- a/service/pixelated/config/soledad.py +++ /dev/null @@ -1,29 +0,0 @@ -# -# Copyright (c) 2014 ThoughtWorks, Inc. -# -# Pixelated is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Pixelated is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with Pixelated. If not, see . - -from pixelated.bitmask_libraries.session import open as open_leap_session - - -def init_soledad_and_user_key(config, leap_home): - leap_session = open_leap_session(config.username, - config.password, - config.provider, - leap_home) - - soledad = leap_session.soledad_session.soledad - soledad.sync(defer_decryption=False) - leap_session.nicknym.generate_openpgp_key() - return leap_session diff --git a/service/pixelated/maintenance.py b/service/pixelated/maintenance.py index a49dc89d..2dbaf49f 100644 --- a/service/pixelated/maintenance.py +++ b/service/pixelated/maintenance.py @@ -28,12 +28,9 @@ from pixelated.config import app_factory from pixelated.config.args import parse_maintenance_args from pixelated.config.config_ua import config_user_agent from pixelated.config.dispatcher import config_dispatcher -from pixelated.config.events_server import init_events_server from pixelated.config.initialize_leap import initialize_leap -from pixelated.config.loading_page import loading from pixelated.config.register import register from pixelated.config.logging_setup import init_logging -from pixelated.config.soledad import init_soledad_and_user_key from twisted.internet import reactor, defer from twisted.internet.threads import deferToThread @@ -57,24 +54,24 @@ def initialize(): init_logging(debug=args.debug) - app = initialize_leap(args.leap_provider_cert, - args.leap_provider_cert_fingerprint, - args.config, - args.dispatcher, - args.dispatcher_stdin) + leap_session = initialize_leap( + args.leap_provider_cert, + args.leap_provider_cert_fingerprint, + args.config, + args.dispatcher, + args.dispatcher_stdin) - init_events_server() - execute_command = create_execute_command(args, app) + execute_command = create_execute_command(args, leap_session) reactor.callWhenRunning(execute_command) reactor.run() -def create_execute_command(args, app): +def create_execute_command(args, leap_session): def execute_command(): def init_soledad(): - return init_soledad_and_user_key(app, args.home) + return leap_session def get_soledad_handle(leap_session): soledad = leap_session.soledad_session.soledad diff --git a/service/test/unit/config/test_app_factory.py b/service/test/unit/config/test_app_factory.py index b09ffd4c..8a89d6e6 100644 --- a/service/test/unit/config/test_app_factory.py +++ b/service/test/unit/config/test_app_factory.py @@ -20,8 +20,9 @@ class AppFactoryTest(unittest.TestCase): def test_that_create_app_binds_to_tcp_port_if_no_ssl_options(self, reactor_mock, init_app_mock): app_mock = MagicMock() leap_session = MagicMock() + config = AppFactoryTest.MockConfig(12345, '127.0.0.1', leap_session) - create_app(app_mock, AppFactoryTest.MockConfig(12345, '127.0.0.1'), leap_session) + create_app(config.home, leap_session, config.host, config.port, config.sslkey, config.sslcert) reactor_mock.listenTCP.assert_called_once_with(12345, ANY, interface='127.0.0.1') @@ -30,8 +31,10 @@ class AppFactoryTest(unittest.TestCase): def test_that_create_app_binds_to_ssl_if_ssl_options(self, reactor_mock, init_app_mock): app_mock = MagicMock() leap_session = MagicMock() - pixelated.config.app_factory._ssl_options = lambda _: 'options' + pixelated.config.app_factory._ssl_options = lambda x, y: 'options' - create_app(app_mock, AppFactoryTest.MockConfig(12345, '127.0.0.1', sslkey="sslkey", sslcert="sslcert"), leap_session) + config = AppFactoryTest.MockConfig(12345, '127.0.0.1', sslkey="sslkey", sslcert="sslcert") + + create_app(config.home, leap_session, config.host, config.port, config.sslkey, config.sslcert) reactor_mock.listenSSL.assert_called_once_with(12345, ANY, 'options', interface='127.0.0.1') -- cgit v1.2.3