From de11b86060ab0c19e40953784e181453f0ccb2eb Mon Sep 17 00:00:00 2001 From: Dan Guido Date: Sun, 22 Feb 2026 02:40:17 -0800 Subject: [PATCH] fix: detect missing SECP384R1 early and fix community.crypto compatibility (#14970) Add pre-flight check in main.yml that catches missing cryptography/SECP384R1 before deployment starts, replacing the cryptic error from community.crypto internals with an actionable message pointing users to run ./algo or uv sync. Root cause of the CI ipsec/both test failures: cryptography 46.0.5 wraps the ec module with _ModuleWithDeprecations (for SECT curve deprecation), which breaks community.crypto's ec.__dict__.get("SECP384R1") lookup. The fix in community.crypto 3.1.1 uses getattr() instead. Changes: - Add SECP384R1 pre-flight check to main.yml (conditional on ipsec_enabled) - Add cryptography>=42.0.0 as explicit dependency in pyproject.toml - Upgrade community.crypto to >=3.1.1 (fixes __dict__ vs getattr bug) - Add ansible-galaxy collection install step to CI - Use venv Python interpreter for local deployments in add_host tasks Co-authored-by: Claude Opus 4.6 --- .github/workflows/integration-tests.yml | 3 +++ deploy_client.yml | 2 +- main.yml | 18 ++++++++++++++++++ playbooks/cloud-post.yml | 2 +- pyproject.toml | 1 + requirements.yml | 2 +- users.yml | 2 +- uv.lock | 2 ++ 8 files changed, 28 insertions(+), 4 deletions(-) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index da7661b8..f8200182 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -56,6 +56,9 @@ jobs: - name: Install Python dependencies run: uv sync + - name: Install Ansible collections + run: uv run ansible-galaxy collection install -r requirements.yml + - name: Create test configuration run: | cat > integration-test.cfg << EOF diff --git a/deploy_client.yml b/deploy_client.yml index ca89c40d..167fcc36 100644 --- a/deploy_client.yml +++ b/deploy_client.yml @@ -13,7 +13,7 @@ ansible_ssh_user: "{{ 'root' if client_ip == 'localhost' else ssh_user }}" vpn_user: "{{ vpn_user }}" IP_subject_alt_name: "{{ server_ip }}" - ansible_python_interpreter: /usr/bin/python3 + ansible_python_interpreter: "{% if client_ip == 'localhost' %}{{ ansible_playbook_python }}{% else %}/usr/bin/python3{% endif %}" - name: Configure the client and install required software hosts: client-host diff --git a/main.yml b/main.yml index 4764ed56..925e953a 100644 --- a/main.yml +++ b/main.yml @@ -60,6 +60,24 @@ You must update the requirements to use this version of Algo. Try to run: uv sync + - name: Check cryptography library SECP384R1 support + command: > + {{ ansible_playbook_python }} -c + "from cryptography.hazmat.primitives.asymmetric.ec import SECP384R1" + changed_when: false + failed_when: false + register: _crypto_check + when: ipsec_enabled | default(true) | bool + + - name: Verify cryptography library supports IPsec requirements + assert: + that: _crypto_check.rc == 0 + msg: > + The Python cryptography library is missing or does not support SECP384R1. + IPsec/IKEv2 requires the cryptography package with elliptic curve support. + Fix: Run ./algo (manages dependencies automatically) or: uv sync && uv run ansible-playbook main.yml + when: ipsec_enabled | default(true) | bool + - name: Include prompts playbook import_playbook: input.yml diff --git a/playbooks/cloud-post.yml b/playbooks/cloud-post.yml index e03a8f5e..f10bf70e 100644 --- a/playbooks/cloud-post.yml +++ b/playbooks/cloud-post.yml @@ -10,7 +10,7 @@ ansible_connection: "{% if cloud_instance_ip == 'localhost' %}local{% else %}ssh{% endif %}" ansible_ssh_user: "{{ ansible_ssh_user | default('root') }}" ansible_ssh_port: "{{ ansible_ssh_port | default(22) }}" - ansible_python_interpreter: /usr/bin/python3 + ansible_python_interpreter: "{% if cloud_instance_ip == 'localhost' %}{{ ansible_playbook_python }}{% else %}/usr/bin/python3{% endif %}" algo_provider: "{{ algo_provider }}" algo_server_name: "{{ algo_server_name }}" algo_ondemand_cellular: "{{ algo_ondemand_cellular }}" diff --git a/pyproject.toml b/pyproject.toml index bc61b0d2..ff6c56e9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,6 +9,7 @@ version = "2.0.0-beta" requires-python = ">=3.11" dependencies = [ "ansible==12.3.0", + "cryptography>=42.0.0", "jinja2>=3.1.6", "netaddr==1.3.0", "pyyaml>=6.0.2", diff --git a/requirements.yml b/requirements.yml index d4f395e7..8fc94d87 100644 --- a/requirements.yml +++ b/requirements.yml @@ -7,7 +7,7 @@ collections: - name: community.general version: "==11.1.0" - name: community.crypto - version: "==3.0.3" + version: ">=3.1.1" - name: openstack.cloud version: "==2.4.1" - name: linode.cloud diff --git a/users.yml b/users.yml index a3f95d12..ad942e19 100644 --- a/users.yml +++ b/users.yml @@ -142,7 +142,7 @@ groups: vpn-host ansible_ssh_user: "{{ server_user | default('root') }}" ansible_connection: "{% if algo_server == 'localhost' %}local{% else %}ssh{% endif %}" - ansible_python_interpreter: /usr/bin/python3 + ansible_python_interpreter: "{% if algo_server == 'localhost' %}{{ ansible_playbook_python }}{% else %}/usr/bin/python3{% endif %}" CA_password: "{{ CA_password | default(omit) }}" rescue: - include_tasks: playbooks/rescue.yml diff --git a/uv.lock b/uv.lock index 1dddf737..ee49d1ec 100644 --- a/uv.lock +++ b/uv.lock @@ -27,6 +27,7 @@ version = "2.0.0b0" source = { editable = "." } dependencies = [ { name = "ansible" }, + { name = "cryptography" }, { name = "jinja2" }, { name = "netaddr" }, { name = "pyyaml" }, @@ -79,6 +80,7 @@ requires-dist = [ { name = "azure-mgmt-network", marker = "extra == 'azure'", specifier = ">=25.0.0" }, { name = "azure-mgmt-resource", marker = "extra == 'azure'", specifier = ">=23.0.0" }, { name = "boto3", marker = "extra == 'aws'", specifier = ">=1.34.0" }, + { name = "cryptography", specifier = ">=42.0.0" }, { name = "cs", marker = "extra == 'cloudstack'", specifier = ">=3.0.0" }, { name = "google-auth", marker = "extra == 'gcp'", specifier = ">=2.28.0" }, { name = "hcloud", marker = "extra == 'hetzner'", specifier = ">=1.33.0" },