From c172efb5300ef5aaf464bac1c046e2421a64cdd2 Mon Sep 17 00:00:00 2001 From: Joshua Gilman Date: Mon, 29 Dec 2025 16:45:53 -0800 Subject: [PATCH 1/4] fix(vyos): correct interface mapping for VP6630 hardware MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update VyOS configuration and tests to reflect actual VP6630 interface layout discovered during hardware setup: - eth0: Top SFP+ port (WAN β†’ CCR2004 DOWNLINK) - eth1: Bottom SFP+ port (Trunk β†’ CRS Switch) - eth2-eth5: 2.5GbE LAN ports Previously documented as eth4/eth5 which was incorrect. πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../09_design_decisions/003_vyos_gitops.md | 12 ++++++------ .../appendices/B_bootstrap_procedure.md | 2 +- .../network/vyos/configs/gateway.conf | 19 ++++++++++--------- infrastructure/network/vyos/tests/README.md | 4 ++-- infrastructure/network/vyos/tests/conftest.py | 4 ++-- .../network/vyos/tests/test_operational.py | 2 +- .../network/vyos/tests/topology.clab.yml | 18 +++++++++--------- 7 files changed, 31 insertions(+), 30 deletions(-) diff --git a/docs/architecture/09_design_decisions/003_vyos_gitops.md b/docs/architecture/09_design_decisions/003_vyos_gitops.md index f2d0da8..bec9b2d 100644 --- a/docs/architecture/09_design_decisions/003_vyos_gitops.md +++ b/docs/architecture/09_design_decisions/003_vyos_gitops.md @@ -209,13 +209,13 @@ infrastructure/network/vyos/ #### Interface Mapping -The test environment uses simplified interface mapping: +The test environment mirrors production interface mapping: -| Production | Test | Network | -|:-----------|:-----|:--------| -| eth4 | eth1 | WAN | -| eth5.10 | eth2 | MGMT (VLAN 10) | -| eth5.30 | eth3 | Platform (VLAN 30) | +| Interface | Network | +|:----------|:--------| +| eth0 | WAN (Transit to CCR2004) | +| eth1.10 | MGMT (VLAN 10) | +| eth1.30 | Platform (VLAN 30) | #### CI Integration diff --git a/docs/architecture/appendices/B_bootstrap_procedure.md b/docs/architecture/appendices/B_bootstrap_procedure.md index 13e09a5..a4f7ef3 100644 --- a/docs/architecture/appendices/B_bootstrap_procedure.md +++ b/docs/architecture/appendices/B_bootstrap_procedure.md @@ -202,7 +202,7 @@ VyOS provides the network connectivity (NAT, DHCP relay, inter-VLAN routing) req **Configuration Source:** The production VyOS configuration is maintained in Git at `infrastructure/network/vyos/configs/gateway.conf`. This file contains: -- Interface configuration (WAN on eth4, trunk on eth5 with all VLANs) +- Interface configuration (WAN on eth0, trunk on eth1 with all VLANs) - Firewall rules (WAN isolation, lab network policies) - NAT (masquerade for lab β†’ internet) - BGP configuration (for Cilium LoadBalancer VIPs) diff --git a/infrastructure/network/vyos/configs/gateway.conf b/infrastructure/network/vyos/configs/gateway.conf index 99fc901..ed24233 100644 --- a/infrastructure/network/vyos/configs/gateway.conf +++ b/infrastructure/network/vyos/configs/gateway.conf @@ -5,10 +5,11 @@ * Applied via Ansible on merge to main branch. * * Interface Mapping: - * WAN_IFACE = eth4 (Top SFP+ -> CCR2004 DOWNLINK) - * TRUNK_IFACE = eth5 (Bottom SFP+ -> CRS Switch) + * WAN_IFACE = eth0 (Top SFP+ -> CCR2004 DOWNLINK) + * TRUNK_IFACE = eth1 (Bottom SFP+ -> CRS Switch) + * LAN_IFACES = eth2-eth5 (2.5GbE LAN ports) * - * Transit Link (eth4 <-> CCR2004): + * Transit Link (eth0 <-> CCR2004): * 10.0.0.0/30 - Point-to-point between lab and home routers * VyOS: 10.0.0.2/30 * CCR2004: 10.0.0.1/30 @@ -41,7 +42,7 @@ firewall { network 192.168.0.0/16 } } - interface eth4 { + interface eth0 { in { name WAN_TO_LAB } @@ -179,11 +180,11 @@ firewall { } } interfaces { - ethernet eth4 { + ethernet eth0 { address 10.0.0.2/30 description "WAN - Transit to Home (CCR2004)" } - ethernet eth5 { + ethernet eth1 { description "TRUNK - Lab Switch (CRS)" vif 10 { address 10.10.10.1/24 @@ -215,7 +216,7 @@ nat { source { rule 100 { outbound-interface { - name eth4 + name eth0 } source { address 10.10.0.0/16 @@ -292,8 +293,8 @@ protocols { } service { dhcp-relay { - interface eth5.30 - interface eth5.40 + interface eth1.30 + interface eth1.40 relay-options { relay-agents-packets discard } diff --git a/infrastructure/network/vyos/tests/README.md b/infrastructure/network/vyos/tests/README.md index c957ed9..b661aca 100644 --- a/infrastructure/network/vyos/tests/README.md +++ b/infrastructure/network/vyos/tests/README.md @@ -1,8 +1,8 @@ # VyOS Containerlab Tests This suite validates the VyOS gateway configuration using a Containerlab -topology and pytest. The topology keeps the production interface layout -(`eth4` WAN, `eth5` trunk) to exercise the real configuration. +topology and pytest. The topology uses the production interface layout +(`eth0` WAN, `eth1` trunk) to exercise the real configuration. ## Prerequisites diff --git a/infrastructure/network/vyos/tests/conftest.py b/infrastructure/network/vyos/tests/conftest.py index 40213eb..2a34f45 100644 --- a/infrastructure/network/vyos/tests/conftest.py +++ b/infrastructure/network/vyos/tests/conftest.py @@ -50,7 +50,7 @@ class TestTopology: """Expected values for the Containerlab test topology.""" # WAN interface (transit link to CCR2004) - wan_iface: str = "eth4" + wan_iface: str = "eth0" wan_ip: str = "10.0.0.2" wan_cidr: str = "10.0.0.2/30" wan_gateway: str = "10.0.0.1" @@ -59,7 +59,7 @@ class TestTopology: wan_client_ip: str = "192.168.1.100" # Trunk interface - trunk_iface: str = "eth5" + trunk_iface: str = "eth1" # VLAN networks (gateway IPs) mgmt_vif: str = "10" diff --git a/infrastructure/network/vyos/tests/test_operational.py b/infrastructure/network/vyos/tests/test_operational.py index 01f7bc8..41ddaf6 100644 --- a/infrastructure/network/vyos/tests/test_operational.py +++ b/infrastructure/network/vyos/tests/test_operational.py @@ -52,7 +52,7 @@ class TestRoutingState: def test_wan_gateway_reachable(self, ping, test_topology): """WAN gateway (transit link peer) is reachable from VyOS. - This validates that the eth4 interface is correctly configured + This validates that the eth0 interface is correctly configured and can reach the transit link peer (10.0.0.1). """ # VyOS can reach the WAN gateway - verified through lab client connectivity diff --git a/infrastructure/network/vyos/tests/topology.clab.yml b/infrastructure/network/vyos/tests/topology.clab.yml index 322a560..fc87f0d 100644 --- a/infrastructure/network/vyos/tests/topology.clab.yml +++ b/infrastructure/network/vyos/tests/topology.clab.yml @@ -3,12 +3,12 @@ # This topology creates a minimal lab environment to test the VyOS gateway # configuration. It simulates key network segments with Linux clients. # -# Interface Mapping: -# eth0 - Containerlab management (reserved) -# eth4 - WAN interface (production mapping) -# eth5 - Trunk interface (production mapping) +# Interface Mapping (production VP6630): +# eth0 - WAN interface (Top SFP+ -> CCR2004 DOWNLINK) +# eth1 - Trunk interface (Bottom SFP+ -> CRS Switch) +# eth2-eth5 - LAN interfaces (2.5GbE ports) # -# This topology keeps the production interface layout and uses a VLAN-aware +# This topology uses the production interface layout and uses a VLAN-aware # trunk so tests exercise the real gateway configuration. name: vyos-gateway-test @@ -100,11 +100,11 @@ topology: - ip route replace default via 10.10.60.1 links: - # WAN connection (gateway eth4 <-> wan-client eth1) - - endpoints: ["gateway:eth4", "wan-client:eth1"] + # WAN connection (gateway eth0 <-> wan-client eth1) + - endpoints: ["gateway:eth0", "wan-client:eth1"] - # Trunk connection (gateway eth5 <-> trunk-switch eth1) - - endpoints: ["gateway:eth5", "trunk-switch:eth1"] + # Trunk connection (gateway eth1 <-> trunk-switch eth1) + - endpoints: ["gateway:eth1", "trunk-switch:eth1"] # VLAN clients connected to trunk-switch - endpoints: ["trunk-switch:eth2", "mgmt-client:eth1"] From a2852f28a2595b604c65d0f650cfbff9d4862111 Mon Sep 17 00:00:00 2001 From: Joshua Gilman Date: Mon, 29 Dec 2025 16:51:44 -0800 Subject: [PATCH 2/4] fix(vyos): remap interfaces for Containerlab tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Containerlab reserves eth0 for management, so tests cannot use production interface names directly. This updates the test infrastructure to: - Add interface remapping in render-config-boot.sh (eth0β†’eth2, eth1β†’eth3) - Update topology.clab.yml with remapped interfaces - Update conftest.py with test-specific values - Update documentation to explain the mapping Production config (gateway.conf) remains unchanged with eth0/eth1. πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../09_design_decisions/003_vyos_gitops.md | 14 +++++----- infrastructure/network/vyos/tests/README.md | 5 ++-- infrastructure/network/vyos/tests/conftest.py | 27 ++++++++++--------- .../network/vyos/tests/render-config-boot.sh | 23 ++++++++++++++-- .../network/vyos/tests/test_operational.py | 4 +-- .../network/vyos/tests/topology.clab.yml | 27 ++++++++++--------- 6 files changed, 63 insertions(+), 37 deletions(-) diff --git a/docs/architecture/09_design_decisions/003_vyos_gitops.md b/docs/architecture/09_design_decisions/003_vyos_gitops.md index bec9b2d..f9c9379 100644 --- a/docs/architecture/09_design_decisions/003_vyos_gitops.md +++ b/docs/architecture/09_design_decisions/003_vyos_gitops.md @@ -209,13 +209,15 @@ infrastructure/network/vyos/ #### Interface Mapping -The test environment mirrors production interface mapping: +The test environment remaps interfaces because Containerlab reserves eth0: -| Interface | Network | -|:----------|:--------| -| eth0 | WAN (Transit to CCR2004) | -| eth1.10 | MGMT (VLAN 10) | -| eth1.30 | Platform (VLAN 30) | +| Production | Test | Network | +|:-----------|:-----|:--------| +| eth0 | eth2 | WAN (Transit to CCR2004) | +| eth1.10 | eth3.10 | MGMT (VLAN 10) | +| eth1.30 | eth3.30 | Platform (VLAN 30) | + +The `render-config-boot.sh` script automatically performs this remapping. #### CI Integration diff --git a/infrastructure/network/vyos/tests/README.md b/infrastructure/network/vyos/tests/README.md index b661aca..8cc1c04 100644 --- a/infrastructure/network/vyos/tests/README.md +++ b/infrastructure/network/vyos/tests/README.md @@ -1,8 +1,9 @@ # VyOS Containerlab Tests This suite validates the VyOS gateway configuration using a Containerlab -topology and pytest. The topology uses the production interface layout -(`eth0` WAN, `eth1` trunk) to exercise the real configuration. +topology and pytest. The test environment remaps production interfaces +(eth0 WAN, eth1 trunk) to test interfaces (eth2 WAN, eth3 trunk) because +Containerlab reserves eth0 for management. ## Prerequisites diff --git a/infrastructure/network/vyos/tests/conftest.py b/infrastructure/network/vyos/tests/conftest.py index 2a34f45..a2b89df 100644 --- a/infrastructure/network/vyos/tests/conftest.py +++ b/infrastructure/network/vyos/tests/conftest.py @@ -50,16 +50,17 @@ class TestTopology: """Expected values for the Containerlab test topology.""" # WAN interface (transit link to CCR2004) - wan_iface: str = "eth0" - wan_ip: str = "10.0.0.2" - wan_cidr: str = "10.0.0.2/30" - wan_gateway: str = "10.0.0.1" - # wan-client simulates both CCR2004 (10.0.0.1) and home network (192.168.1.100) - wan_client_transit_ip: str = "10.0.0.1" - wan_client_ip: str = "192.168.1.100" - - # Trunk interface - trunk_iface: str = "eth1" + # Note: Test uses eth2 (remapped from production eth0 - Containerlab reserves eth0) + wan_iface: str = "eth2" + wan_ip: str = "192.168.0.2" + wan_cidr: str = "192.168.0.2/24" + wan_gateway: str = "192.168.0.1" + # wan-client simulates both CCR2004 and home network traffic + wan_client_transit_ip: str = "192.168.0.1" + wan_client_ip: str = "192.168.0.100" + + # Trunk interface (remapped from production eth1) + trunk_iface: str = "eth3" # VLAN networks (gateway IPs) mgmt_vif: str = "10" @@ -86,9 +87,9 @@ class TestTopology: storage_gateway: str = "10.10.60.1" storage_client_ip: str = "10.10.60.100" - # Network ranges - transit_cidr: str = "10.0.0.0/30" - home_cidr: str = "192.168.1.0/24" + # Network ranges (test environment uses 192.168.0.0/24 for WAN simulation) + transit_cidr: str = "192.168.0.0/24" + home_cidr: str = "192.168.0.0/24" lab_cidr: str = "10.10.0.0/16" # DHCP configuration diff --git a/infrastructure/network/vyos/tests/render-config-boot.sh b/infrastructure/network/vyos/tests/render-config-boot.sh index 6c05837..7fd6419 100755 --- a/infrastructure/network/vyos/tests/render-config-boot.sh +++ b/infrastructure/network/vyos/tests/render-config-boot.sh @@ -1,8 +1,14 @@ #!/bin/bash # Render config.boot for containerlab testing # -# Takes gateway.conf as the base configuration and injects an SSH public key -# for test authentication. +# Takes gateway.conf as the base configuration and: +# 1. Remaps production interfaces to test interfaces (Containerlab reserves eth0) +# 2. Injects an SSH public key for test authentication +# 3. Adjusts network addresses for the isolated test environment +# +# Interface Mapping (production -> test): +# eth0 -> eth2 (WAN) +# eth1 -> eth3 (Trunk) # # Usage: render-config-boot.sh @@ -43,6 +49,19 @@ fi # Start with the base gateway.conf cp "${CONFIG_FILE}" "${OUTPUT_FILE}" +# Remap interfaces for test environment (Containerlab reserves eth0 for management) +# Production: eth0 (WAN), eth1 (Trunk) +# Test: eth2 (WAN), eth3 (Trunk) +sed -i.bak -e 's/eth0/eth2/g' -e 's/eth1/eth3/g' "${OUTPUT_FILE}" +rm -f "${OUTPUT_FILE}.bak" + +# Adjust WAN IP for test environment (192.168.0.0/24 instead of 10.0.0.0/30) +# This allows the test topology to use a simpler addressing scheme +sed -i.bak -e 's|10\.0\.0\.2/30|192.168.0.2/24|g' \ + -e 's|next-hop 10\.0\.0\.1|next-hop 192.168.0.1|g' \ + -e 's|192\.168\.1\.0/24|192.168.0.0/24|g' "${OUTPUT_FILE}" +rm -f "${OUTPUT_FILE}.bak" + # Inject SSH key into the system login section # Find the closing brace of the system block and insert login config before it # Use temp file approach for portability (macOS vs GNU sed) diff --git a/infrastructure/network/vyos/tests/test_operational.py b/infrastructure/network/vyos/tests/test_operational.py index 41ddaf6..25b8d5f 100644 --- a/infrastructure/network/vyos/tests/test_operational.py +++ b/infrastructure/network/vyos/tests/test_operational.py @@ -52,8 +52,8 @@ class TestRoutingState: def test_wan_gateway_reachable(self, ping, test_topology): """WAN gateway (transit link peer) is reachable from VyOS. - This validates that the eth0 interface is correctly configured - and can reach the transit link peer (10.0.0.1). + This validates that the WAN interface is correctly configured + and can reach the transit link peer. """ # VyOS can reach the WAN gateway - verified through lab client connectivity # If lab clients can reach WAN via NAT, the routing is working diff --git a/infrastructure/network/vyos/tests/topology.clab.yml b/infrastructure/network/vyos/tests/topology.clab.yml index fc87f0d..786c011 100644 --- a/infrastructure/network/vyos/tests/topology.clab.yml +++ b/infrastructure/network/vyos/tests/topology.clab.yml @@ -3,13 +3,16 @@ # This topology creates a minimal lab environment to test the VyOS gateway # configuration. It simulates key network segments with Linux clients. # -# Interface Mapping (production VP6630): +# Production Interface Mapping (VP6630): # eth0 - WAN interface (Top SFP+ -> CCR2004 DOWNLINK) # eth1 - Trunk interface (Bottom SFP+ -> CRS Switch) # eth2-eth5 - LAN interfaces (2.5GbE ports) # -# This topology uses the production interface layout and uses a VLAN-aware -# trunk so tests exercise the real gateway configuration. +# Test Interface Mapping (Containerlab reserves eth0 for management): +# eth2 - WAN interface (remapped from eth0) +# eth3 - Trunk interface (remapped from eth1) +# +# The render-config-boot.sh script remaps interfaces from production to test. name: vyos-gateway-test @@ -38,16 +41,16 @@ topology: - sh -c "for iface in eth1 eth2 eth3 eth4 eth5 eth6 eth7; do ip link set $iface up && ip link set $iface master br0; done" # WAN-side client (simulates CCR2004 on transit link + home network client) - # Primary: 10.0.0.1/30 (transit link - acts as CCR2004) - # Secondary: 192.168.1.100/24 (home network simulation for firewall tests) + # Primary: 192.168.0.1/24 (acts as gateway/CCR2004 in test environment) + # Secondary: 192.168.0.100/24 (home network simulation for firewall tests) wan-client: kind: linux image: alpine:latest exec: - apk add --no-cache tcpdump netcat-openbsd - - sh -c "ip addr add 10.0.0.1/30 dev eth1 && ip link set eth1 up" - - sh -c "ip addr add 192.168.1.100/24 dev eth1" - - ip route replace default via 10.0.0.2 + - sh -c "ip addr add 192.168.0.1/24 dev eth1 && ip link set eth1 up" + - sh -c "ip addr add 192.168.0.100/24 dev eth1" + - ip route replace default via 192.168.0.2 # Management network client (VLAN 10 simulation) mgmt-client: @@ -100,11 +103,11 @@ topology: - ip route replace default via 10.10.60.1 links: - # WAN connection (gateway eth0 <-> wan-client eth1) - - endpoints: ["gateway:eth0", "wan-client:eth1"] + # WAN connection (gateway eth2 <-> wan-client eth1) + - endpoints: ["gateway:eth2", "wan-client:eth1"] - # Trunk connection (gateway eth1 <-> trunk-switch eth1) - - endpoints: ["gateway:eth1", "trunk-switch:eth1"] + # Trunk connection (gateway eth3 <-> trunk-switch eth1) + - endpoints: ["gateway:eth3", "trunk-switch:eth1"] # VLAN clients connected to trunk-switch - endpoints: ["trunk-switch:eth2", "mgmt-client:eth1"] From 27e5244ccad2afee8e9e8243077258c2b1797663 Mon Sep 17 00:00:00 2001 From: Joshua Gilman Date: Mon, 29 Dec 2025 17:02:42 -0800 Subject: [PATCH 3/4] fix(vyos): address config warnings and add user login block MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Update DHCP relay to use new syntax (listen-interface/upstream-interface) to fix deprecation warning - Add system login block with vyos user to prevent "delete current user" error when applying config - User authentication (SSH keys, password) managed separately via Ansible The flow control warnings on SFP+ ports are hardware-related and benign. πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../network/vyos/configs/gateway.conf | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/infrastructure/network/vyos/configs/gateway.conf b/infrastructure/network/vyos/configs/gateway.conf index ed24233..f2c1dce 100644 --- a/infrastructure/network/vyos/configs/gateway.conf +++ b/infrastructure/network/vyos/configs/gateway.conf @@ -293,8 +293,9 @@ protocols { } service { dhcp-relay { - interface eth1.30 - interface eth1.40 + listen-interface eth1.30 + listen-interface eth1.40 + upstream-interface eth0 relay-options { relay-agents-packets discard } @@ -335,10 +336,20 @@ service { system { domain-name lab.gilman.io host-name gateway - /* SSH keys managed separately via Ansible - * Do not commit real keys to this file - * Ansible: deploy.yml -e ssh_public_key_file=~/.ssh/id_rsa.pub - */ + login { + /* User authentication managed separately via Ansible + * Do not commit passwords or keys to this file + * Ansible adds SSH keys and optionally sets password + * Console access requires password set via: + * set system login user vyos authentication plaintext-password + */ + user vyos { + authentication { + /* SSH public keys added by Ansible deploy.yml */ + /* Password set manually for console access */ + } + } + } name-server 1.1.1.1 name-server 8.8.8.8 ntp { From d2c50c776b659f1dc3c396fb26279d576290db11 Mon Sep 17 00:00:00 2001 From: Joshua Gilman Date: Mon, 29 Dec 2025 17:14:37 -0800 Subject: [PATCH 4/4] fix(vyos): inject SSH key into existing authentication block MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous approach added a new login block, but gateway.conf now includes a user login block to prevent the "delete current user" error. Updated render-config-boot.sh to inject the SSH public key into the existing authentication block using awk instead of sed. Also update ansible inventory to use transit link IP by default. πŸ€– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../network/vyos/ansible/inventory/hosts.yml | 2 +- .../network/vyos/tests/render-config-boot.sh | 33 ++++++++++--------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/infrastructure/network/vyos/ansible/inventory/hosts.yml b/infrastructure/network/vyos/ansible/inventory/hosts.yml index de73f63..12f8b76 100644 --- a/infrastructure/network/vyos/ansible/inventory/hosts.yml +++ b/infrastructure/network/vyos/ansible/inventory/hosts.yml @@ -8,7 +8,7 @@ all: gateway: # Connect via Tailscale in CI/CD # Or direct IP for local execution - ansible_host: "{{ lookup('env', 'VYOS_HOST') | default('gateway.lab.gilman.io', true) }}" + ansible_host: "{{ lookup('env', 'VYOS_HOST') | default('10.0.0.2', true) }}" ansible_user: vyos ansible_network_os: vyos.vyos.vyos ansible_connection: ansible.netcommon.network_cli diff --git a/infrastructure/network/vyos/tests/render-config-boot.sh b/infrastructure/network/vyos/tests/render-config-boot.sh index 7fd6419..8291131 100755 --- a/infrastructure/network/vyos/tests/render-config-boot.sh +++ b/infrastructure/network/vyos/tests/render-config-boot.sh @@ -62,23 +62,26 @@ sed -i.bak -e 's|10\.0\.0\.2/30|192.168.0.2/24|g' \ -e 's|192\.168\.1\.0/24|192.168.0.0/24|g' "${OUTPUT_FILE}" rm -f "${OUTPUT_FILE}.bak" -# Inject SSH key into the system login section -# Find the closing brace of the system block and insert login config before it -# Use temp file approach for portability (macOS vs GNU sed) +# Inject SSH key into the existing vyos user authentication block +# The gateway.conf already has the user vyos { authentication { ... }} structure +# We just need to add the public-keys section inside it TEMP_FILE=$(mktemp) -sed '/^system {$/,/^}$/{ - /^}$/i\ - login {\ - user vyos {\ - authentication {\ - public-keys test {\ - key "'"${SSH_KEY_BODY}"'"\ - type '"${SSH_KEY_TYPE}"'\ - }\ - }\ - }\ +awk ' + /user vyos \{/ { in_user = 1 } + in_user && /authentication \{/ { + in_auth = 1 + print + # Insert the public key right after the authentication { line + print " public-keys test {" + print " key \"'"${SSH_KEY_BODY}"'\"" + print " type '"${SSH_KEY_TYPE}"'" + print " }" + next } -}' "${OUTPUT_FILE}" > "${TEMP_FILE}" + in_auth && /\}/ { in_auth = 0 } + in_user && /^\s*\}\s*$/ && !in_auth { in_user = 0 } + { print } +' "${OUTPUT_FILE}" > "${TEMP_FILE}" mv "${TEMP_FILE}" "${OUTPUT_FILE}" # Fix SELinux context if applicable (for container environments)