def test_conditional_expected_secret(self, mock_safe_load):
     mock_safe_load.return_value = {"secrets": {}}
     self._setting_overrides["ADDRESS_LOOKUP_API_AUTH_ENABLED"] = True
     with self.assertRaises(Exception) as ex:
         create_app(self._setting_overrides)
     assert "Missing Secret [ADDRESS_LOOKUP_API_AUTH_TOKEN_SECRET]" in str(
         ex.exception)
    def test_eq_submission_backend_not_set(self):
        # Given
        self._setting_overrides["EQ_SUBMISSION_BACKEND"] = ""

        # When
        with self.assertRaises(Exception) as ex:
            create_app(self._setting_overrides)

        # Then
        assert "Unknown EQ_SUBMISSION_BACKEND" in str(ex.exception)
    def test_eq_publisher_backend_not_set(self):
        # Given
        self._setting_overrides["EQ_PUBLISHER_BACKEND"] = ""

        # When
        with self.assertRaises(Exception) as ex:
            create_app(self._setting_overrides)

        # Then
        assert "Unknown EQ_PUBLISHER_BACKEND" in str(ex.exception)
    def test_eq_feedback_backend_not_set(self):
        # Given
        self._setting_overrides["EQ_FEEDBACK_BACKEND"] = ""

        # When
        with self.assertRaises(Exception) as ex:
            create_app(self._setting_overrides)

        # Then
        assert "Unknown EQ_FEEDBACK_BACKEND" in str(ex.exception)
    def test_gcs_feedback_bucket_id_not_set_raises_exception(self):
        # Given
        self._setting_overrides["EQ_FEEDBACK_BACKEND"] = "gcs"

        # When
        with self.assertRaises(Exception) as ex:
            create_app(self._setting_overrides)

        # Then
        assert "Setting EQ_GCS_FEEDBACK_BUCKET_ID Missing" in str(ex.exception)
    def test_rabbit_submitter_host_not_set_raises_exception(self):
        # Given
        self._setting_overrides["EQ_SUBMISSION_BACKEND"] = "rabbitmq"
        self._setting_overrides["EQ_RABBITMQ_HOST"] = ""

        # When
        with self.assertRaises(Exception) as ex:
            create_app(self._setting_overrides)

        # Then
        assert "Setting EQ_RABBITMQ_HOST Missing" in str(ex.exception)
Beispiel #7
0
    def test_gcs_submitter_bucket_id_not_set_raises_exception(self):
        # Given
        self._setting_overrides["EQ_SUBMISSION_BACKEND"] = "gcs"

        # WHEN
        with self.assertRaises(Exception) as ex:
            create_app(self._setting_overrides)

        # Then
        assert "Setting EQ_GCS_SUBMISSION_BUCKET_ID Missing" in str(
            ex.exception)
    def test_enforces_secure_headers(self):
        with create_app(self._setting_overrides).test_client() as client:
            headers = client.get(
                '/',
                headers={
                    'X-Forwarded-Proto': 'https'
                }  # set protocal so that talisman sets HSTS headers
            ).headers

            self.assertEqual('no-cache, no-store, must-revalidate',
                             headers['Cache-Control'])
            self.assertEqual('no-cache', headers['Pragma'])
            self.assertEqual('max-age=31536000; includeSubDomains',
                             headers['Strict-Transport-Security'])
            self.assertEqual('DENY', headers['X-Frame-Options'])
            self.assertEqual('1; mode=block', headers['X-Xss-Protection'])
            self.assertEqual('nosniff', headers['X-Content-Type-Options'])

            csp_policy_parts = headers['Content-Security-Policy'].split('; ')
            self.assertIn("default-src 'self' https://cdn.ons.gov.uk",
                          csp_policy_parts)
            self.assertIn(
                "script-src 'self' https://www.google-analytics.com https://cdn.ons.gov.uk 'nonce-{}'"
                .format(request.csp_nonce), csp_policy_parts)
            self.assertIn(
                "img-src 'self' data: https://www.google-analytics.com https://cdn.ons.gov.uk",
                csp_policy_parts)
            self.assertIn("font-src 'self' data: https://cdn.ons.gov.uk",
                          csp_policy_parts)
    def test_setup_datastore(self):
        self._setting_overrides["EQ_STORAGE_BACKEND"] = "datastore"

        with patch("google.cloud.datastore.Client"):
            application = create_app(self._setting_overrides)

        self.assertIsInstance(application.eq["storage"], Datastore)
