Skip to content

feat(vpn): fail-fast reachability check + timeouts for VPN-gated targets (ADR-011) - #172

Open
vsutra-admin wants to merge 1 commit into
ansible-deployfrom
infra/vpn-connectivity-adr011
Open

feat(vpn): fail-fast reachability check + timeouts for VPN-gated targets (ADR-011)#172
vsutra-admin wants to merge 1 commit into
ansible-deployfrom
infra/vpn-connectivity-adr011

Conversation

@vsutra-admin

Copy link
Copy Markdown

Summary

ADR-011 VPN connectivity (Virtual-Sutra/openspecimen-ansible epic #143): operators connect the VPN tunnel manually on the controller before triggering a deploy — Ansible/Jenkins never drives openconnect, computes a TOTP code, or stores a VPN credential. This PR adds the pieces of that model that belong in the core playbook:

  • ansible.cfg: SSH + privilege_escalation timeout 10s → 60s. The ocserv AnyConnect PoC (PR fix(tomcat): adopt a legacy unmarked datasource block in shared context.xml #149 in openspecimen-ansible) found VPN tunnel round-trip latency (~200ms+) tight enough to fail privilege escalation before the connection even finished setting up — harmless for fast/direct connections, which never come close to the limit.
  • site.yml: a new pre-flight play, gated on an opt-in vpn_required customer var (default off), that waits for the target's SSH port before the main play's implicit fact-gathering would otherwise be the first thing to hit a down tunnel — turns a deep, generic SSH timeout into a clear "check the tunnel" failure instead.
  • inventory/customers/ocserv-openspecimen/: test customer profile for the ocserv AnyConnect PoC target, vpn_required: true.

No Jenkinsfile changes, no new credentials, no openconnect/TOTP automation anywhere in this repo — that's intentionally out of scope.

Related: Virtual-Sutra/openspecimen-ansible#143

Test plan

  • ansible-playbook site.yml --syntax-check -i inventory/customers/ocserv-openspecimen/
  • Live E2E: operator connects the VPN tunnel, deploy runs against ocserv-openspecimen, pre-flight check passes; negative test with the tunnel disconnected produces the pre-flight failure instead of a deep SSH timeout

…ets (ADR-011)

Operators connect the VPN tunnel manually on the controller before
triggering a deploy - Ansible/Jenkins never drives openconnect itself
(see Virtual-Sutra/openspecimen-ansible#143). This adds the pieces that
belong in the core playbook for that model:

- inventory/customers/ocserv-openspecimen/hosts: ansible_timeout +
  ansible_become_timeout 10s -> 60s, scoped to this VPN-gated customer
  only (not a global ansible.cfg change - direct/EICE customers should
  keep failing fast on a genuinely unreachable host). The ocserv PoC
  found VPN tunnel latency (~200ms+) tight enough to fail privilege
  escalation before the connection even finished setting up.
- site.yml: a new pre-flight play (vpn_required opt-in, default off)
  that waits for the target's SSH port before the main play's implicit
  fact gathering would otherwise be the first thing to hit a down
  tunnel, then fails with a clear "check the tunnel" message (matching
  verify-customer.yml's existing assert/fail_msg convention) instead of
  a deep, generic SSH timeout.
- inventory/customers/ocserv-openspecimen/: test profile for the ocserv
  AnyConnect PoC target, vpn_required: true.
@vsutra-admin
vsutra-admin force-pushed the infra/vpn-connectivity-adr011 branch from 68ee247 to e1bf172 Compare August 11, 2026 07:04
@vsutra-admin

Copy link
Copy Markdown
Author

🤖 Automated review

Findings below were applied before this comment was posted (branch was amended + force-pushed).

Simplify

  • Scoping (reuse + altitude, both flagged independently): the original ansible.cfg timeout bump was global, affecting every customer's connection/become timeout, not just VPN-gated ones — a genuinely-down direct/EICE target would now take up to 6x longer to fail. Fixed: moved ansible_timeout/ansible_become_timeout into inventory/customers/ocserv-openspecimen/hosts [all:vars], scoped to this customer only. ansible.cfg is now untouched by this PR.
  • Dead state: openspecimen_paid_plugins: [] / openspecimen_customer_plugins: [] in the new customer's group_vars/openspecimen.yml just restated the existing global defaults from inventory/group_vars/all.yml. Fixed: removed both lines.
  • Efficiency / altitude on the pre-flight play itself: confirmed clean — connection: local + gather_facts: false means no SSH/fact-gathering overhead, and the when: vpn_required gate makes it a no-op for every non-VPN customer.

Code review

  • Missing remediation message (reuse gap): the original wait_for task relied on Ansible's own generic timeout error instead of the codebase's established assert/fail_msg convention (see verify-customer.yml's "Fail if VM is unreachable" task). Fixed: added a follow-up ansible.builtin.fail task with a message pointing at docs/vpn/ and telling the operator to confirm the tunnel is connected, matching that existing pattern.
  • Hardcoded pre-flight timeout: the wait_for timeout was a fixed 15 with no override, in some tension with the PR's own "VPN latency varies" premise. Fixed: now {{ vpn_preflight_timeout | default(15) }}, overridable per customer.
  • Pre-flight check is TCP-only, not an auth/become check: correct as designed (a full SSH+become handshake here would duplicate the main play) — tightened the comment so it doesn't overclaim what the check covers.
  • Per-instance vpn_required granularity (a customer with a mixed VPN/non-VPN host group has no documented per-host override path) — left as-is; normal Ansible host_vars precedence already supports it, and no current customer needs it. Flagging for future reference rather than building it speculatively.
  • No security, backwards-compat, or test-coverage issues beyond the pre-existing lack of CI/lint in this repo (unrelated to this diff).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants