diff --git a/.github/actions/setup-project/action.yml b/.github/actions/setup-project/action.yml index b2d582986..db1540fad 100644 --- a/.github/actions/setup-project/action.yml +++ b/.github/actions/setup-project/action.yml @@ -9,10 +9,10 @@ runs: sudo apt-get update \ && sudo apt-get install -y --no-install-recommends \ libcurl4-openssl-dev - - name: Set up Python 3.12 + - name: Set up Python 3.12.3 uses: actions/setup-python@v4 with: - python-version: "3.12" + python-version: "3.12.3" - name: Install poetry shell: bash run: pip install poetry diff --git a/app/__init__.py b/app/__init__.py index e99a5ae51..76f3664cd 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -233,6 +233,24 @@ def create_app(application): ) logging.init_app(application) + # Hopefully will help identify if there is a race condition causing the CSRF errors + # that we have occasionally seen in our environments. + for key in ("SECRET_KEY", "DANGEROUS_SALT"): + try: + value = application.config[key] + except KeyError: + application.logger.error(f"Env Var {key} doesn't exist.") + else: + try: + data_len = len(value.strip()) + except (TypeError, AttributeError): + application.logger.error(f"Env Var {key} invalid type: {type(value)}") + else: + if data_len: + application.logger.info(f"Env Var {key} is a non-zero length.") + else: + application.logger.error(f"Env Var {key} is empty.") + login_manager.login_view = "main.sign_in" login_manager.login_message_category = "default" login_manager.session_protection = None diff --git a/app/main/views/register.py b/app/main/views/register.py index a7e188f0c..761582b3d 100644 --- a/app/main/views/register.py +++ b/app/main/views/register.py @@ -130,10 +130,10 @@ def put_invite_data_in_redis( ): ttl = 60 * 15 # 15 minutes - redis_client.raw_set(f"invitedata-{state}", json.dumps(invite_data), ex=ttl) - redis_client.raw_set(f"user_email-{state}", user_email, ex=ttl) - redis_client.raw_set(f"user_uuid-{state}", user_uuid, ex=ttl) - redis_client.raw_set( + redis_client.set(f"invitedata-{state}", json.dumps(invite_data), ex=ttl) + redis_client.set(f"user_email-{state}", user_email, ex=ttl) + redis_client.set(f"user_uuid-{state}", user_uuid, ex=ttl) + redis_client.set( f"invited_user_email_address-{state}", invited_user_email_address, ex=ttl, diff --git a/deploy-config/production.yml b/deploy-config/production.yml index 18b5cfdcc..b38094f28 100644 --- a/deploy-config/production.yml +++ b/deploy-config/production.yml @@ -1,6 +1,6 @@ env: production instances: 2 -memory: 1G +memory: 2G public_admin_route: beta.notify.gov cloud_dot_gov_route: notify.app.cloud.gov redis_enabled: 1 diff --git a/gunicorn_config.py b/gunicorn_config.py index 4f928a467..f9eb4f17d 100644 --- a/gunicorn_config.py +++ b/gunicorn_config.py @@ -5,7 +5,10 @@ import multiprocessing import gunicorn # Let gunicorn figure out the right number of workers -workers = multiprocessing.cpu_count() * 2 + 1 +# The recommended formula is cpu_count() * 2 + 1 +# but we have an unusual configuration with a lot of cpus and not much memory +# so adjust it. +workers = multiprocessing.cpu_count() worker_class = "eventlet" bind = "0.0.0.0:{}".format(os.getenv("PORT")) disable_redirect_access_to_syslog = True @@ -16,23 +19,3 @@ def worker_abort(worker): worker.log.info("worker received ABORT") for stack in sys._current_frames().values(): worker.log.error("".join(traceback.format_stack(stack))) - - -# This issue is fixed in the 22.0.0 release, which we are using -# See github issue for details -# def fix_ssl_monkeypatching(): -# """ -# eventlet works by monkey-patching core IO libraries (such as ssl) to be non-blocking. However, there's currently -# a bug: In the normal socket library it may throw a timeout error as a `socket.timeout` exception. However -# eventlet.green.ssl's patch raises an ssl.SSLError('timed out',) instead. redispy handles socket.timeout but not -# ssl.SSLError, so we solve this by monkey patching the monkey patching code to raise the correct exception type -# :scream: -# https://github.com/eventlet/eventlet/issues/692 -# """ -# # this has probably already been called somewhere in gunicorn internals, however, to be sure, we invoke it again. -# # eventlet.monkey_patch can be called multiple times without issue -# eventlet.monkey_patch() -# eventlet.green.ssl.timeout_exc = socket.timeout - - -# fix_ssl_monkeypatching() diff --git a/poetry.lock b/poetry.lock index d73c31d04..f77b03707 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1681,6 +1681,7 @@ files = [ {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fbb160554e319f7b22ecf530a80a3ff496d38e8e07ae763b9e82fadfe96f273"}, {file = "msgpack-1.0.8-cp39-cp39-win32.whl", hash = "sha256:f9af38a89b6a5c04b7d18c492c8ccf2aee7048aff1ce8437c4683bb5a1df893d"}, {file = "msgpack-1.0.8-cp39-cp39-win_amd64.whl", hash = "sha256:ed59dd52075f8fc91da6053b12e8c89e37aa043f8986efd89e61fae69dc1b011"}, + {file = "msgpack-1.0.8-py3-none-any.whl", hash = "sha256:24f727df1e20b9876fa6e95f840a2a2651e34c0ad147676356f4bf5fbb0206ca"}, {file = "msgpack-1.0.8.tar.gz", hash = "sha256:95c02b0e27e706e48d0e5426d1710ca78e0f0628d6e89d5b5a5b91a5f12274f3"}, ] diff --git a/runtime.txt b/runtime.txt index 64f28603a..4ddc7cd66 100644 --- a/runtime.txt +++ b/runtime.txt @@ -1 +1 @@ -python-3.12.x +python-3.12.3 diff --git a/tests/app/main/views/test_index.py b/tests/app/main/views/test_index.py index 1e08cd606..154106250 100644 --- a/tests/app/main/views/test_index.py +++ b/tests/app/main/views/test_index.py @@ -19,9 +19,12 @@ def test_non_logged_in_user_can_see_homepage( "Reach people where they are with government-powered text messages" ) - assert page.select_one( - "a.usa-button.login-button.login-button--primary.margin-right-2" - ).text == "Sign in with \n" + assert ( + page.select_one( + "a.usa-button.login-button.login-button--primary.margin-right-2" + ).text + == "Sign in with \n" + ) assert page.select_one("meta[name=description]") is not None # This area is hidden for the pilot # assert normalize_spaces(page.select_one('#whos-using-notify').text) == ( diff --git a/tests/end_to_end/test_landing_and_sign_in_pages.py b/tests/end_to_end/test_landing_and_sign_in_pages.py index 513269f51..4dcab63a1 100644 --- a/tests/end_to_end/test_landing_and_sign_in_pages.py +++ b/tests/end_to_end/test_landing_and_sign_in_pages.py @@ -31,7 +31,7 @@ def test_landing_page(end_to_end_context): expect(benefits_studio_email).to_be_visible() # Check to make sure the sign-in button and email links are correct. - href_value = sign_in_button.get_attribute('href') + href_value = sign_in_button.get_attribute("href") assert href_value is not None, "The sign-in button does not have an href attribute" expect(benefits_studio_email).to_have_attribute( "href", "mailto:tts-benefits-studio@gsa.gov"