Beispiel #10
0
    def test_enforces_secure_session(self):
        application = create_app(self._setting_overrides)
        self.assertTrue(application.secret_key)
        self.assertTrue(application.session_interface)

        # This is derived from EQ_ENABLE_SECURE_SESSION_COOKIE which is false
        # when running tests
        self.assertFalse(application.config['SESSION_COOKIE_SECURE'])
    def test_submission_backend_not_set_raises_exception(self):
        # Given
        self._setting_overrides["EQ_SUBMISSION_CONFIRMATION_BACKEND"] = ""
        self._setting_overrides[
            "EQ_SUBMISSION_CONFIRMATION_CLOUD_FUNCTION_NAME"] = "test"

        # When
        with patch(
                "google.auth._default._get_explicit_environ_credentials",
                return_value=(Mock(), "test-project-id"),
        ):
            with self.assertRaises(Exception) as ex:
                create_app(self._setting_overrides)

        # Then
        assert "Unknown EQ_SUBMISSION_CONFIRMATION_BACKEND" in str(
            ex.exception)
Beispiel #12
0
    def test_versioned_url_for_with_version(self):
        self._setting_overrides['EQ_APPLICATION_VERSION'] = 'abc123'
        application = create_app(self._setting_overrides)
        application.config['SERVER_NAME'] = 'test'

        with application.app_context(), self.override_settings():
            self.assertEqual('http://test/s/a.jpg?q=abc123',
                             versioned_url_for('static', filename='a.jpg'))
    def test_adds_logging_of_request_ids(self):
        with patch("app.setup.logger") as logger:
            self._setting_overrides.update({"EQ_APPLICATION_VERSION": False})
            application = create_app(self._setting_overrides)

            application.test_client().get("/")
            self.assertEqual(1, logger.new.call_count)
            _, kwargs = logger.new.call_args
            self.assertTrue(UUID(kwargs["request_id"], version=4))
Beispiel #14
0
def app(mocker):
    setting_overrides = {"LOGIN_DISABLED": True}
    mocker.patch("app.setup.datastore.Client", MockDatastore)
    mocker.patch("app.setup.redis.Redis", fakeredis.FakeStrictRedis)
    the_app = create_app(setting_overrides=setting_overrides)
    the_app.config["SERVER_NAME"] = "test.localdomain"
    app_context = the_app.app_context()
    app_context.push()
    yield the_app
    app_context.pop()
Beispiel #15
0
    def test_versioned_url_for_without_version(self):
        self._setting_overrides.update({
            'EQ_APPLICATION_VERSION': False,
        })
        application = create_app(self._setting_overrides)
        application.config['SERVER_NAME'] = 'test'

        # Patches the application version, since it's used in `versioned_url_for`
        with application.app_context(), self.override_settings():
            self.assertEqual('http://test/s/a.jpg?q=False',
                             versioned_url_for('static', filename='a.jpg'))
    def test_adds_rabbit_submitter_to_the_application(self):
        # Given
        self._setting_overrides["EQ_SUBMISSION_BACKEND"] = "rabbitmq"
        self._setting_overrides["EQ_RABBITMQ_HOST"] = "host-1"
        self._setting_overrides["EQ_RABBITMQ_HOST_SECONDARY"] = "host-2"

        # When
        application = create_app(self._setting_overrides)

        # Then
        assert isinstance(application.eq["submitter"], RabbitMQSubmitter)
    def test_adds_gcs_submitter_to_the_application(self):
        # Given
        self._setting_overrides["EQ_SUBMISSION_BACKEND"] = "gcs"
        self._setting_overrides["EQ_GCS_SUBMISSION_BUCKET_ID"] = "123"

        # When
        with patch("google.cloud.storage.Client"):
            application = create_app(self._setting_overrides)

        # Then
        assert isinstance(application.eq["submitter"], GCSSubmitter)
    def test_setup_sql(self):
        self._setting_overrides['EQ_STORAGE_BACKEND'] = 'sql'

        db_string = 'sqlite:////tmp/test.db'
        self._setting_overrides['SQLALCHEMY_DATABASE_URI'] = db_string

        application = create_app(self._setting_overrides)
        self.assertFalse(application.config['SQLALCHEMY_TRACK_MODIFICATIONS'])
        self.assertEqual(60, application.config['SQLALCHEMY_POOL_RECYCLE'])
        self.assertEqual(db_string,
                         application.config['SQLALCHEMY_DATABASE_URI'])
Beispiel #19
0
def test_schema_cache_on_app_start_up():
    _load_schema_from_name.cache_clear()
    cache_info = _load_schema_from_name.cache_info()
    assert cache_info.currsize == 0
    assert cache_info.hits == 0

    # create app and load schemas into cache
    create_app()

    total_schemas = sum(
        len(schemas)
        for schemas in get_schema_path_map(include_test_schemas=True).values())
    cache_info = _load_schema_from_name.cache_info()
    assert cache_info.currsize > 0 and cache_info.currsize == total_schemas
    assert cache_info.hits == 0

    # loads schema again to fetch from cache
    cache_questionnaire_schemas()
    cache_info = _load_schema_from_name.cache_info()
    assert cache_info.currsize == total_schemas
    assert cache_info.hits == total_schemas
    def test_adds_gcs_feedback_to_the_application(self):
        # Given
        self._setting_overrides["EQ_FEEDBACK_BACKEND"] = "gcs"
        self._setting_overrides["EQ_GCS_FEEDBACK_BUCKET_ID"] = "123456"

        # When
        with patch("google.cloud.storage.Client"):
            application = create_app(self._setting_overrides)

        # Then
        assert isinstance(application.eq["feedback_submitter"],
                          GCSFeedbackSubmitter)
