Beispiel #1
0
def get_etcd_config(namespace: Optional[str] = None) -> FrontConfig:
    if namespace is None:
        namespace = '/eduid/webapp/jsapps/'
    parser = EtcdConfigParser(namespace)
    config = parser.read_configuration(silent=False)
    config = {k.lower(): v for k, v in config.items()}
    return FrontConfig(**config)
Beispiel #2
0
    def setUp(self):
        self.etcd_instance = EtcdTemporaryInstance()

        self.ns = '/test/'
        self.parser = EtcdConfigParser(namespace=self.ns,
                                       host=self.etcd_instance.host,
                                       port=self.etcd_instance.port)
Beispiel #3
0
def get_config():

    parser = EtcdConfigParser('/eduid/webapp/jsapps/')
    config = parser.read_configuration(silent=True)

    jsconfig.update(config)

    return jsconfig
Beispiel #4
0
def get_config():

    parser = EtcdConfigParser('/eduid/webapp/jsapps/')
    config = parser.read_configuration(silent=True)
    jsconfig.update(config)
    jsconfig['csrf_token'] = session.get_csrf_token()

    return jsconfig
Beispiel #5
0
def eduid_init_app_no_db(name, config, app_class=AuthnApp):
    """
    Create and prepare the flask app for eduID APIs with all the attributes
    common to all  apps.

     * Parse and merge configurations
     * Add logging
     * Add db connection
     * Add eduID session

    :param name: The name of the instance, it will affect the configuration file
                 loaded from the filesystem.
    :type name: str
    :param config: any additional configuration settings. Specially useful
                   in test cases
    :type config: dict
    :param app_class: The class used to build the flask app. Should be a
                      descendant of flask.Flask
    :type app_class: type

    :return: the flask application.
    :rtype: flask.Flask
    """
    app = app_class(name)
    app.wsgi_app = ProxyFix(app.wsgi_app)
    app.request_class = Request

    # Init etcd config parsers
    common_parser = EtcdConfigParser('/eduid/webapp/common/')
    app_parser = EtcdConfigParser('/eduid/webapp/{!s}/'.format(name))

    # Load project wide default settings
    app.config.from_object('eduid_webapp.settings.common')

    try:
        # Load optional app specific default settings
        app.config.from_object('eduid_webapp.{!s}.settings.common'.format(name))
    except ImportError:  # No app specific default config found
        pass

    # Load optional project wide settings
    app.config.update(common_parser.read_configuration(silent=True))
    # Load optional app specific settings
    app.config.update(app_parser.read_configuration(silent=True))

    # Load optional init time settings
    app.config.update(config)

    # Initialize shared features
    app = init_logging(app)
    app = init_exception_handlers(app)
    app = init_sentry(app)
    app.session_interface = SessionFactory(app.config)

    return app
Beispiel #6
0
    def setUp(self):
        super(JSConfigTests, self).setUp(copy_user_to_private=False)

        self.jsconfig_ns = '/eduid/webapp/jsapps/'
        self.jsconfig_parser = EtcdConfigParser(namespace=self.jsconfig_ns,
                                                host=self.etcd_instance.host,
                                                port=self.etcd_instance.port)

        jsconfig_config = {
            'eduid': {
                'webapp': {
                    'jsapps': {
                        'password_entropy': 12,
                        'password_length': 10,
                        'dashboard_url': 'dummy-url'
                    }
                }
            }
        }
        self.jsconfig_parser.write_configuration(jsconfig_config)
        os.environ['EDUID_CONFIG_NS'] = '/eduid/webapp/jsapps/'
        os.environ['ETCD_HOST'] = self.etcd_instance.host
        os.environ['ETCD_PORT'] = str(self.etcd_instance.port)
