From aaefe7a400522607484a51ab9377d22f39177d0b Mon Sep 17 00:00:00 2001 From: Vaibhav Gulati Date: Tue, 27 Oct 2026 12:01:23 +0000 Subject: [PATCH] fix: install each service's pinned pip into its venv xqueue, xqwatcher, insights and analytics_api venvs got pip from ensurepip/virtualenv (24.x), or from the COMMON_PIP_VERSION pin (24.0) for edx_django_service. pip vendors its own certifi, so these hosts kept trusting the emSign root removed in certifi 2026.10.19 (eMudhra incident) for any pip install. Install the app repo's requirements/pip.txt (pip==26.2.2) into the venv before the app requirements. edx_django_service gets an overridable edx_django_service_pip_install_args that defaults to the existing COMMON_PIP_VERSION pin, so other services are unchanged. Ticket: LP-1401 Co-Authored-By: Claude Opus 5.5 --- playbooks/roles/analytics_api/meta/main.yml | 1 + .../roles/edx_django_service/defaults/main.yml | 3 +++ playbooks/roles/edx_django_service/tasks/main.yml | 2 +- playbooks/roles/insights/defaults/main.yml | 1 + playbooks/roles/xqueue/defaults/main.yml | 1 + playbooks/roles/xqueue/tasks/main.yml | 15 +++++++++++++++ playbooks/roles/xqwatcher/defaults/main.yml | 1 + .../roles/xqwatcher/tasks/deploy_watcher.yml | 14 ++++++++++++++ 8 files changed, 37 insertions(+), 1 deletion(-) diff --git a/playbooks/roles/analytics_api/meta/main.yml b/playbooks/roles/analytics_api/meta/main.yml index b3c4b0ad0..4c4ccf013 100644 --- a/playbooks/roles/analytics_api/meta/main.yml +++ b/playbooks/roles/analytics_api/meta/main.yml @@ -27,6 +27,7 @@ dependencies: edx_django_service_name: '{{ analytics_api_service_name }}' edx_django_service_user: '{{ analytics_api_user }}' edx_django_service_home: '{{ COMMON_APP_DIR }}/{{ analytics_api_service_name }}' + edx_django_service_pip_install_args: '-r {{ COMMON_APP_DIR }}/{{ analytics_api_service_name }}/{{ analytics_api_service_name }}/requirements/pip.txt' edx_django_service_config_overrides: '{{ analytics_api_service_config_overrides }}' edx_django_service_nginx_port: '{{ ANALYTICS_API_NGINX_PORT }}' edx_django_service_nginx_read_timeout: 300 diff --git a/playbooks/roles/edx_django_service/defaults/main.yml b/playbooks/roles/edx_django_service/defaults/main.yml index 0d0ab72cb..373359b4a 100644 --- a/playbooks/roles/edx_django_service/defaults/main.yml +++ b/playbooks/roles/edx_django_service/defaults/main.yml @@ -33,6 +33,9 @@ edx_django_service_app_config_file: "{{ COMMON_CFG_DIR }}/{{ edx_django_service edx_django_service_code_dir: '{{ edx_django_service_home }}/{{ edx_django_service_name }}' edx_django_service_venv_dir: '{{ edx_django_service_home }}/venvs/{{ edx_django_service_name }}' edx_django_service_venv_bin_dir: '{{ edx_django_service_venv_dir }}/bin' +# Arguments for the "Pin pip" step. Services can override this, for example +# with "-r /requirements/pip.txt" to follow the repo's own pin. +edx_django_service_pip_install_args: 'pip=={{ COMMON_PIP_VERSION }}' edx_django_service_nodeenv_dir: '{{ edx_django_service_home }}/nodeenvs/{{ edx_django_service_name }}' edx_django_service_nodeenv_bin: '{{ edx_django_service_nodeenv_dir }}/bin' diff --git a/playbooks/roles/edx_django_service/tasks/main.yml b/playbooks/roles/edx_django_service/tasks/main.yml index da7367186..767a29335 100644 --- a/playbooks/roles/edx_django_service/tasks/main.yml +++ b/playbooks/roles/edx_django_service/tasks/main.yml @@ -220,7 +220,7 @@ - install:system-requirements - name: Pin pip to a specific version. - command: "{{ edx_django_service_venv_dir }}/bin/pip install pip=={{ COMMON_PIP_VERSION }}" + command: "{{ edx_django_service_venv_dir }}/bin/pip install {{ edx_django_service_pip_install_args }}" become_user: "{{ edx_django_service_user }}" when: not edx_django_service_enable_experimental_docker_shim tags: diff --git a/playbooks/roles/insights/defaults/main.yml b/playbooks/roles/insights/defaults/main.yml index 4902164a4..cc338e6d5 100644 --- a/playbooks/roles/insights/defaults/main.yml +++ b/playbooks/roles/insights/defaults/main.yml @@ -250,6 +250,7 @@ insights_manage: "{{ insights_code_dir }}/manage.py" insights_requirements_base: "{{ insights_code_dir }}/requirements" insights_requirements: + - pip.txt - production.txt - optional.txt diff --git a/playbooks/roles/xqueue/defaults/main.yml b/playbooks/roles/xqueue/defaults/main.yml index c57c7b65b..ca18ac43b 100644 --- a/playbooks/roles/xqueue/defaults/main.yml +++ b/playbooks/roles/xqueue/defaults/main.yml @@ -176,6 +176,7 @@ xqueue_environment: XQUEUE_CFG: '{{ COMMON_CFG_DIR }}/xqueue.yml' xqueue_requirements_file: "{{ xqueue_code_dir }}/requirements.txt" +xqueue_pip_requirements_file: "{{ xqueue_code_dir }}/requirements/pip.txt" xqueue_openstack_requirements_file: "{{ xqueue_code_dir }}/openstack-requirements.txt" # These packages are required for the xqueue server, diff --git a/playbooks/roles/xqueue/tasks/main.yml b/playbooks/roles/xqueue/tasks/main.yml index 15c666348..a3b8b22af 100644 --- a/playbooks/roles/xqueue/tasks/main.yml +++ b/playbooks/roles/xqueue/tasks/main.yml @@ -69,6 +69,21 @@ - install - install:system-requirements +# The venv gets whatever pip python3.12's ensurepip bundles, so install the +# repo's pinned pip before the app requirements. +- name: "Install pinned pip into the python3.12 venv" + pip: + requirements: "{{ xqueue_pip_requirements_file }}" + virtualenv: "{{ xqueue_venv_dir }}" + virtualenv_command: 'python3.12 -m venv' + state: present + extra_args: "-i {{ COMMON_PYPI_MIRROR_URL }} --exists-action w" + become_user: "{{ xqueue_user }}" + when: xqueue_use_python312 + tags: + - install + - install:app-requirements + - name: "Install python3.12 requirements" pip: requirements: "{{ xqueue_requirements_file }}" diff --git a/playbooks/roles/xqwatcher/defaults/main.yml b/playbooks/roles/xqwatcher/defaults/main.yml index a6cc60ca7..dadf022a9 100644 --- a/playbooks/roles/xqwatcher/defaults/main.yml +++ b/playbooks/roles/xqwatcher/defaults/main.yml @@ -100,6 +100,7 @@ xqwatcher_use_python312: true xqwatcher_conf_dir: "{{ xqwatcher_app_dir }}" xqwatcher_requirements_file: "{{ xqwatcher_code_dir }}/requirements/production.txt" +xqwatcher_pip_requirements_file: "{{ xqwatcher_code_dir }}/requirements/pip.txt" xqwatcher_log_dir: "{{ COMMON_LOG_DIR }}/{{ xqwatcher_service_name }}" xqwatcher_module: "xqueue_watcher" diff --git a/playbooks/roles/xqwatcher/tasks/deploy_watcher.yml b/playbooks/roles/xqwatcher/tasks/deploy_watcher.yml index 6e52b6d8d..ca3973a5a 100644 --- a/playbooks/roles/xqwatcher/tasks/deploy_watcher.yml +++ b/playbooks/roles/xqwatcher/tasks/deploy_watcher.yml @@ -2,6 +2,20 @@ # The watcher can watch one or many queues and dispatch submissions # to the appropriate grader which lives in a separate SCM repository. +# Install the repo's pinned pip first, rather than keeping the pip that +# virtualenv bundles. +- name: Install pinned pip + pip: + requirements: "{{ xqwatcher_pip_requirements_file }}" + virtualenv: "{{ xqwatcher_app_dir }}/venvs/{{ xqwatcher_service_name }}" + virtualenv_python: "{{ xqwatcher_python_version }}" + state: present + become: true + become_user: "{{ xqwatcher_user }}" + tags: + - install + - install:app-requirements + - name: Install application requirements pip: requirements: "{{ xqwatcher_requirements_file }}"