summaryrefslogtreecommitdiff
path: root/src
AgeCommit message (Collapse)Author
10 dayshttp-api-client: T8955: leave warning handling to the callerfix/T8955-http-api-verify-tlsYuriy Andamasov
Address the round-2 adversarial-review finding: warnings.catch_warnings() mutates the process-global filter list for the duration of the block (still the case on Python 3.13), so scoping suppression inside the library was not actually isolated. - http_api_client no longer touches warning filters at all. The _suppress_insecure_warning helper is removed and post() calls session.post directly again. The unused warnings, contextmanager and urllib3 imports are dropped. The class docstring now states that callers disabling verification own InsecureRequestWarning handling. The OSError wrapping and verify_tls validation are unchanged. - config_sync ignores InsecureRequestWarning in its __main__ block only, before opmode.run(). That one-shot op-mode process deliberately connects without verification (verify_tls=False) until T9396. Importing the module adds no filter. 🤖 Generated by [robots](https://vyos.io)
10 dayshttp-api-client: T8955: harden verify_tls handlingYuriy Andamasov
Address the adversarial-review findings on the TLS verification change: - Finding 1: validate ApiClientConfig.verify_tls in __post_init__. Only a bool or a non-empty CA bundle path is accepted; anything else (including "", None and ints) raises ValueError. requests treats "" as falsy and would silently disable verification. Strings are never coerced: "false" is a path, so callers must pass a real bool. - Finding 2: stop calling urllib3.disable_warnings() process-wide from ApiClient.__init__. InsecureRequestWarning is now ignored only around the request itself, via warnings.catch_warnings(), and only when verify_tls is False. post() is the only request path in the client. - Finding 3: wrap OSError (raised by requests' cert_verify for a missing CA bundle path) in ApiTransportError. The handler sits after the RequestException handlers, since those subclass OSError. - Finding 4: config-sync hard-codes verify_tls = False instead of reading an unmapped 'verify_tls' key from the runtime config, whose leaf values are strings. Mapping a CLI option to a bool or CA path is T9396. 🤖 Generated by [robots](https://vyos.io)
10 dayshttp-api-client: T8955: enable TLS verification by defaultYuriy Andamasov
ApiClientConfig.verify_tls defaulted to False and ApiClient unconditionally silenced urllib3's InsecureRequestWarning, so TLS peer verification was off by default. The sole consumer, src/op_mode/config_sync.py, builds the client without passing verify_tls and therefore connected to a *remote* secondary VyOS node over HTTPS without verifying the certificate -- a MITM exposure on the channel that carries the API key and the full configuration. - ApiClientConfig.verify_tls now defaults to True and accepts bool | str; a string is forwarded to requests as a CA bundle path (verify=<path>). - InsecureRequestWarning is suppressed only when verification is explicitly disabled (verify_tls is False), not when a CA path or True is set. - config_sync reads an optional verify_tls from the secondary runtime settings, defaulting to False to preserve current behaviour for self-signed secondaries. The insecurity is now explicit at the call site instead of hidden in the library default. Exposing a CA certificate (PKI reference) and peer fingerprint pinning under service config-sync secondary is follow-up T9396. 🤖 Generated by [robots](https://vyos.io)
12 dayspolicy: T9379: prefix-list duplicate check in linear timeAlex Kudentsov
verify() looked up each prefix-list rule in a list of the rules seen so far, which is quadratic in the size of the list and runs on every policy commit. verify() alone, run from the source on a workstation, took 41.8 s for a 40,000-rule list; on a 1.5.1 VM the check cost 0.08 s at 2,000 rules. Keep a set of the rules' sorted items instead. Every value under a prefix-list rule is a single leaf, so the key is hashable, and two keys are equal exactly when the rule dicts are: the same rules are flagged, with the same message. The workstation benchmark took 0.11 s.
13 daysMerge pull request #5515 from ordex/T9364-openvpn-dco-mtuChristian Breunig
T9364: openvpn: default the MTU to 1420 when DCO is enabled
14 daysMerge pull request #5483 from yzguy/wwan-modem-by-port-ownershipChristian Breunig
wwan: T7487: identify modem by port ownership, not interface number
2026-09-29openvpn: T9364: default the MTU to 1420 when DCO is enabledAntonio Quartulli
The ovpn Kernel module does no MSS clamping, so with a 1500 bytes MTU full sized packets get fragmented on the underlay. Add an "mtu" node, rendered as "tun-mtu". With "offload dco" it defaults to 1420, unless a raw tun-mtu/link-mtu/udp-mtu option is present. Reject "mtu" together with such an option, below 100, and below 1280 when IPv6 runs inside the tunnel.
2026-09-29Merge pull request #5491 from omnom62/T8989-hotfix-oidc_aud_validationJohn Estabrook
http-api: T8989: Hotfix to enforce audience validation if OIDC is configured
2026-09-29openvpn: T9363: multiply the site-to-site keepalive timeoutAntonio Quartulli
"failure-count" counts missed intervals, so the timeout it describes is interval * failure-count. Server mode renders and verifies it that way; site-to-site passed the bare count to "ping-restart", where it lands as seconds - 60s instead of 600s with the defaults. Render the product. That puts a timeout past the 86400 "ping-restart" accepts within reach, so verify() rejects it and the 5-to-6 migration clamps configurations already beyond it. This changes behaviour on upgrade: site-to-site tunnels now tolerate a longer silence, 600 seconds instead of 60 with the defaults.
2026-09-29Merge pull request #5397 from jeleel-muibi/t8999-openvpn-shared-secret-errorsChristian Breunig
openvpn: T8999: improve shared-secret reference errors
2026-09-29wwan: T7487: identify modem by port ownership, not interface numberAdam Smith
modem_index() in python/vyos/utils/wwan.py derived the ModemManager modem index straight from the interface name (wwan0 -> 0). The kernel-assigned WWAN interface number and ModemManager's own modem index are two independently enumerated values and are not guaranteed to match - on a box with more than one modem, they can enumerate in different orders, so modem index 0 does not necessarily own wwan0. Every function in this module funnels through modem_index() (start_modem_manager, modem_disconnect, modem_connect, and both admin-disconnect marker helpers), and is_wwan_connected() in vyos.utils.network had its own separate copy of the same assumption - so a single reversed enumeration order silently commands the wrong physical modem for every one of them. modem_index() now lists every modem ModemManager currently knows about and returns whichever one actually has ifname in its own port list, instead of assuming the correspondence. A modem that has not shown up on the bus yet looks the same as one that will never exist, so this waits up to the same modem_wait_timeout budget start_modem_manager() already gives a modem to become dialable, then returns None if nothing claimed the interface. is_wwan_connected() now calls the same resolver instead of keeping its own copy of the old assumption. None is a real, expected return now, not just a theoretical one - the three callers that previously assumed modem_index() always produced *a* string (right or wrong) are updated: start_modem_manager() bails out early (matching the tolerance its own caller's w.exists() check already has for hardware that isn't detected yet), modem_disconnect() and modem_connect() treat it as nothing to disconnect / a failed dial, matching each function's own existing return contract. show_wwan.py's modem_info() raises a clear, specific error instead, which its own top-level exception handler already reports cleanly. set_admin_disconnected()/clear_admin_disconnected() only ever used modem_index() to validate the interface name looks like a WWAN interface in the first place, so they're unaffected.
2026-09-29Merge pull request #5499 from c-po/wwan-improvementsChristian Breunig
wwan: T9350: possible dead interface after boot, disconnect does not stick
2026-09-29https: T8989: Hotfix to enforce audience settings with OIDC is configuredomnom62
2026-09-28Merge pull request #5503 from c-po/T9354Christian Breunig
op-mode: T9354: replace "reset connection" with "reconnect interface"
2026-09-28Merge pull request #5509 from c-po/pim-deleteJohn Estabrook
pim: T9362: prevent killing an already dead/non-existing PID
2026-09-28openvpn: T8999: improve shared-secret reference errorsJeleel Muibi
2026-09-28Merge pull request #5266 from MPStudyly/T8977_fix_haproxy_rebindDaniil Baturin
T8977: Fix regression with is_addr_assigned and is_listen_port_bind_service
2026-09-27pim: T9362: pim: prevent killing an already dead/non-existing PIDChristian Breunig
The daemon is not guaranteed to be running when PIM is removed - it may have never started, or already died.
2026-09-27pki: T9323: give elliptic curve keys their own constructorAntonio Quartulli
create_private_key() took one "size" for every key type, but the number means entirely different things per type: for RSA and DSA it is a modulus size, for EC it selects a curve. CodeQL is not path sensitive across the key_type comparison, so it follows the 256 an EC caller passes into the RSA and DSA branches that caller can never reach, and reports pki.py as generating 256 bit RSA and DSA keys. Build elliptic curve keys in create_ec_private_key() instead and route the op mode generator and the OpenVPN smoketest there, so no curve size ever enters the function that also builds RSA and DSA keys. create_private_key() now refuses a key type it does not build rather than returning None, so a caller cannot drift back into the old shape unnoticed.
2026-09-26Merge pull request #5495 from xTITUSMAXIMUSX/T9303-vpp-ipsec-accelerationChristian Breunig
ipsec: T9303: use ipsec-acceleration for VPP algo check
2026-09-26Merge pull request #5398 from ruben-herold/T9205-firewall-ruff-cleanupChristian Breunig
firewall: T9205: fix ruff findings in conf_mode/op_mode firewall.py
2026-09-26Merge pull request #5328 from BradKollmyer/T9077-literal-question-markChristian Breunig
cli: T9077: insert literal '?' inside quoted values instead of triggering help
2026-09-26configverify: T8859: remove dead code for verify_diffie_hellman_length()Christian Breunig
Commit a9e9c4acfa ("pki: openvpn: T3642: Migrate OpenVPN to PKI and refactor") was the last caller of verify_diffie_hellman_length() despite the build time testcases. Unused code is dead code, drop it.
2026-09-26python: T8859: fail loudly on an invalid Diffie-Hellman keysize argumentfix/T8859-dh-keysize-validationYuriy Andamasov
The Diffie-Hellman length check stringified the requested minimum keysize into a variable it never used, then converted the original argument again for the comparison. A non-numeric value therefore escaped as an uncaught ValueError from the comparison rather than being reported where it was passed in. The argument is now typed and validated up front: a non-integer raises TypeError, booleans included, and a non-positive integer raises ValueError. Both indicate a logic error in the calling script and should fail loudly instead of silently reporting an undersized key. The only callers today are the unit tests, so the contract is free to change. A file that exists but holds no readable parameters is user input rather than a logic error, and now fails the check instead of propagating the error from openssl. The bit-count pattern becomes a raw string, and the tests pass integer keysizes and cover the new paths.
2026-09-26vyos.utils: T8977: fix regressions in address and port validationChristian Breunig
Whether an interface belongs to a VRF was only established when a VRF was named explicitly. A lookup for the default VRF - what most callers ask for - thus reported an address living in an arbitrary VRF, or on a VRF device itself, as locally assigned, and accepted a configuration the daemon cannot bind later on. Naming the VRF device remains the way to ask for the addresses it carries. Probing the next address family after a failed bind was unreachable, as the argument is validated as a literal beforehand and then resolves to exactly one family. The early return is restored. An interface address carries host bits and must stay valid, but the range variants classify untrusted input handed over to nftables, which only accepts a prefix in canonical form. Those reject host bits again. All of it is covered by tests.
2026-09-26haproxy: T8977: allow a listen-address that is not assigned to an interfaceMichael Pardatscher
A listen-address had to be present on an interface at commit time, which refused a perfectly valid configuration: such an address is commonly supplied by a failover mechanism only after the commit, and the kernel permits binding it as soon as the non-local bind sysctl is set. That is accepted now. Co-authored-by: Christian Breunig <christian@breunig.cc>
2026-09-26vyos.utils: T8977: let a caller accept a non-local address as assignedMichael Pardatscher
Whether an address may be bound is not the same question as whether it is currently configured somewhere: the kernel permits binding a foreign address once the non-local bind sysctl is set, which is how a failover address is commonly handed over after the commit. Callers can now opt into that, the default is unchanged. A lookup no longer skips the VRF device itself, which carries the addresses of its own L3 domain, and an interface name can be retrieved for an address without the caller asking a yes/no question in the first place. Address and range validation is split into separate checks, so a caller no longer has to accept ranges where only an address is meaningful. The two duplicated version checks are dropped in favour of the existing ones. Co-authored-by: Christian Breunig <christian@breunig.cc>
2026-09-25op-mode: T9354: replace "reset connection" with "reconnect interface"Christian Breunig
"connect interface" and "disconnect interface" cannot be combined to restart a dialer interface when the CLI session runs over that very interface, yet the command which does cover it was filed under an unrelated top-level node and was hard to find. It is now "reconnect interface <ifname>", mirroring the existing connect and disconnect commands. "reset connection" is removed, no alias is kept. The removed command was reachable through the REST API as a "reset" path. A dedicated "/reconnect" endpoint takes its place, so the operation stays available to API consumers.
2026-09-25op-mode: T9354: run interface reconnect detached from calling sessionChristian Breunig
A reconnect is usually issued via the very interface being reconnected. Once the link drops, the calling session dies and the reconnect was killed by SIGHUP - or by SIGPIPE on the next write to the dead terminal - before the interface could be dialed again, leaving the system unreachable. The reconnect now runs in a transient systemd unit and survives the loss of the session. Progress is logged to the journal. PPPoE and SSTP restart the ppp service in a single operation instead of stopping and starting it, so there is no window in which an interrupted command leaves the link down. WWAN still disconnects the modem before dialing again.
2026-09-25firewall: T9205: keep 3 pre-existing over-length ConfigError lines untouchedRuben Herold
The f-string-without-placeholder cleanup on these 3 raise ConfigError() calls forced darker/black to wrap them onto 3 lines each, since the lines were already over ruff.toml's 88-char limit before this PR. Per review feedback, that reformatting adds more backport friction than it resolves, so leave these 3 pre-existing long lines exactly as they were (f-string prefix included). They're untouched, not part of this diff, so CI's diff-scoped ruff/darker checks don't flag them either.
2026-09-25firewall: T9205: also catch UnicodeDecodeError from cmdl() outputRuben Herold
cmdl() decodes subprocess output as utf-8 and can raise UnicodeDecodeError (not an OSError subclass) if that fails, in addition to OSError on command failure. Catch both, closing a gap left by the exact-exception narrowing in the previous commit.
2026-09-25firewall: T9205: narrow except Exception to expected error typesRuben Herold
Address copilot-pull-request-reviewer feedback on PR #5398: cmdl() only raises OSError and json.loads() only raises json.JSONDecodeError here, so catching bare Exception hid unrelated bugs. Narrowed all four call sites accordingly (three flagged, one identical pattern found by inspection).
2026-09-25firewall: T9205: fix ruff findings in conf_mode/op_mode firewall.pyRuben Herold
Bare except:, extraneous f-string prefixes on ConfigError()/text calls without placeholders, and 3 unused test locals in test_firewall.py. No behavior change. Split out of PR #5374 (T9160) at sever-sever's request: that PR bundled this cleanup with the apply-path feature because it happened to touch the same files, but it isn't related to apply-path itself.
2026-09-25Merge pull request #5376 from natali-rs1985/T9146Daniil Baturin
vpp: T9146: Enable DPDK no-multi-seg when a full frame fits the buffer
2026-09-25Merge pull request #5453 from m-songer/T9274-add-telegraf-configNataliia S.
T9274: Add more telegraf configuration
2026-09-24wwan: T9350: wait for the modem to become dialable, not merely listedChristian Breunig
A modem is on the bus while still probing, so a dial could start too early and leave the interface without a session until something re-dialled it.
2026-09-24Merge pull request #5494 from ↵Christian Breunig
t-shiro/fix/T9345-vrf-address-family-config-validation bgp: T9345: restore named-VRF AFI validation
2026-09-24Merge pull request #5484 from haakonnore/feat/T9319-vxlan-gbpChristian Breunig
vxlan: T9319: add VXLAN-GBP support
2026-09-24T9274: Add more telegraf configuration- #5453MichaelSonger
Added the ability to make several agent values configurable instead of hardcoded.
2026-09-24Merge pull request #5492 from c-po/devDaniil Baturin
frr: T9344: remove dead code path when vyos-configd is not running
2026-09-24Merge pull request #5485 from natali-rs1985/T9320Daniil Baturin
ipsec: T9320: Add deprecation warning for IKEv1 key-exchange
2026-09-24wwan: T9350: query ModemManager instead of the QMI control portChristian Breunig
show_wwan.py drove qmicli against /dev/cdc-wdmN, which assumes the modem exposes a QMI control port. An MBIM modem does not, so every subcommand of "show interfaces wwan wwanN" failed on one - after waiting out a five second transaction timeout, twice over for "signal": $ show interfaces wwan wwan0 signal Command not supported by Modem (10.6s) $ qmicli --device=/dev/cdc-wdm0 --device-open-proxy --nas-get-signal-info error: couldn't create client for the 'nas' service: CID allocation failed in the CTL client: Transaction timed out ports: cdc-wdm0 (mbim), ttyUSB0 (at), wwan0 (net) ModemManager has already probed the modem and speaks whichever protocol it exposes - QMI, MBIM or plain AT. It is a hard dependency of "interfaces wwan" anyway, as conf_mode cannot dial without it, and it answers from its own cache over D-Bus without touching the device: $ show interfaces wwan wwan0 signal Access technology: lte (0.2s) Signal quality: 58% Operator: Telekom.de Registration: home Packet service: attached State: connected
2026-09-24wwan: T9350: properly disconnect "disconnect interface wwanN"Christian Breunig
Two things kept an operator disconnect from taking effect. vyos-netlinkd re-dials every configured WWAN interface that has lost its session. It cannot tell a session lost to RF signal loss from one that was taken down on purpose, so the disconnect was undone on the next reconcile pass, at most 30 seconds later: $ disconnect interface wwan0 08:53:33 t+10s state=registered 08:53:43 t+20s state=registered 08:53:53 t+30s state=connected <- re-dialled 08:54:03 t+40s state=connected vyos-netlinkd: WWAN interface wwan0 is not connected, re-dialling... vyos-netlinkd: Re-dialled WWAN interface wwan0 Record the intent instead of inferring it from the session state. op-mode "disconnect" drops a marker in /run/vyos-wwan, which _reconcile_wwan() honours and "connect" removes again. conf_mode removes it too, so a commit keeps re-asserting the configured state - the marker only survives for as long as nobody says otherwise, and never across a reboot.
2026-09-24wwan: T9350: move session re-dial from cron into vyos-netlinkdChristian Breunig
/etc/cron.d/vyos-wwan re-ran the conf_mode script every 5 minutes via op-mode "connect interface wwanN" to re-establish a session lost to RF signal loss. Re-entering conf_mode from cron is unsafe: the cron job knows nothing about the boot commit or about a commit in flight, so when a tick lands before the running config is populated, get_config() returns nothing but {'ifname', 'deleted'} and apply() takes the teardown branch instead of dialling. It then stops the DHCP clients, stops ModemManager and unlinks its own cron file, leaving wwan0 down with no way to recover until the next commit: CRON[1869]: (root) CMD (/usr/libexec/vyos/vyos-check-wwan.py) systemd[1]: Stopping DHCP client on wwan0... systemd[1]: Stopping Modem Manager... This is timing dependent - it only bites when a */5 tick coincides with boot - which is why it presents as an intermittently dead WWAN interface. Move the re-dial into vyos-netlinkd, which already tracks these interfaces for DHCP and already gates all of its work behind boot_configuration_complete() and commit_in_progress2(). A re-dial can therefore no longer land on a half-applied configuration. It also dials ModemManager directly rather than re-entering conf_mode, so the teardown branch is no longer reachable from the recovery path at all.
2026-09-24cli: T9077: quote expansions and send DSR to /dev/ttyBrad Kollmyer
Harden the quote-aware '?' handler: quote readline buffer expansions and write the DSR query to /dev/tty so help still works when stdout is redirected.
2026-09-24cli: T9077: insert literal '?' inside quoted values instead of triggering helpBrad Kollmyer
The '?' key is a raw readline binding (possible-completions), so a literal question mark can never be typed into a value: readline intercepts the keystroke before bash parsing begins and quoting cannot protect it. Values like remote-group URLs with query strings get silently corrupted ('.../blacklist?key=x' is stored as '.../blacklistkey=x') with no error at any stage. Rebind '?' to a bind -x handler that scans the line left of the cursor for an open single/double quote or a pending backslash escape. Inside a quote or escape the key self-inserts; otherwise it triggers the standard help via a DSR round-trip (printf '\e[5n' with the terminal's reply ESC [ 0 n bound to possible-completions), keeping the help path and output identical to the previous behavior. 'set terminal key query-help enable' now restores the quote-aware handler instead of the raw binding; 'disable' keeps its existing self-insert override, which takes precedence at login as before. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-23ipsec: T9303: use ipsec-acceleration for VPP algo checkxTITUSMAXIMUSX
T8262 renamed "vpp settings ipsec" to "vpp settings ipsec-acceleration". get_config() still probed the old path, so vpp_ipsec_exists was always False and incompatible IKE/ESP algorithms were accepted. Check the current CLI node and add a smoketest that 3des (ESP) and serpent128 (IKE) fail commit when VPP IPsec acceleration is enabled.
2026-09-23bgp: T9345: restore named-VRF AFI validationTakayuki Shiroma
2026-09-22vxlan: T9319: add VXLAN-GBP supportHaakon Nore
Expose the Group Policy extension as a valueless gbp CLI node and pass it to iproute2 when creating VXLAN links. Recreate links when GBP changes and reject configurations combining GBP with GPE. Reject conflicting GBP settings on a shared UDP port, accounting for address families and underlay VRF socket bindings. Warn that external mode carries GBP in tunnel metadata instead of the packet mark. Add smoketest coverage for GBP creation, removal and re-enabling, retained interface settings, rejection without changing the running tunnel, shared ports, separate address families, and external mode.
2026-09-22frr: T9344: remove dead code path when vyos-configd is not runningChristian Breunig
vyos-configd used to be optional, so every FRR related conf_mode script carried a fallback that instantiated FRRender() and rendered/applied the configuration on its own whenever the service was not running. The service is now the only thing driving configuration mode, so that branch can never be taken. Drop the is_systemd_service_running('vyos-configd.service') fallbacks along with the now unused FRRender imports. For bonding and ethernet interfaces this also removes collecting the full frrender dict on an "evpn" node change, which only existed to feed that dead path.