Beispiel #7
0
def eduid_init_app_no_db(name, config, app_class=AuthnApp):
    """
    Create and prepare the flask app for eduID APIs with all the attributes
    common to all  apps.

     * Parse and merge configurations
     * Add logging
     * Add db connection
     * Add eduID session

    :param name: The name of the instance, it will affect the configuration file
                 loaded from the filesystem.
    :type name: str
    :param config: any additional configuration settings. Specially useful
                   in test cases
    :type config: dict
    :param app_class: The class used to build the flask app. Should be a
                      descendant of flask.Flask
    :type app_class: type

    :return: the flask application.
    :rtype: flask.Flask
    """
    app = app_class(name)
    app.wsgi_app = ProxyFix(app.wsgi_app)
    app.request_class = Request

    # Init etcd config parsers
    common_parser = EtcdConfigParser('/eduid/webapp/common/')
    app_parser = EtcdConfigParser('/eduid/webapp/{!s}/'.format(name))

    # Load project wide default settings
    app.config.from_object('eduid_webapp.settings.common')

    try:
        # Load optional app specific default settings
        app.config.from_object(
            'eduid_webapp.{!s}.settings.common'.format(name))
    except ImportError:  # No app specific default config found
        pass

    # Load optional project wide settings
    app.config.update(common_parser.read_configuration(silent=True))
    # Load optional app specific settings
    app.config.update(app_parser.read_configuration(silent=True))

    # Load optional init time settings
    app.config.update(config)

    # Initialize shared features
    app = init_logging(app)
    app = init_exception_handlers(app)
    app = init_sentry(app)
    app.session_interface = SessionFactory(app.config)

    return app
Beispiel #8
0
    def setUp(self):
        self.etcd_instance = EtcdTemporaryInstance()

        self.ns = '/test/'
        self.parser = EtcdConfigParser(namespace=self.ns, host=self.etcd_instance.host, port=self.etcd_instance.port)
Beispiel #9
0
class TestEtcdParser(unittest.TestCase):

    def setUp(self):
        self.etcd_instance = EtcdTemporaryInstance()

        self.ns = '/test/'
        self.parser = EtcdConfigParser(namespace=self.ns, host=self.etcd_instance.host, port=self.etcd_instance.port)

    def tearDown(self):
        self.etcd_instance.shutdown()

    def test_write(self):

        config = {
            'test': {
                'MY_BOOL': True,
                'MY_STRING': 'A value',
                'MY_LIST': ['One', 'Two', 3],
                'MY_DICT': {'A': 'B'}
            }
        }

        self.parser.write_configuration(config)

        self.assertEqual(self.parser.get('MY_BOOL'), True)
        self.assertEqual(self.parser.get('MY_STRING'), 'A value')
        self.assertEqual(self.parser.get('MY_LIST'), ['One', 'Two', 3])
        self.assertEqual(self.parser.get('MY_DICT'), {'A': 'B'})

    def test_read(self):

        config = {
            'test': {
                'MY_BOOL': True,
                'MY_STRING': 'A value',
                'MY_LIST': ['One', 'Two', 3],
                'MY_DICT': {'A': 'B'}
            }
        }

        self.parser.write_configuration(config)
        read_config = self.parser.read_configuration()

        self.assertEqual(config['test'], read_config)

    def test_set_get(self):

        self.parser.set('MY_SET_KEY', 'a nice value')
        self.assertEqual(self.parser.get('MY_SET_KEY'), 'a nice value')

        read_config = self.parser.read_configuration()
        self.assertEqual({'MY_SET_KEY': 'a nice value'}, read_config)

    def test_uppercase(self):

        config = {
            'test': {
                'my_bool': True,
                'my_string': 'A value',
                'my_list': ['One', 'Two', 3],
                'my_dict': {'A': 'B'}
            }
        }

        self.parser.write_configuration(config)
        read_config = self.parser.read_configuration()
        for key in config['test'].keys():
            self.assertIn(key.upper(), read_config.keys())

        self.parser.set('my_set_key', 'a nice value')
        self.assertEqual(self.parser.get('MY_SET_KEY'), 'a nice value')