Beispiel #21
0
    def test_adds_logging_of_request_ids(self):
        with patch('app.setup.logger') as logger:
            self._setting_overrides.update({
                'EQ_DEV_MODE': True,
                'EQ_APPLICATION_VERSION': False
            })
            application = create_app(self._setting_overrides)

            application.test_client().get('/')
            self.assertEqual(1, logger.new.call_count)
            _, kwargs = logger.new.call_args
            self.assertTrue(UUID(kwargs['request_id'], version=4))
    def test_csp_policy_headers(self):
        cdn_url = "https://cdn.test.domain"
        address_lookup_api_url = "https://ai.test.domain"
        self._setting_overrides = {
            "EQ_ENABLE_LIVE_RELOAD": False,
            "CDN_URL": cdn_url,
            "ADDRESS_LOOKUP_API_URL": address_lookup_api_url,
        }

        with create_app(self._setting_overrides).test_client() as client:
            headers = client.get(
                "/",
                headers={
                    "X-Forwarded-Proto": "https"
                },  # set protocal so that talisman sets HSTS headers
            ).headers

            csp_policy_parts = headers["Content-Security-Policy"].split("; ")
            self.assertIn(f"default-src 'self' {cdn_url}", csp_policy_parts)
            self.assertIn(
                "script-src 'self' https://www.googletagmanager.com https://www.google-analytics.com "
                f"https://ssl.google-analytics.com 'unsafe-inline' {cdn_url} 'nonce-{request.csp_nonce}'",
                csp_policy_parts,
            )
            self.assertIn(
                f"style-src 'self' https://tagmanager.google.com https://fonts.googleapis.com 'unsafe-inline' {cdn_url}",
                csp_policy_parts,
            )
            self.assertIn(
                f"img-src 'self' data: https://www.google-analytics.com https://ssl.gstatic.com https://www.gstatic.com {cdn_url}",
                csp_policy_parts,
            )
            self.assertIn(
                f"font-src 'self' data: https://fonts.gstatic.com {cdn_url}",
                csp_policy_parts,
            )
            self.assertIn("frame-src https://www.googletagmanager.com",
                          csp_policy_parts)
            self.assertIn(
                f"connect-src 'self' https://www.google-analytics.com {cdn_url} {address_lookup_api_url}",
                csp_policy_parts,
            )
            self.assertIn(
                "object-src 'none'",
                csp_policy_parts,
            )
            self.assertIn(
                "base-uri 'none'",
                csp_policy_parts,
            )
Beispiel #23
0
    def setUp(self):
        self._ds = patch("app.setup.datastore.Client", MockDatastore)
        self._ds.start()

        self._redis = patch("app.setup.redis.Redis", fakeredis.FakeStrictRedis)
        self._redis.start()

        setting_overrides = {"LOGIN_DISABLED": self.LOGIN_DISABLED}
        setting_overrides.update(self.setting_overrides)
        self._app = create_app(setting_overrides)

        self._app.config["SERVER_NAME"] = "test.localdomain"
        self._app_context = self._app.app_context()
        self._app_context.push()
