feat: read the virtual IPs vip-manager and keepalived declare on a host #24

Merged
christianmanivong merged 1 commits from feature/virtual-ips into main 2026-10-08 10:41:02 +00:00
Owner

Adds VirtualIpsMixin.get_virtual_ips(): the addresses a host's vip-manager and keepalived configuration lets float onto it — declared, whether or not the host holds them right now. For NetOrk/netork#829 (db-01/db-02 share 10.7.224.10 through vip-manager).

What is read

  • vip-manager: every vip-manager.service / vip-manager@*.service unit. Address, mask, interface and trigger key from a flag (1.x's -ip=${VIP_IP} resolved through the unit's environment), the environment (EnvironmentFile over Environment), or the --config YAML (5.x).
  • keepalived: virtual_ipaddress and virtual_ipaddress_excluded of every vrrp_instance, with its interface and virtual_router_id (vrid:<n>). include is followed four levels deep, relative to the including file; a cycle is cut.

Secrets stay on the host. The configuration also holds the etcd password and auth_pass, so an awk program filters on the host and prints allowlisted fields only. The tests run the command for real against a stub systemctl and real files, under mawk and busybox awk, and assert that no secret token appears. An include pattern that is not a plain path glob is never handed to the (root) shell.

Semantics: per mechanism a list ([] = none there) or None (could not read: unreadable file, include not followed, no systemd). Root first via the driver's hook, then unprivileged. The command is ~4 kB, so a driver sends it on an exec channel.

Checked against the live hosts (read-only): db-01 and db-02 both report 10.7.224.10/24 on ens7, trigger key /service/netork-db/leader, 215 bytes of output, no password or etcd endpoint in it.

Version 4.2.0 (4.1.0 is the FreeBSD host status, #23).

Adds `VirtualIpsMixin.get_virtual_ips()`: the addresses a host's vip-manager and keepalived configuration lets float onto it — declared, whether or not the host holds them right now. For NetOrk/netork#829 (db-01/db-02 share 10.7.224.10 through vip-manager). **What is read** - vip-manager: every `vip-manager.service` / `vip-manager@*.service` unit. Address, mask, interface and trigger key from a flag (1.x's `-ip=${VIP_IP}` resolved through the unit's environment), the environment (`EnvironmentFile` over `Environment`), or the `--config` YAML (5.x). - keepalived: `virtual_ipaddress` and `virtual_ipaddress_excluded` of every `vrrp_instance`, with its `interface` and `virtual_router_id` (`vrid:<n>`). `include` is followed four levels deep, relative to the including file; a cycle is cut. **Secrets stay on the host.** The configuration also holds the etcd password and `auth_pass`, so an awk program filters on the host and prints allowlisted fields only. The tests run the command for real against a stub `systemctl` and real files, under mawk and busybox awk, and assert that no secret token appears. An include pattern that is not a plain path glob is never handed to the (root) shell. **Semantics**: per mechanism a list (`[]` = none there) or `None` (could not read: unreadable file, include not followed, no systemd). Root first via the driver's hook, then unprivileged. The command is ~4 kB, so a driver sends it on an exec channel. Checked against the live hosts (read-only): db-01 and db-02 both report `10.7.224.10/24 on ens7, trigger key /service/netork-db/leader`, 215 bytes of output, no password or etcd endpoint in it. Version 4.2.0 (4.1.0 is the FreeBSD host status, #23).
christianmanivong added 1 commit 2026-10-08 10:37:40 +00:00
feat: read the virtual IPs vip-manager and keepalived declare on a host
CI / test (3.10) (push) Successful in 26s
CI / test (3.11) (push) Successful in 24s
CI / test (3.12) (push) Successful in 26s
CI / test (3.10) (pull_request) Successful in 35s
CI / test (3.11) (pull_request) Successful in 36s
CI / test (3.12) (pull_request) Successful in 39s
37c09d0fa0
A virtual IP sits on whichever member holds it right now; a standby's
address list shows no trace of it. What every member has is the
configuration that declares it, and reading that is the same on every
Linux host -- so VirtualIpsMixin.get_virtual_ips() lives here and a driver
only carries the command across (NetOrk/netork#829).

- vip-manager: every vip-manager.service / vip-manager@*.service unit; the
  address from a flag (1.x's -ip=${VIP_IP} resolved through the unit's
  environment), the environment, or the --config YAML (5.x).
- keepalived: the virtual_ipaddress(_excluded) entries of every
  vrrp_instance, with its interface and virtual_router_id; include is
  followed four levels deep, and a pattern that is no plain path glob is
  never handed to the root shell.

The same files hold the etcd password and auth_pass, so an awk program
filters on the host and prints allowlisted fields only. None per
mechanism is "did not look", [] a host without it. The command is about
4 kB and goes on an exec channel.

Version 4.2.0.
christianmanivong merged commit ba2f18ea7d into main 2026-10-08 10:41:02 +00:00
christianmanivong deleted branch feature/virtual-ips 2026-10-08 10:41:02 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: NAPALM/napalm-device-types#24