Beispiel #10
0
class TestEtcdParser(unittest.TestCase):
    def setUp(self):
        self.etcd_instance = EtcdTemporaryInstance()

        self.ns = '/test/'
        self.parser = EtcdConfigParser(namespace=self.ns,
                                       host=self.etcd_instance.host,
                                       port=self.etcd_instance.port)

    def tearDown(self):
        self.etcd_instance.shutdown()

    def test_write(self):

        config = {
            'test': {
                'MY_BOOL': True,
                'MY_STRING': 'A value',
                'MY_LIST': ['One', 'Two', 3],
                'MY_DICT': {
                    'A': 'B'
                }
            }
        }

        self.parser.write_configuration(config)

        self.assertEqual(self.parser.get('MY_BOOL'), True)
        self.assertEqual(self.parser.get('MY_STRING'), 'A value')
        self.assertEqual(self.parser.get('MY_LIST'), ['One', 'Two', 3])
        self.assertEqual(self.parser.get('MY_DICT'), {'A': 'B'})

    def test_read(self):

        config = {
            'test': {
                'MY_BOOL': True,
                'MY_STRING': 'A value',
                'MY_LIST': ['One', 'Two', 3],
                'MY_DICT': {
                    'A': 'B'
                }
            }
        }

        self.parser.write_configuration(config)
        read_config = self.parser.read_configuration()

        self.assertEqual(config['test'], read_config)

    def test_set_get(self):

        self.parser.set('MY_SET_KEY', 'a nice value')
        self.assertEqual(self.parser.get('MY_SET_KEY'), 'a nice value')

        read_config = self.parser.read_configuration()
        self.assertEqual({'MY_SET_KEY': 'a nice value'}, read_config)

    def test_uppercase(self):

        config = {
            'test': {
                'my_bool': True,
                'my_string': 'A value',
                'my_list': ['One', 'Two', 3],
                'my_dict': {
                    'A': 'B'
                }
            }
        }

        self.parser.write_configuration(config)
        read_config = self.parser.read_configuration()
        for key in config['test'].keys():
            self.assertIn(key.upper(), read_config.keys())

        self.parser.set('my_set_key', 'a nice value')
        self.assertEqual(self.parser.get('MY_SET_KEY'), 'a nice value')