Beispiel #24
0
    def test_versioned_url_for_regular_assets(self):
        self._setting_overrides.update({
            'EQ_MINIMIZE_ASSETS': False,
            'EQ_APPLICATION_VERSION': False,
        })
        application = create_app(self._setting_overrides)
        application.config['SERVER_NAME'] = 'test'

        with application.app_context(), self.override_settings():
            self.assertEqual('http://test/s/some.css?q=False',
                             versioned_url_for('static', filename='some.css'))

            self.assertEqual('http://test/s/some.js?q=False',
                             versioned_url_for('static', filename='some.js'))
    def test_adds_pub_sub_to_the_application(self):
        # Given
        self._setting_overrides["EQ_PUBLISHER_BACKEND"] = "pubsub"
        self._setting_overrides["EQ_FULFILMENT_TOPIC_ID"] = "123"

        # When
        with patch(
                "app.publisher.publisher.google.auth._default._get_explicit_environ_credentials",
                return_value=(Mock(), "test-project-id"),
        ):
            application = create_app(self._setting_overrides)

        # Then
        assert isinstance(application.eq["publisher"], PubSubPublisher)
    def test_adds_logging_of_span_and_trace(self):
        with patch("app.setup.logger") as logger:
            self._setting_overrides.update({"EQ_APPLICATION_VERSION": False})
            application = create_app(self._setting_overrides)

            x_cloud_headers = {
                "X-Cloud-Trace-Context":
                "0123456789/0123456789012345678901;o=1"
            }
            application.test_client().get("/", headers=x_cloud_headers)

            self.assertEqual(1, logger.bind.call_count)
            _, kwargs = logger.bind.call_args
            self.assertTrue(kwargs["span"] == "0123456789012345678901")
            self.assertTrue(kwargs["trace"] == "0123456789")
    def test_adds_cloud_task_publisher_to_the_application(self):
        self._setting_overrides[
            "EQ_SUBMISSION_CONFIRMATION_BACKEND"] = "cloud-tasks"
        self._setting_overrides[
            "EQ_SUBMISSION_CONFIRMATION_CLOUD_FUNCTION_NAME"] = "test"

        # When
        with patch(
                "google.auth._default._get_explicit_environ_credentials",
                return_value=(Mock(), "test-project-id"),
        ):
            application = create_app(self._setting_overrides)

        # Then
        assert isinstance(application.eq["cloud_tasks"], CloudTaskPublisher)
    def setUp(self):
        self._ddb = mock_dynamodb2()
        self._ddb.start()

        setting_overrides = {
            'SQLALCHEMY_DATABASE_URI': 'sqlite://',
            'LOGIN_DISABLED': self.LOGIN_DISABLED,
            'EQ_DYNAMODB_ENDPOINT': None,
        }
        self._app = create_app(setting_overrides)

        self._app.config['SERVER_NAME'] = 'test.localdomain'
        self._app_context = self._app.app_context()
        self._app_context.push()

        setup_tables()
Beispiel #29
0
    def test_enforces_secure_headers(self):
        self._setting_overrides["EQ_ENABLE_LIVE_RELOAD"] = False

        with create_app(self._setting_overrides).test_client() as client:
            headers = client.get(
                "/",
                headers={
                    "X-Forwarded-Proto": "https"
                },  # set protocal so that talisman sets HSTS headers
            ).headers

            self.assertEqual("no-cache, no-store, must-revalidate",
                             headers["Cache-Control"])
            self.assertEqual("no-cache", headers["Pragma"])
            self.assertEqual(
                "max-age=31536000; includeSubDomains",
                headers["Strict-Transport-Security"],
            )
            self.assertEqual("DENY", headers["X-Frame-Options"])
            self.assertEqual("1; mode=block", headers["X-Xss-Protection"])
            self.assertEqual("nosniff", headers["X-Content-Type-Options"])

            csp_policy_parts = headers["Content-Security-Policy"].split("; ")
            self.assertIn("default-src 'self' https://cdn.ons.gov.uk",
                          csp_policy_parts)
            self.assertIn(
                f"script-src 'self' https://cdn.ons.gov.uk https://www.googletagmanager.com 'unsafe-inline' 'unsafe-eval' 'nonce-{request.csp_nonce}'",
                csp_policy_parts,
            )
            self.assertIn(
                "style-src 'self' https://cdn.ons.gov.uk https://tagmanager.google.com https://fonts.googleapis.com 'unsafe-inline'",
                csp_policy_parts,
            )
            self.assertIn(
                "img-src 'self' data: https://cdn.ons.gov.uk https://www.google-analytics.com https://ssl.gstatic.com https://www.gstatic.com",
                csp_policy_parts,
            )
            self.assertIn(
                "font-src 'self' data: https://cdn.ons.gov.uk https://fonts.gstatic.com",
                csp_policy_parts,
            )
            self.assertIn("frame-src https://www.googletagmanager.com",
                          csp_policy_parts)
            self.assertIn(
                "connect-src 'self' https://cdn.ons.gov.uk https://cdn.eq.census-gcp.onsdigital.uk",
                csp_policy_parts,
            )
    def test_enforces_secure_headers(self):
        self._setting_overrides["EQ_ENABLE_LIVE_RELOAD"] = False

        with create_app(self._setting_overrides).test_client() as client:
            headers = client.get(
                "/",
                headers={
                    "X-Forwarded-Proto": "https"
                },  # set protocal so that talisman sets HSTS headers
            ).headers

            self.assertEqual("no-cache, no-store, must-revalidate",
                             headers["Cache-Control"])
            self.assertEqual("no-cache", headers["Pragma"])
            self.assertEqual(
                "max-age=31536000; includeSubDomains",
                headers["Strict-Transport-Security"],
            )
            self.assertEqual("DENY", headers["X-Frame-Options"])
            self.assertEqual("1; mode=block", headers["X-Xss-Protection"])
            self.assertEqual("nosniff", headers["X-Content-Type-Options"])