Beispiel #11
0
class JSConfigTests(EduidAPITestCase):
    def setUp(self):
        super(JSConfigTests, self).setUp(copy_user_to_private=False)

        self.jsconfig_ns = '/eduid/webapp/jsapps/'
        self.jsconfig_parser = EtcdConfigParser(namespace=self.jsconfig_ns,
                                                host=self.etcd_instance.host,
                                                port=self.etcd_instance.port)

        jsconfig_config = {
            'eduid': {
                'webapp': {
                    'jsapps': {
                        'password_entropy': 12,
                        'password_length': 10,
                        'dashboard_url': 'dummy-url'
                    }
                }
            }
        }
        self.jsconfig_parser.write_configuration(jsconfig_config)
        os.environ['EDUID_CONFIG_NS'] = '/eduid/webapp/jsapps/'
        os.environ['ETCD_HOST'] = self.etcd_instance.host
        os.environ['ETCD_PORT'] = str(self.etcd_instance.port)

    def load_app(self, config):
        """
        Called from the parent class, so we can provide the appropriate flask
        app for this test case.
        """
        app = jsconfig_init_app('jsconfig', config)
        self.browser = app.test_client(allow_subdomain_redirects=True)
        app.url_map.host_matching = False
        return app

    def update_config(self, app_config):
        app_config.update({
            'server_name': 'example.com',
            'tou_url': 'dummy-url',
            'testing': True,
            'dashboard_bundle_path': 'dummy-dashboard-bundle',
            'dashboard_bundle_version': 'dummy-dashboard-version',
            'signup_bundle_path': 'dummy-signup-bundle',
            'signup_bundle_version': 'dummy-signup-version',
            'login_bundle_path': 'dummy-login-bundle',
            'login_bundle_version': 'dummy-login-version',
        })
        return JSConfigConfig(**app_config)

    def test_get_dashboard_config(self):
        eppn = self.test_user_data['eduPersonPrincipalName']
        with self.session_cookie(self.browser,
                                 eppn,
                                 server_name='example.com',
                                 subdomain='dashboard') as client:
            response = client.get('http://dashboard.example.com/config')

            self.assertEqual(response.status_code, 200)

            config_data = json.loads(response.data)

            self.assertEqual(config_data['type'],
                             'GET_JSCONFIG_CONFIG_SUCCESS')
            self.assertEqual(config_data['payload']['dashboard_url'],
                             'dummy-url')
            self.assertEqual(config_data['payload']['static_faq_url'], '')

    @patch('eduid_webapp.jsconfig.views.requests.get')
    def test_get_signup_config(self, mock_request_get):
        class MockResponse:
            status_code = 200
            headers = {'mock-header': 'dummy-value'}

            def json(self):
                return {
                    'payload': {
                        'test-version-1': '1st Dummy TOU',
                        'test-version-2': '2st Dummy TOU',
                    }
                }

        mock_request_get.return_value = MockResponse()

        eppn = self.test_user_data['eduPersonPrincipalName']
        with self.session_cookie(self.browser,
                                 eppn,
                                 server_name='example.com',
                                 subdomain='signup') as client:
            response = client.get('http://signup.example.com/signup/config')

            self.assertEqual(response.status_code, 200)

            config_data = json.loads(response.data)

            self.assertEqual(config_data['type'],
                             'GET_JSCONFIG_SIGNUP_CONFIG_SUCCESS')
            self.assertEqual(config_data['payload']['dashboard_url'],
                             'dummy-url')
            self.assertEqual(config_data['payload']['static_faq_url'], '')
            self.assertEqual(config_data['payload']['tous']['test-version-2'],
                             '2st Dummy TOU')

    def test_get_login_config(self):

        eppn = self.test_user_data['eduPersonPrincipalName']
        with self.session_cookie(self.browser,
                                 eppn,
                                 server_name='example.com',
                                 subdomain='login') as client:
            response = client.get('http://login.example.com/login/config')

            self.assertEqual(response.status_code, 200)

            config_data = json.loads(response.data)

            self.assertEqual(config_data['type'],
                             'GET_JSCONFIG_LOGIN_CONFIG_SUCCESS')
            self.assertEqual(config_data['payload']['password_entropy'], 12)
            self.assertEqual(config_data['payload']['password_length'], 10)

    def test_get_dashboard_bundle(self):
        eppn = self.test_user_data['eduPersonPrincipalName']
        with self.session_cookie(self.browser,
                                 eppn,
                                 server_name='example.com',
                                 subdomain='dashboard') as client:
            response = client.get('http://dashboard.example.com/get-bundle')

            self.assertEqual(response.status_code, 200)

            body = response.data
            self.assertTrue('dummy-dashboard-bundle' in str(body))
            self.assertTrue('dummy-dashboard-version' in str(body))

    def test_get_signup_bundle(self):
        # XXX Here we access the view by exposing it in a different path - the
        # production manner of distinguishing it (throught its subdomain) does
        # not work with the test client
        from eduid_webapp.jsconfig import views

        views.jsconfig_views.route('/get-signup-bundle',
                                   methods=['GET'])(views.get_signup_bundle)
        self.app.register_blueprint(views.jsconfig_views)
        eppn = self.test_user_data['eduPersonPrincipalName']
        with self.session_cookie(self.browser, eppn) as client:
            response = client.get(
                'http://signup.example.com/get-signup-bundle')

            self.assertEqual(response.status_code, 200)

            body = response.data
            self.assertTrue('dummy-signup-bundle' in str(body))
            self.assertTrue('dummy-signup-version' in str(body))

    def test_get_login_bundle(self):
        # XXX Here we access the view by exposing it in a different path - the
        # production manner of distinguishing it (throught its subdomain) does
        # not work with the test client
        from eduid_webapp.jsconfig import views

        views.jsconfig_views.route('/get-login-bundle',
                                   methods=['GET'])(views.get_login_bundle)
        self.app.register_blueprint(views.jsconfig_views)
        eppn = self.test_user_data['eduPersonPrincipalName']
        with self.session_cookie(self.browser, eppn) as client:
            response = client.get('http://login.example.com/get-login-bundle')

            self.assertEqual(response.status_code, 200)

            body = response.data
            self.assertTrue('dummy-login-bundle' in str(body))
            self.assertTrue('dummy-login-version' in str(body))