diff options
| author | omnom62 <omnom62@outlook.com> | 2026-10-05 20:56:05 +1000 |
|---|---|---|
| committer | omnom62 <omnom62@outlook.com> | 2026-10-05 20:56:05 +1000 |
| commit | 8ee802e41374942965b6b93cfb4534725ef45145 (patch) | |
| tree | ef3e5579bd767422caa6fe77cea6a7b5d2d8562c /extensions | |
| parent | 748df2bc1d35fa285dd3fe46916e1230408778c7 (diff) | |
| download | vyos.blueprints-main.tar.gz vyos.blueprints-main.zip | |
T9393: new rolesmain
Diffstat (limited to 'extensions')
50 files changed, 1636 insertions, 0 deletions
diff --git a/extensions/molecule/bgp_unnumbered/converge.yml b/extensions/molecule/bgp_unnumbered/converge.yml new file mode 100644 index 0000000..3b3260a --- /dev/null +++ b/extensions/molecule/bgp_unnumbered/converge.yml @@ -0,0 +1,6 @@ +--- +- name: Converge + hosts: fabric + gather_facts: false + roles: + - vyos.blueprints.bgp_unnumbered diff --git a/extensions/molecule/bgp_unnumbered/inventory.yml b/extensions/molecule/bgp_unnumbered/inventory.yml new file mode 100644 index 0000000..1785087 --- /dev/null +++ b/extensions/molecule/bgp_unnumbered/inventory.yml @@ -0,0 +1,23 @@ +--- +all: + children: + vyos: + children: + fabric: + hosts: + r1: + ansible_host: clab-bp-bgp-r1 + bgp_unnumbered_asn: 64496 + bgp_unnumbered_router_id: 192.168.0.1 + r2: + ansible_host: clab-bp-bgp-r2 + bgp_unnumbered_asn: 64499 + bgp_unnumbered_router_id: 192.168.0.2 + vars: + bgp_unnumbered_interfaces: [eth1, eth2] + bgp_unnumbered_group: fabric + vars: + ansible_network_os: vyos.vyos.vyos + ansible_connection: ansible.netcommon.network_cli + ansible_user: admin + ansible_password: admin diff --git a/extensions/molecule/bgp_unnumbered/molecule.yml b/extensions/molecule/bgp_unnumbered/molecule.yml new file mode 100644 index 0000000..9fa905c --- /dev/null +++ b/extensions/molecule/bgp_unnumbered/molecule.yml @@ -0,0 +1,28 @@ +--- +# VyOS runs as a container (containerlab kind vyosnetworks_vyos); +# the lab is deployed in prepare and destroyed in cleanup. +dependency: + name: galaxy + enabled: false +driver: + name: default + options: + managed: false +platforms: + - name: r1 + - name: r2 +provisioner: + name: ansible + config_options: + defaults: + host_key_checking: false + persistent_connection: + command_timeout: 60 + inventory: + links: + hosts: inventory.yml + playbooks: + prepare: ../_shared/lab_up.yml + cleanup: ../_shared/lab_down.yml +verifier: + name: ansible diff --git a/extensions/molecule/bgp_unnumbered/topology.clab.yml b/extensions/molecule/bgp_unnumbered/topology.clab.yml new file mode 100644 index 0000000..a370c2f --- /dev/null +++ b/extensions/molecule/bgp_unnumbered/topology.clab.yml @@ -0,0 +1,14 @@ +name: bp-bgp +topology: + kinds: + vyosnetworks_vyos: + image: ${VYOS_IMAGE:=vyos:blueprints-ci} + nodes: + r1: + kind: vyosnetworks_vyos + r2: + kind: vyosnetworks_vyos + links: + # two parallel links without IP addresses; BGP peers over IPv6 link-local + - endpoints: ["r1:eth1", "r2:eth1"] + - endpoints: ["r1:eth2", "r2:eth2"] diff --git a/extensions/molecule/bgp_unnumbered/verify.yml b/extensions/molecule/bgp_unnumbered/verify.yml new file mode 100644 index 0000000..3f251af --- /dev/null +++ b/extensions/molecule/bgp_unnumbered/verify.yml @@ -0,0 +1,20 @@ +--- +- name: Verify + hosts: fabric + gather_facts: false + tasks: + - name: Wait for BGP sessions and routes + ansible.builtin.pause: + seconds: 45 + run_once: true + + - name: Run role checks + ansible.builtin.include_role: + name: vyos.blueprints.bgp_unnumbered + tasks_from: verify + + - name: Ping the other router's loopback from this loopback, as on the docs page + vyos.vyos.vyos_ping: + dest: "{{ '192.168.0.2' if inventory_hostname == 'r1' else '192.168.0.1' }}" + source: "{{ bgp_unnumbered_router_id }}" + count: 3 diff --git a/extensions/molecule/bridge_firewall/converge.yml b/extensions/molecule/bridge_firewall/converge.yml new file mode 100644 index 0000000..89558a3 --- /dev/null +++ b/extensions/molecule/bridge_firewall/converge.yml @@ -0,0 +1,7 @@ +--- +- name: Converge + hosts: vyos + gather_facts: false + roles: + - vyos.blueprints.base + - vyos.blueprints.bridge_firewall diff --git a/extensions/molecule/bridge_firewall/inventory.yml b/extensions/molecule/bridge_firewall/inventory.yml new file mode 100644 index 0000000..dface0d --- /dev/null +++ b/extensions/molecule/bridge_firewall/inventory.yml @@ -0,0 +1,94 @@ +--- +all: + children: + vyos: + hosts: + r1: + ansible_host: clab-bp-bridge-r1 + vars: + ansible_network_os: vyos.vyos.vyos + ansible_connection: ansible.netcommon.network_cli + ansible_user: admin + ansible_password: admin + # internet uplink: eth8 here, eth0 on the docs page (management in containerlab) + base_interfaces: + - {name: eth8, addresses: [203.0.113.1/24]} + bridge_firewall_bridges: + - name: br0 + description: Isolated L2 bridge + members: + - {interface: eth1, description: br0} + - {interface: eth2, description: br0} + prerouting: + default_action: drop + rules: + - {number: 10, description: Accept IPv6 traffic, ethernet_type: ipv6} + forward: + default_action: accept + + - name: br1 + description: L3 bridge br1 + addresses: [10.1.1.1/24] + members: + - {interface: eth3, description: br1} + - {interface: eth4, description: br1} + prerouting: + default_action: accept + rules: + - number: 10 + description: Drop DHCP discover + action: drop + protocol: udp + source: {port: "68"} + destination: {port: "67", mac_address: "ff:ff:ff:ff:ff:ff"} + log: true + - {number: 20, description: Drop IPv6 traffic, action: drop, ethernet_type: ipv6} + forward: + default_action: drop + rules: + - {number: 10, description: Accept ARP, ethernet_type: arp} + - {number: 20, description: Accept ipv4 from host, source: {address: 10.1.1.102}, state: [new]} + ip_forward: + rules: + - {number: 10, description: br1 - allow internet access, outbound_interface: eth8} + router_access: accept + + - name: br2 + description: L3 bridge br2 + addresses: [10.2.2.1/24] + members: + - {interface: eth5, description: br2 - Host} + - {interface: eth6, description: br2 - Trusted DHCP Server} + - {interface: eth7, description: br2} + prerouting: + default_action: accept + rules: + - {number: 10, description: Drop IPv6 traffic, action: drop, ethernet_type: ipv6} + forward: + default_action: drop + rules: + - number: 10 + description: Accept DHCP discover + protocol: udp + source: {port: "68"} + destination: {port: "67", mac_address: "ff:ff:ff:ff:ff:ff"} + - number: 20 + description: Accept DHCP offers from trusted interface + protocol: udp + source: {port: "67"} + destination: {port: "68"} + inbound_interface: eth6 + - number: 22 + description: Drop all other DHCP offers + action: drop + protocol: udp + source: {port: "67"} + destination: {port: "68"} + log: true + - {number: 30, description: Accept ARP, ethernet_type: arp} + - {number: 40, description: Accept ipv4, ethernet_type: ipv4} + ip_forward: + rules: + - {number: 10, description: br2 - allow internet access, outbound_interface: eth8} + - {number: 20, description: br2 - allow access to br1, outbound_bridge: br1} + router_access: drop diff --git a/extensions/molecule/bridge_firewall/molecule.yml b/extensions/molecule/bridge_firewall/molecule.yml new file mode 100644 index 0000000..612af0a --- /dev/null +++ b/extensions/molecule/bridge_firewall/molecule.yml @@ -0,0 +1,27 @@ +--- +# VyOS runs as a container (containerlab kind vyosnetworks_vyos); +# the lab is deployed in prepare and destroyed in cleanup. +dependency: + name: galaxy + enabled: false +driver: + name: default + options: + managed: false +platforms: + - name: r1 +provisioner: + name: ansible + config_options: + defaults: + host_key_checking: false + persistent_connection: + command_timeout: 60 + inventory: + links: + hosts: inventory.yml + playbooks: + prepare: ../_shared/lab_up.yml + cleanup: ../_shared/lab_down.yml +verifier: + name: ansible diff --git a/extensions/molecule/bridge_firewall/topology.clab.yml b/extensions/molecule/bridge_firewall/topology.clab.yml new file mode 100644 index 0000000..1b70e89 --- /dev/null +++ b/extensions/molecule/bridge_firewall/topology.clab.yml @@ -0,0 +1,63 @@ +name: bp-bridge +topology: + nodes: + r1: + kind: vyosnetworks_vyos + image: ${VYOS_IMAGE:=vyos:blueprints-ci} + h1: + kind: linux + image: alpine:3 + exec: + - ip addr add 192.168.0.1/24 dev eth1 + - ip -6 addr add fd00:b0::1/64 dev eth1 + h2: + kind: linux + image: alpine:3 + exec: + - ip addr add 192.168.0.2/24 dev eth1 + - ip -6 addr add fd00:b0::2/64 dev eth1 + h3: + kind: linux + image: alpine:3 + exec: + - ip addr add 10.1.1.102/24 dev eth1 + - ip route replace default via 10.1.1.1 + h4: + kind: linux + image: alpine:3 + exec: + - ip addr add 10.1.1.103/24 dev eth1 + - ip route replace default via 10.1.1.1 + h5: + kind: linux + image: alpine:3 + exec: + - ip addr add 10.2.2.5/24 dev eth1 + - ip route replace default via 10.2.2.1 + h6: + kind: linux + image: alpine:3 + exec: + - ip addr add 10.2.2.6/24 dev eth1 + - ip route replace default via 10.2.2.1 + h7: + kind: linux + image: alpine:3 + exec: + - ip addr add 10.2.2.7/24 dev eth1 + - ip route replace default via 10.2.2.1 + wan: + kind: linux + image: alpine:3 + exec: + - ip addr add 203.0.113.100/24 dev eth1 + - ip route replace default via 203.0.113.1 + links: + - endpoints: ["r1:eth1", "h1:eth1"] + - endpoints: ["r1:eth2", "h2:eth1"] + - endpoints: ["r1:eth3", "h3:eth1"] + - endpoints: ["r1:eth4", "h4:eth1"] + - endpoints: ["r1:eth5", "h5:eth1"] + - endpoints: ["r1:eth6", "h6:eth1"] + - endpoints: ["r1:eth7", "h7:eth1"] + - endpoints: ["r1:eth8", "wan:eth1"] diff --git a/extensions/molecule/bridge_firewall/verify.yml b/extensions/molecule/bridge_firewall/verify.yml new file mode 100644 index 0000000..dd2f042 --- /dev/null +++ b/extensions/molecule/bridge_firewall/verify.yml @@ -0,0 +1,37 @@ +--- +- name: Verify role state + hosts: vyos + gather_facts: false + tasks: + - name: Run role checks + ansible.builtin.include_role: + name: vyos.blueprints.bridge_firewall + tasks_from: verify + +- name: Verify the page's requirements with traffic + hosts: localhost + gather_facts: false + vars: + _flows: + - {from: h1, ping: "-6 fd00:b0::2", allowed: true, why: "br0 accepts IPv6 within the bridge"} + - {from: h1, ping: "192.168.0.2", allowed: false, why: "br0 drops everything but IPv6"} + - {from: h3, ping: "10.1.1.103", allowed: true, why: "br1 accepts new IPv4 from 10.1.1.102"} + - {from: h4, ping: "10.1.1.102", allowed: false, why: "br1 drops other IPv4 connections"} + - {from: h3, ping: "10.1.1.1", allowed: true, why: "br1 may access the router"} + - {from: h3, ping: "203.0.113.100", allowed: true, why: "br1 may reach the internet"} + - {from: h3, ping: "10.2.2.5", allowed: false, why: "br1 may not reach other LANs"} + - {from: h5, ping: "10.2.2.7", allowed: true, why: "br2 accepts all IPv4"} + - {from: h5, ping: "10.2.2.1", allowed: false, why: "br2 may not access the router"} + - {from: h5, ping: "203.0.113.100", allowed: true, why: "br2 may reach the internet"} + - {from: h5, ping: "10.1.1.102", allowed: true, why: "br2 may connect to br1"} + tasks: + - name: Ping per requirement + ansible.builtin.command: + cmd: docker exec clab-bp-bridge-{{ item.from }} ping -c 2 -W 2 {{ item.ping }} + become: "{{ lookup('ansible.builtin.env', 'CLAB_BECOME', default='true') | bool }}" + register: _ping + changed_when: false + failed_when: (_ping.rc == 0) != item.allowed + loop: "{{ _flows }}" + loop_control: + label: "{{ item.from }} -> {{ item.ping }} ({{ item.why }})" diff --git a/extensions/molecule/gre_tunnel/converge.yml b/extensions/molecule/gre_tunnel/converge.yml new file mode 100644 index 0000000..913e659 --- /dev/null +++ b/extensions/molecule/gre_tunnel/converge.yml @@ -0,0 +1,7 @@ +--- +- name: Converge + hosts: gre + gather_facts: false + roles: + - vyos.blueprints.base + - vyos.blueprints.gre_tunnel diff --git a/extensions/molecule/gre_tunnel/inventory.yml b/extensions/molecule/gre_tunnel/inventory.yml new file mode 100644 index 0000000..191ed70 --- /dev/null +++ b/extensions/molecule/gre_tunnel/inventory.yml @@ -0,0 +1,24 @@ +--- +all: + children: + vyos: + children: + gre: + hosts: + r1: + ansible_host: clab-bp-gre-r1 + base_interfaces: + - {name: eth1, addresses: [198.51.100.1/24]} + gre_tunnel_interfaces: + - {name: tun1, source_address: 198.51.100.1, remote: 198.51.100.2, mtu: 1376, adjust_mss: "1336", addresses: [172.16.122.1/30]} + r2: + ansible_host: clab-bp-gre-r2 + base_interfaces: + - {name: eth1, addresses: [198.51.100.2/24]} + gre_tunnel_interfaces: + - {name: tun1, source_address: 198.51.100.2, remote: 198.51.100.1, mtu: 1376, adjust_mss: "1336", addresses: [172.16.122.2/30]} + vars: + ansible_network_os: vyos.vyos.vyos + ansible_connection: ansible.netcommon.network_cli + ansible_user: admin + ansible_password: admin diff --git a/extensions/molecule/gre_tunnel/molecule.yml b/extensions/molecule/gre_tunnel/molecule.yml new file mode 100644 index 0000000..9fa905c --- /dev/null +++ b/extensions/molecule/gre_tunnel/molecule.yml @@ -0,0 +1,28 @@ +--- +# VyOS runs as a container (containerlab kind vyosnetworks_vyos); +# the lab is deployed in prepare and destroyed in cleanup. +dependency: + name: galaxy + enabled: false +driver: + name: default + options: + managed: false +platforms: + - name: r1 + - name: r2 +provisioner: + name: ansible + config_options: + defaults: + host_key_checking: false + persistent_connection: + command_timeout: 60 + inventory: + links: + hosts: inventory.yml + playbooks: + prepare: ../_shared/lab_up.yml + cleanup: ../_shared/lab_down.yml +verifier: + name: ansible diff --git a/extensions/molecule/gre_tunnel/topology.clab.yml b/extensions/molecule/gre_tunnel/topology.clab.yml new file mode 100644 index 0000000..7a5e955 --- /dev/null +++ b/extensions/molecule/gre_tunnel/topology.clab.yml @@ -0,0 +1,12 @@ +name: bp-gre +topology: + kinds: + vyosnetworks_vyos: + image: ${VYOS_IMAGE:=vyos:blueprints-ci} + nodes: + r1: + kind: vyosnetworks_vyos + r2: + kind: vyosnetworks_vyos + links: + - endpoints: ["r1:eth1", "r2:eth1"] diff --git a/extensions/molecule/gre_tunnel/verify.yml b/extensions/molecule/gre_tunnel/verify.yml new file mode 100644 index 0000000..88f2442 --- /dev/null +++ b/extensions/molecule/gre_tunnel/verify.yml @@ -0,0 +1,14 @@ +--- +- name: Verify + hosts: gre + gather_facts: false + tasks: + - name: Run role checks + ansible.builtin.include_role: + name: vyos.blueprints.gre_tunnel + tasks_from: verify + + - name: Ping the other end through the tunnel + vyos.vyos.vyos_ping: + dest: "{{ '172.16.122.2' if inventory_hostname == 'r1' else '172.16.122.1' }}" + count: 3 diff --git a/extensions/molecule/ipsec_route_based/converge.yml b/extensions/molecule/ipsec_route_based/converge.yml new file mode 100644 index 0000000..0fb7a50 --- /dev/null +++ b/extensions/molecule/ipsec_route_based/converge.yml @@ -0,0 +1,7 @@ +--- +- name: Converge + hosts: vpn + gather_facts: false + roles: + - vyos.blueprints.base + - vyos.blueprints.ipsec_route_based diff --git a/extensions/molecule/ipsec_route_based/inventory.yml b/extensions/molecule/ipsec_route_based/inventory.yml new file mode 100644 index 0000000..92b460c --- /dev/null +++ b/extensions/molecule/ipsec_route_based/inventory.yml @@ -0,0 +1,61 @@ +--- +all: + children: + vyos: + children: + vpn: + hosts: + r1: + ansible_host: clab-bp-ipsec-vyos + base_interfaces: + - {name: eth1, addresses: [10.0.1.2/30]} + - {name: eth2, addresses: [192.168.0.1/24]} + ipsec_route_based_peers: + - name: CISCO + local_address: 10.0.1.2 + remote_address: 10.0.2.2 + psk: molecule-psk + connection_type: initiate + vti: {interface: vti1, address: 10.100.100.1/30, mtu: 1438} + ipsec_route_based_ospf: + router_id: 2.2.2.2 + networks: [10.100.100.0/30, 192.168.0.0/24] + passive_interfaces: [eth2] + ipsec_route_based_default_gateway: 10.0.1.1 + r2: + ansible_host: clab-bp-ipsec-cisco + base_interfaces: + - {name: eth1, addresses: [10.0.2.2/30]} + - {name: eth2, addresses: [192.168.10.1/24]} + ipsec_route_based_peers: + - name: VYOS + local_address: 10.0.2.2 + remote_address: 10.0.1.2 + psk: molecule-psk + connection_type: none + vti: {interface: vti1, address: 10.100.100.2/30, mtu: 1438} + ipsec_route_based_ospf: + router_id: 1.1.1.1 + networks: [10.100.100.0/30, 192.168.10.0/24] + passive_interfaces: [eth2] + ipsec_route_based_default_gateway: 10.0.2.1 + vars: + # proposals from the page's IKE and IPsec parameter tables + ipsec_route_based_ike_group: + name: IKE-GROUP + key_exchange: ikev1 + lifetime: 28800 + dh_group: 14 + encryption: aes128 + hash: sha1 + ipsec_route_based_esp_group: + name: ESP-GROUP + lifetime: 3600 + pfs: disable + encryption: aes256 + hash: sha256 + vars: + ansible_network_os: vyos.vyos.vyos + ansible_connection: ansible.netcommon.network_cli + ansible_user: admin + ansible_password: admin diff --git a/extensions/molecule/ipsec_route_based/molecule.yml b/extensions/molecule/ipsec_route_based/molecule.yml new file mode 100644 index 0000000..9fa905c --- /dev/null +++ b/extensions/molecule/ipsec_route_based/molecule.yml @@ -0,0 +1,28 @@ +--- +# VyOS runs as a container (containerlab kind vyosnetworks_vyos); +# the lab is deployed in prepare and destroyed in cleanup. +dependency: + name: galaxy + enabled: false +driver: + name: default + options: + managed: false +platforms: + - name: r1 + - name: r2 +provisioner: + name: ansible + config_options: + defaults: + host_key_checking: false + persistent_connection: + command_timeout: 60 + inventory: + links: + hosts: inventory.yml + playbooks: + prepare: ../_shared/lab_up.yml + cleanup: ../_shared/lab_down.yml +verifier: + name: ansible diff --git a/extensions/molecule/ipsec_route_based/topology.clab.yml b/extensions/molecule/ipsec_route_based/topology.clab.yml new file mode 100644 index 0000000..f6b9b29 --- /dev/null +++ b/extensions/molecule/ipsec_route_based/topology.clab.yml @@ -0,0 +1,32 @@ +name: bp-ipsec +topology: + kinds: + vyosnetworks_vyos: + image: ${VYOS_IMAGE:=vyos:blueprints-ci} + nodes: + vyos: + kind: vyosnetworks_vyos + # second VyOS standing in for the page's Cisco router + cisco: + kind: vyosnetworks_vyos + isp: + kind: linux + image: alpine:3 + exec: + - sysctl -w net.ipv4.ip_forward=1 + - ip addr add 10.0.1.1/30 dev eth1 + - ip addr add 10.0.2.1/30 dev eth2 + pc1: + kind: linux + image: alpine:3 + exec: ["ip addr add 192.168.0.2/24 dev eth1", "ip route replace default via 192.168.0.1"] + pc3: + kind: linux + image: alpine:3 + exec: ["ip addr add 192.168.10.2/24 dev eth1", "ip route replace default via 192.168.10.1"] + links: + # WAN is eth1 here (eth0 on the page; eth0 is containerlab management) + - endpoints: ["vyos:eth1", "isp:eth1"] + - endpoints: ["cisco:eth1", "isp:eth2"] + - endpoints: ["vyos:eth2", "pc1:eth1"] + - endpoints: ["cisco:eth2", "pc3:eth1"] diff --git a/extensions/molecule/ipsec_route_based/verify.yml b/extensions/molecule/ipsec_route_based/verify.yml new file mode 100644 index 0000000..e190a90 --- /dev/null +++ b/extensions/molecule/ipsec_route_based/verify.yml @@ -0,0 +1,29 @@ +--- +- name: Verify role state + hosts: vpn + gather_facts: false + tasks: + - name: Wait for IKE, IPsec and OSPF + ansible.builtin.pause: + seconds: 45 + run_once: true + + - name: Run role checks + ansible.builtin.include_role: + name: vyos.blueprints.ipsec_route_based + tasks_from: verify + +- name: Verify traffic through the tunnel, as in the page's "Checking Connectivity" + hosts: localhost + gather_facts: false + tasks: + - name: Ping across the VPN in both directions + ansible.builtin.command: + cmd: docker exec clab-bp-ipsec-{{ item.from }} ping -c 3 -W 2 {{ item.to }} + become: "{{ lookup('ansible.builtin.env', 'CLAB_BECOME', default='true') | bool }}" + changed_when: false + loop: + - {from: pc1, to: 192.168.10.2} + - {from: pc3, to: 192.168.0.2} + loop_control: + label: "{{ item.from }} -> {{ item.to }}" diff --git a/extensions/molecule/ipsec_route_based_bgp/converge.yml b/extensions/molecule/ipsec_route_based_bgp/converge.yml new file mode 100644 index 0000000..0fb7a50 --- /dev/null +++ b/extensions/molecule/ipsec_route_based_bgp/converge.yml @@ -0,0 +1,7 @@ +--- +- name: Converge + hosts: vpn + gather_facts: false + roles: + - vyos.blueprints.base + - vyos.blueprints.ipsec_route_based diff --git a/extensions/molecule/ipsec_route_based_bgp/inventory.yml b/extensions/molecule/ipsec_route_based_bgp/inventory.yml new file mode 100644 index 0000000..dff75f1 --- /dev/null +++ b/extensions/molecule/ipsec_route_based_bgp/inventory.yml @@ -0,0 +1,86 @@ +--- +# Values from docs.vyos.io/en/1.5/configexamples/azure-vpn-bgp.html, except: +# - no NAT in the lab, so local_address is the public IP 198.51.100.3; +# - disable-route-autoinstall is set (the page does not set it): without it +# IPsec installs a route for the VTI's catch-all selector that would also +# capture containerlab management traffic; +# - both sides announce a LAN so the test can ping across BGP-learned routes. +all: + children: + vyos: + children: + vpn: + hosts: + r1: + ansible_host: clab-bp-azure-vyos + base_interfaces: + - {name: eth1, addresses: [198.51.100.3/24]} + - {name: eth2, addresses: [10.10.2.1/24]} + ipsec_route_based_peers: + - name: 203.0.113.2 + description: AZURE PRIMARY TUNNEL + psk_name: azure + psk: molecule-psk + local_address: 198.51.100.3 + remote_address: 203.0.113.2 + connection_type: initiate + ikev2_reauth: inherit + esp_group_on_vti: true + vti: {interface: vti1, address: 10.10.1.5/32, description: Azure Tunnel, adjust_mss: "1350"} + ipsec_route_based_interfaces: [eth1] + ipsec_route_based_interface_routes: + - {dest: 10.0.0.4/32, interface: vti1} + ipsec_route_based_bgp: + asn: 64499 + networks: [10.10.2.0/24] + neighbors: + - {address: 10.0.0.4, remote_as: 65540, holdtime: 30, keepalive: 10, soft_reconfiguration_inbound: true} + ipsec_route_based_default_gateway: 198.51.100.1 + r2: + ansible_host: clab-bp-azure-azure + base_interfaces: + - {name: eth1, addresses: [203.0.113.2/24]} + - {name: eth2, addresses: [10.0.1.1/24]} + ipsec_route_based_peers: + - name: 198.51.100.3 + psk_name: onprem + psk: molecule-psk + local_address: 203.0.113.2 + remote_address: 198.51.100.3 + connection_type: none + esp_group_on_vti: true + vti: {interface: vti1, address: 10.0.0.4/32} + ipsec_route_based_interfaces: [eth1] + ipsec_route_based_interface_routes: + - {dest: 10.10.1.5/32, interface: vti1} + ipsec_route_based_bgp: + asn: 65540 + networks: [10.0.1.0/24] + neighbors: + - {address: 10.10.1.5, remote_as: 64499, holdtime: 30, keepalive: 10} + ipsec_route_based_default_gateway: 203.0.113.1 + vars: + ipsec_route_based_ike_group: + name: AZURE + key_exchange: ikev2 + ikev2_reauth: true + lifetime: 28800 + proposal_id: 1 + dh_group: 2 + encryption: aes256 + hash: sha1 + dead_peer_detection: {action: restart, interval: 15, timeout: 30} + ipsec_route_based_esp_group: + name: AZURE + lifetime: 3600 + mode: tunnel + pfs: dh-group2 + proposal_id: 1 + encryption: aes256 + hash: sha1 + ipsec_route_based_disable_route_autoinstall: true + vars: + ansible_network_os: vyos.vyos.vyos + ansible_connection: ansible.netcommon.network_cli + ansible_user: admin + ansible_password: admin diff --git a/extensions/molecule/ipsec_route_based_bgp/molecule.yml b/extensions/molecule/ipsec_route_based_bgp/molecule.yml new file mode 100644 index 0000000..9fa905c --- /dev/null +++ b/extensions/molecule/ipsec_route_based_bgp/molecule.yml @@ -0,0 +1,28 @@ +--- +# VyOS runs as a container (containerlab kind vyosnetworks_vyos); +# the lab is deployed in prepare and destroyed in cleanup. +dependency: + name: galaxy + enabled: false +driver: + name: default + options: + managed: false +platforms: + - name: r1 + - name: r2 +provisioner: + name: ansible + config_options: + defaults: + host_key_checking: false + persistent_connection: + command_timeout: 60 + inventory: + links: + hosts: inventory.yml + playbooks: + prepare: ../_shared/lab_up.yml + cleanup: ../_shared/lab_down.yml +verifier: + name: ansible diff --git a/extensions/molecule/ipsec_route_based_bgp/topology.clab.yml b/extensions/molecule/ipsec_route_based_bgp/topology.clab.yml new file mode 100644 index 0000000..e8ba878 --- /dev/null +++ b/extensions/molecule/ipsec_route_based_bgp/topology.clab.yml @@ -0,0 +1,28 @@ +name: bp-azure +topology: + kinds: + vyosnetworks_vyos: + image: ${VYOS_IMAGE:=vyos:blueprints-ci} + nodes: + vyos: + kind: vyosnetworks_vyos + # second VyOS standing in for the Azure VNet gateway + azure: + kind: vyosnetworks_vyos + isp: + kind: linux + image: alpine:3 + exec: ["sysctl -w net.ipv4.ip_forward=1", "ip addr add 198.51.100.1/24 dev eth1", "ip addr add 203.0.113.1/24 dev eth2"] + onprem: + kind: linux + image: alpine:3 + exec: ["ip addr add 10.10.2.10/24 dev eth1", "ip route replace default via 10.10.2.1"] + vm: + kind: linux + image: alpine:3 + exec: ["ip addr add 10.0.1.10/24 dev eth1", "ip route replace default via 10.0.1.1"] + links: + - endpoints: ["vyos:eth1", "isp:eth1"] + - endpoints: ["azure:eth1", "isp:eth2"] + - endpoints: ["vyos:eth2", "onprem:eth1"] + - endpoints: ["azure:eth2", "vm:eth1"] diff --git a/extensions/molecule/ipsec_route_based_bgp/verify.yml b/extensions/molecule/ipsec_route_based_bgp/verify.yml new file mode 100644 index 0000000..04ad7c2 --- /dev/null +++ b/extensions/molecule/ipsec_route_based_bgp/verify.yml @@ -0,0 +1,29 @@ +--- +- name: Verify role state + hosts: vpn + gather_facts: false + tasks: + - name: Wait for IKE, IPsec and BGP + ansible.builtin.pause: + seconds: 60 + run_once: true + + - name: Run role checks + ansible.builtin.include_role: + name: vyos.blueprints.ipsec_route_based + tasks_from: verify + +- name: Verify traffic over BGP-learned routes through the tunnel + hosts: localhost + gather_facts: false + tasks: + - name: Ping between on-premises and the "Azure" LAN + ansible.builtin.command: + cmd: docker exec clab-bp-azure-{{ item.from }} ping -c 3 -W 2 {{ item.to }} + become: "{{ lookup('ansible.builtin.env', 'CLAB_BECOME', default='true') | bool }}" + changed_when: false + loop: + - {from: onprem, to: 10.0.1.10} + - {from: vm, to: 10.10.2.10} + loop_control: + label: "{{ item.from }} -> {{ item.to }}" diff --git a/extensions/molecule/ipsec_route_based_bgp_dual/converge.yml b/extensions/molecule/ipsec_route_based_bgp_dual/converge.yml new file mode 100644 index 0000000..0fb7a50 --- /dev/null +++ b/extensions/molecule/ipsec_route_based_bgp_dual/converge.yml @@ -0,0 +1,7 @@ +--- +- name: Converge + hosts: vpn + gather_facts: false + roles: + - vyos.blueprints.base + - vyos.blueprints.ipsec_route_based diff --git a/extensions/molecule/ipsec_route_based_bgp_dual/inventory.yml b/extensions/molecule/ipsec_route_based_bgp_dual/inventory.yml new file mode 100644 index 0000000..84d5c9d --- /dev/null +++ b/extensions/molecule/ipsec_route_based_bgp_dual/inventory.yml @@ -0,0 +1,115 @@ +--- +# Values from docs.vyos.io/en/1.5/configexamples/azure-vpn-dual-bgp.html, except: +# - no NAT in the lab, so local_address is the public IP 198.51.100.3; +# - the second gateway instance is on its own ISP subnet (203.0.114.0/24); +# - disable-route-autoinstall is set (see ipsec_route_based_bgp/inventory.yml); +# - both sides announce a LAN so the test can ping across BGP-learned routes. +all: + children: + vyos: + children: + vpn: + hosts: + r1: + ansible_host: clab-bp-azure2-vyos + base_interfaces: + - name: eth1 + addresses: [198.51.100.3/24] + - name: eth2 + addresses: [10.10.2.1/24] + ipsec_route_based_peers: + - name: azure-primary + description: AZURE PRIMARY TUNNEL + psk_name: azure + psk: molecule-psk + local_address: 198.51.100.3 + remote_address: 203.0.113.2 + connection_type: initiate + ikev2_reauth: inherit + esp_group_on_vti: true + vti: {interface: vti1, address: 10.10.1.5/32, adjust_mss: '1350'} + - name: azure-secondary + description: AZURE secondary TUNNEL + psk_name: azure + psk: molecule-psk + local_address: 198.51.100.3 + remote_address: 203.0.114.3 + connection_type: initiate + ikev2_reauth: inherit + esp_group_on_vti: true + vti: {interface: vti2, address: 10.10.1.6/32, adjust_mss: '1350'} + ipsec_route_based_interfaces: [eth1] + ipsec_route_based_interface_routes: + - {dest: 10.0.0.4/32, interface: vti1} + - {dest: 10.0.0.5/32, interface: vti2} + ipsec_route_based_bgp: + asn: 64499 + networks: [10.10.2.0/24] + neighbors: + - {address: 10.0.0.4, remote_as: 65540, holdtime: 30, keepalive: 10, soft_reconfiguration_inbound: true} + - {address: 10.0.0.5, remote_as: 65540, holdtime: 30, keepalive: 10, soft_reconfiguration_inbound: true} + ipsec_route_based_default_gateway: 198.51.100.1 + r2: + ansible_host: clab-bp-azure2-azure1 + base_interfaces: + - name: eth1 + addresses: [203.0.113.2/24] + - name: eth2 + addresses: [10.0.1.1/24] + ipsec_route_based_peers: + - name: 198.51.100.3 + psk_name: onprem + psk: molecule-psk + local_address: 203.0.113.2 + remote_address: 198.51.100.3 + connection_type: none + esp_group_on_vti: true + vti: {interface: vti1, address: 10.0.0.4/32} + ipsec_route_based_interfaces: [eth1] + ipsec_route_based_interface_routes: + - {dest: 10.10.1.5/32, interface: vti1} + ipsec_route_based_bgp: + asn: 65540 + networks: [10.0.1.0/24] + neighbors: + - {address: 10.10.1.5, remote_as: 64499, holdtime: 30, keepalive: 10} + ipsec_route_based_default_gateway: 203.0.113.1 + r3: + ansible_host: clab-bp-azure2-azure2 + base_interfaces: + - name: eth1 + addresses: [203.0.114.3/24] + - name: eth2 + addresses: [10.0.1.2/24] + ipsec_route_based_peers: + - name: 198.51.100.3 + psk_name: onprem + psk: molecule-psk + local_address: 203.0.114.3 + remote_address: 198.51.100.3 + connection_type: none + esp_group_on_vti: true + vti: {interface: vti1, address: 10.0.0.5/32} + ipsec_route_based_interfaces: [eth1] + ipsec_route_based_interface_routes: + - {dest: 10.10.1.6/32, interface: vti1} + ipsec_route_based_bgp: + asn: 65540 + networks: [10.0.1.0/24] + neighbors: + - {address: 10.10.1.6, remote_as: 64499, holdtime: 30, keepalive: 10} + ipsec_route_based_default_gateway: 203.0.114.1 + vars: + ipsec_route_based_ike_group: + name: AZURE + key_exchange: ikev2 + ikev2_reauth: true + lifetime: 28800 + proposal_id: 1 + dh_group: 2 + encryption: aes256 + hash: sha1 + dead_peer_detection: {action: restart, interval: 15, timeout: 30} + ipsec_route_based_esp_group: {name: AZURE, lifetime: 3600, mode: tunnel, pfs: dh-group2, proposal_id: 1, encryption: aes256, hash: sha1} + ipsec_route_based_disable_route_autoinstall: true + vars: {ansible_network_os: vyos.vyos.vyos, ansible_connection: ansible.netcommon.network_cli, ansible_user: admin, ansible_password: admin} diff --git a/extensions/molecule/ipsec_route_based_bgp_dual/molecule.yml b/extensions/molecule/ipsec_route_based_bgp_dual/molecule.yml new file mode 100644 index 0000000..11a5f84 --- /dev/null +++ b/extensions/molecule/ipsec_route_based_bgp_dual/molecule.yml @@ -0,0 +1,29 @@ +--- +# VyOS runs as a container (containerlab kind vyosnetworks_vyos); +# the lab is deployed in prepare and destroyed in cleanup. +dependency: + name: galaxy + enabled: false +driver: + name: default + options: + managed: false +platforms: + - name: r1 + - name: r2 + - name: r3 +provisioner: + name: ansible + config_options: + defaults: + host_key_checking: false + persistent_connection: + command_timeout: 60 + inventory: + links: + hosts: inventory.yml + playbooks: + prepare: ../_shared/lab_up.yml + cleanup: ../_shared/lab_down.yml +verifier: + name: ansible diff --git a/extensions/molecule/ipsec_route_based_bgp_dual/topology.clab.yml b/extensions/molecule/ipsec_route_based_bgp_dual/topology.clab.yml new file mode 100644 index 0000000..140aee6 --- /dev/null +++ b/extensions/molecule/ipsec_route_based_bgp_dual/topology.clab.yml @@ -0,0 +1,39 @@ +name: bp-azure2 +topology: + kinds: + vyosnetworks_vyos: + image: ${VYOS_IMAGE:=vyos:blueprints-ci} + nodes: + vyos: + kind: vyosnetworks_vyos + # two VyOS standing in for the active-active Azure VNet gateway instances + azure1: + kind: vyosnetworks_vyos + azure2: + kind: vyosnetworks_vyos + isp: + kind: linux + image: alpine:3 + exec: ["sysctl -w net.ipv4.ip_forward=1", "ip addr add 198.51.100.1/24 dev eth1", "ip addr add 203.0.113.1/24 dev eth2", "ip addr add 203.0.114.1/24 dev eth3"] + onprem: + kind: linux + image: alpine:3 + exec: ["ip addr add 10.10.2.10/24 dev eth1", "ip route replace default via 10.10.2.1"] + # the "VNet": one host behind both gateway instances + vm: + kind: linux + image: alpine:3 + exec: + - ip link add br0 type bridge + - ip link set eth1 master br0 + - ip link set eth2 master br0 + - ip link set br0 up + - ip addr add 10.0.1.10/24 dev br0 + - ip route replace 10.10.0.0/16 nexthop via 10.0.1.1 nexthop via 10.0.1.2 + links: + - endpoints: ["vyos:eth1", "isp:eth1"] + - endpoints: ["azure1:eth1", "isp:eth2"] + - endpoints: ["azure2:eth1", "isp:eth3"] + - endpoints: ["vyos:eth2", "onprem:eth1"] + - endpoints: ["azure1:eth2", "vm:eth1"] + - endpoints: ["azure2:eth2", "vm:eth2"] diff --git a/extensions/molecule/ipsec_route_based_bgp_dual/verify.yml b/extensions/molecule/ipsec_route_based_bgp_dual/verify.yml new file mode 100644 index 0000000..34bee33 --- /dev/null +++ b/extensions/molecule/ipsec_route_based_bgp_dual/verify.yml @@ -0,0 +1,47 @@ +--- +- name: Verify both tunnels and BGP sessions + hosts: vpn + gather_facts: false + tasks: + - name: Wait for IKE, IPsec and BGP + ansible.builtin.pause: + seconds: 60 + run_once: true + + - name: Run role checks + ansible.builtin.include_role: + name: vyos.blueprints.ipsec_route_based + tasks_from: verify + +- name: Verify redundancy - traffic survives losing the primary tunnel + hosts: r1 + gather_facts: false + vars: + _ping: docker exec clab-bp-azure2-onprem ping -c 3 -W 2 10.0.1.10 + _become: "{{ lookup('ansible.builtin.env', 'CLAB_BECOME', default='true') | bool }}" + tasks: + - name: Ping the VNet with both tunnels up + ansible.builtin.command: "{{ _ping }}" + delegate_to: localhost + become: "{{ _become }}" + changed_when: false + + - name: Take the primary tunnel down + vyos.vyos.vyos_config: + lines: + - set vpn ipsec site-to-site peer azure-primary disable + + - name: Wait for BGP to converge on the secondary path + ansible.builtin.pause: + seconds: 40 + + - name: Ping the VNet over the secondary tunnel only + ansible.builtin.command: "{{ _ping }}" + delegate_to: localhost + become: "{{ _become }}" + changed_when: false + + - name: Bring the primary tunnel back + vyos.vyos.vyos_config: + lines: + - delete vpn ipsec site-to-site peer azure-primary disable diff --git a/extensions/molecule/ospf_unnumbered/converge.yml b/extensions/molecule/ospf_unnumbered/converge.yml new file mode 100644 index 0000000..c5e906b --- /dev/null +++ b/extensions/molecule/ospf_unnumbered/converge.yml @@ -0,0 +1,7 @@ +--- +- name: Converge + hosts: fabric + gather_facts: false + roles: + - vyos.blueprints.base + - vyos.blueprints.ospf_unnumbered diff --git a/extensions/molecule/ospf_unnumbered/inventory.yml b/extensions/molecule/ospf_unnumbered/inventory.yml new file mode 100644 index 0000000..efaf93f --- /dev/null +++ b/extensions/molecule/ospf_unnumbered/inventory.yml @@ -0,0 +1,26 @@ +--- +all: + children: + vyos: + children: + fabric: + hosts: + r1: + ansible_host: clab-bp-ospf-r1 + ospf_unnumbered_router_id: 192.168.0.1 + base_interfaces: + - {name: eth3, addresses: [10.1.0.1/24]} + r2: + ansible_host: clab-bp-ospf-r2 + ospf_unnumbered_router_id: 192.168.0.2 + base_interfaces: + - {name: eth3, addresses: [10.2.0.1/24]} + vars: + ospf_unnumbered_interfaces: [eth1, eth2] + ospf_unnumbered_md5_key: molecule-ospf + ospf_unnumbered_group: fabric + vars: + ansible_network_os: vyos.vyos.vyos + ansible_connection: ansible.netcommon.network_cli + ansible_user: admin + ansible_password: admin diff --git a/extensions/molecule/ospf_unnumbered/molecule.yml b/extensions/molecule/ospf_unnumbered/molecule.yml new file mode 100644 index 0000000..9fa905c --- /dev/null +++ b/extensions/molecule/ospf_unnumbered/molecule.yml @@ -0,0 +1,28 @@ +--- +# VyOS runs as a container (containerlab kind vyosnetworks_vyos); +# the lab is deployed in prepare and destroyed in cleanup. +dependency: + name: galaxy + enabled: false +driver: + name: default + options: + managed: false +platforms: + - name: r1 + - name: r2 +provisioner: + name: ansible + config_options: + defaults: + host_key_checking: false + persistent_connection: + command_timeout: 60 + inventory: + links: + hosts: inventory.yml + playbooks: + prepare: ../_shared/lab_up.yml + cleanup: ../_shared/lab_down.yml +verifier: + name: ansible diff --git a/extensions/molecule/ospf_unnumbered/topology.clab.yml b/extensions/molecule/ospf_unnumbered/topology.clab.yml new file mode 100644 index 0000000..e2fb3c9 --- /dev/null +++ b/extensions/molecule/ospf_unnumbered/topology.clab.yml @@ -0,0 +1,20 @@ +name: bp-ospf +topology: + kinds: + vyosnetworks_vyos: + image: ${VYOS_IMAGE:=vyos:blueprints-ci} + nodes: + r1: + kind: vyosnetworks_vyos + r2: + kind: vyosnetworks_vyos + lan: + kind: linux + image: alpine:3 + links: + # two parallel unnumbered links -> ECMP, as on the docs page + - endpoints: ["r1:eth1", "r2:eth1"] + - endpoints: ["r1:eth2", "r2:eth2"] + # LAN side (eth0 on the docs page; eth0 is management in containerlab) + - endpoints: ["r1:eth3", "lan:eth1"] + - endpoints: ["r2:eth3", "lan:eth2"] diff --git a/extensions/molecule/ospf_unnumbered/verify.yml b/extensions/molecule/ospf_unnumbered/verify.yml new file mode 100644 index 0000000..d75a2ea --- /dev/null +++ b/extensions/molecule/ospf_unnumbered/verify.yml @@ -0,0 +1,27 @@ +--- +- name: Verify + hosts: fabric + gather_facts: false + tasks: + - name: Wait for OSPF adjacencies and routes + ansible.builtin.pause: + seconds: 45 + run_once: true + + - name: Run role checks + ansible.builtin.include_role: + name: vyos.blueprints.ospf_unnumbered + tasks_from: verify + + - name: Read the route to the other router's LAN + vyos.vyos.vyos_command: + commands: + - "show ip route {{ '10.2.0.0/24' if inventory_hostname == 'r1' else '10.1.0.0/24' }}" + register: _lan_route + + - name: The other LAN is learned via OSPF (redistribute connected) over both links + ansible.builtin.assert: + that: + - _lan_route.stdout[0] is search('Known via "ospf"') + - _lan_route.stdout[0] | regex_findall('via \S+ onlink') | length == 2 + quiet: true diff --git a/extensions/molecule/policy_ipsec_firewall/converge.yml b/extensions/molecule/policy_ipsec_firewall/converge.yml new file mode 100644 index 0000000..1696e59 --- /dev/null +++ b/extensions/molecule/policy_ipsec_firewall/converge.yml @@ -0,0 +1,9 @@ +--- +- name: Converge + hosts: sites + gather_facts: false + roles: + - vyos.blueprints.base + - vyos.blueprints.ipsec_policy_based + - vyos.blueprints.firewall + - vyos.blueprints.nat diff --git a/extensions/molecule/policy_ipsec_firewall/inventory.yml b/extensions/molecule/policy_ipsec_firewall/inventory.yml new file mode 100644 index 0000000..afc0223 --- /dev/null +++ b/extensions/molecule/policy_ipsec_firewall/inventory.yml @@ -0,0 +1,131 @@ +--- +all: + children: + vyos: + children: + sites: + hosts: + left: + ansible_host: clab-bp-pif-left + ipsec_policy_based_peers: + - name: RIGHT + psk_name: RIGHT + psk: molecule-psk + authentication_ids: false + local_address: 198.51.100.14 + remote_address: 192.0.2.130 + connection_type: initiate + tunnels: + - {id: 0, local_prefix: 10.1.11.0/24, remote_prefix: 10.2.21.0/24} + - {id: 1, local_prefix: 10.1.11.0/24, remote_prefix: 10.2.22.0/24} + - {id: 2, local_prefix: 10.1.12.0/24, remote_prefix: 10.2.21.0/24} + - {id: 3, local_prefix: 10.1.12.0/24, remote_prefix: 10.2.22.0/24} + ipsec_policy_based_default_gateway: 198.51.100.13 + firewall_groups: + network: + - name: LOCAL-NETS + networks: [10.1.11.0/24, 10.1.12.0/24] + - name: REMOTE-NETS + networks: [10.2.21.0/24, 10.2.22.0/24] + - name: TRUSTED + networks: [198.51.100.125/32, 203.0.113.0/24, 10.1.11.0/24, 192.168.70.0/24] + firewall_ipv4: + forward: + default_action: drop + rules: + - number: 1 + action: accept + state: {established: true, related: true} + - number: 2 + action: drop + state: {invalid: true} + - number: 10 + action: accept + source: + group: {network_group: LOCAL-NETS} + - number: 20 + action: accept + source: + group: {network_group: REMOTE-NETS} + destination: + group: {network_group: LOCAL-NETS} + input: + default_action: drop + rules: + - number: 1 + action: accept + state: {established: true, related: true} + - number: 2 + action: drop + state: {invalid: true} + - number: 5 + action: accept + description: containerlab management + inbound_interface: {name: eth0} + - number: 10 + action: accept + protocol: udp + destination: {port: '500,4500'} + inbound_interface: {name: eth3} + - number: 15 + action: accept + protocol: esp + inbound_interface: {name: eth3} + - number: 20 + action: accept + protocol: tcp + destination: {port: '22'} + source: + group: {network_group: TRUSTED} + - number: 25 + action: accept + protocol: udp + destination: {port: '53'} + source: + group: {network_group: LOCAL-NETS} + - {number: 30, action: accept, protocol: icmp} + nat_source_rules: + - id: 10 + exclude: true + outbound_interface: {name: eth3} + source: {network_group: LOCAL-NETS} + destination: {network_group: REMOTE-NETS} + - id: 20 + outbound_interface: {name: eth3} + source: {network_group: LOCAL-NETS} + translation: {address: masquerade} + base_interfaces: + - name: eth3 + addresses: [198.51.100.14/30] + - name: eth1.111 + addresses: [10.1.11.1/24] + - name: eth2.112 + addresses: [10.1.12.1/24] + right: + ansible_host: clab-bp-pif-right + ipsec_policy_based_peers: + - name: LEFT + psk_name: LEFT + psk: molecule-psk + authentication_ids: false + local_address: 192.0.2.130 + remote_address: 198.51.100.14 + connection_type: none + tunnels: + - {id: 0, local_prefix: 10.2.21.0/24, remote_prefix: 10.1.11.0/24} + - {id: 1, local_prefix: 10.2.22.0/24, remote_prefix: 10.1.11.0/24} + - {id: 2, local_prefix: 10.2.21.0/24, remote_prefix: 10.1.12.0/24} + - {id: 3, local_prefix: 10.2.22.0/24, remote_prefix: 10.1.12.0/24} + base_interfaces: + - name: eth3 + addresses: [192.0.2.130/30] + - name: eth1.221 + addresses: [10.2.21.1/24] + - name: eth2.222 + addresses: [10.2.22.1/24] + ipsec_policy_based_default_gateway: 192.0.2.129 + vars: + ipsec_policy_based_ike_group: {name: IKE-GROUP, key_exchange: ikev2, proposal_id: 1, dh_group: 14, encryption: aes256, hash: sha256} + ipsec_policy_based_esp_group: {name: ESP-GROUP, mode: tunnel, proposal_id: 1, encryption: aes256, hash: sha256} + ipsec_policy_based_interfaces: [eth3] + vars: {ansible_network_os: vyos.vyos.vyos, ansible_connection: ansible.netcommon.network_cli, ansible_user: admin, ansible_password: admin} diff --git a/extensions/molecule/policy_ipsec_firewall/molecule.yml b/extensions/molecule/policy_ipsec_firewall/molecule.yml new file mode 100644 index 0000000..9fa905c --- /dev/null +++ b/extensions/molecule/policy_ipsec_firewall/molecule.yml @@ -0,0 +1,28 @@ +--- +# VyOS runs as a container (containerlab kind vyosnetworks_vyos); +# the lab is deployed in prepare and destroyed in cleanup. +dependency: + name: galaxy + enabled: false +driver: + name: default + options: + managed: false +platforms: + - name: r1 + - name: r2 +provisioner: + name: ansible + config_options: + defaults: + host_key_checking: false + persistent_connection: + command_timeout: 60 + inventory: + links: + hosts: inventory.yml + playbooks: + prepare: ../_shared/lab_up.yml + cleanup: ../_shared/lab_down.yml +verifier: + name: ansible diff --git a/extensions/molecule/policy_ipsec_firewall/topology.clab.yml b/extensions/molecule/policy_ipsec_firewall/topology.clab.yml new file mode 100644 index 0000000..a94822e --- /dev/null +++ b/extensions/molecule/policy_ipsec_firewall/topology.clab.yml @@ -0,0 +1,51 @@ +name: bp-pif +topology: + kinds: + vyosnetworks_vyos: + image: ${VYOS_IMAGE:=vyos:blueprints-ci} + nodes: + left: + kind: vyosnetworks_vyos + right: + kind: vyosnetworks_vyos + isp: + kind: linux + image: alpine:3 + exec: + - sysctl -w net.ipv4.ip_forward=1 + - ip addr add 198.51.100.13/30 dev eth1 + - ip addr add 192.0.2.129/30 dev eth2 + - ip addr add 203.0.113.1/24 dev eth3 + internet: + kind: linux + image: alpine:3 + exec: ["ip addr add 203.0.113.10/24 dev eth1", "ip route replace default via 203.0.113.1"] + l11: + kind: linux + image: alpine:3 + exec: ["ip link add link eth1 name eth1.111 type vlan id 111", "ip link set eth1.111 up", + "ip addr add 10.1.11.10/24 dev eth1.111", "ip route replace default via 10.1.11.1"] + l12: + kind: linux + image: alpine:3 + exec: ["ip link add link eth1 name eth1.112 type vlan id 112", "ip link set eth1.112 up", + "ip addr add 10.1.12.10/24 dev eth1.112", "ip route replace default via 10.1.12.1"] + r21: + kind: linux + image: alpine:3 + exec: ["ip link add link eth1 name eth1.221 type vlan id 221", "ip link set eth1.221 up", + "ip addr add 10.2.21.10/24 dev eth1.221", "ip route replace default via 10.2.21.1"] + r22: + kind: linux + image: alpine:3 + exec: ["ip link add link eth1 name eth1.222 type vlan id 222", "ip link set eth1.222 up", + "ip addr add 10.2.22.10/24 dev eth1.222", "ip route replace default via 10.2.22.1"] + links: + # WAN is eth3 here (eth0 on the page; eth0 is containerlab management) + - endpoints: ["left:eth3", "isp:eth1"] + - endpoints: ["right:eth3", "isp:eth2"] + - endpoints: ["isp:eth3", "internet:eth1"] + - endpoints: ["left:eth1", "l11:eth1"] + - endpoints: ["left:eth2", "l12:eth1"] + - endpoints: ["right:eth1", "r21:eth1"] + - endpoints: ["right:eth2", "r22:eth1"] diff --git a/extensions/molecule/policy_ipsec_firewall/verify.yml b/extensions/molecule/policy_ipsec_firewall/verify.yml new file mode 100644 index 0000000..5502dc4 --- /dev/null +++ b/extensions/molecule/policy_ipsec_firewall/verify.yml @@ -0,0 +1,35 @@ +--- +- name: Verify role state + hosts: sites + gather_facts: false + tasks: + - name: Wait for IKE and IPsec + ansible.builtin.pause: + seconds: 30 + run_once: true + + - name: Run role checks + ansible.builtin.include_role: + name: "vyos.blueprints.{{ item }}" + tasks_from: verify + loop: "{{ ['ipsec_policy_based', 'firewall', 'nat'] if inventory_hostname == 'left' else ['ipsec_policy_based'] }}" + +- name: Verify the page's requirements with traffic + hosts: localhost + gather_facts: false + vars: + _flows: + - {from: l11, to: 10.2.21.10, why: "LAN to LAN through the tunnel, without NAT"} + - {from: l12, to: 10.2.22.10, why: "second LAN pair through the tunnel"} + - {from: r21, to: 10.1.11.10, why: "remote LANs may connect to local LANs"} + - {from: l11, to: 203.0.113.10, why: "local subnets reach the internet using source NAT"} + - {from: internet, to: 198.51.100.14, why: "ICMP is allowed on all interfaces"} + tasks: + - name: Ping per requirement + ansible.builtin.command: + cmd: docker exec clab-bp-pif-{{ item.from }} ping -c 3 -W 2 {{ item.to }} + become: "{{ lookup('ansible.builtin.env', 'CLAB_BECOME', default='true') | bool }}" + changed_when: false + loop: "{{ _flows }}" + loop_control: + label: "{{ item.from }} -> {{ item.to }} ({{ item.why }})" diff --git a/extensions/molecule/vrf_firewall/converge.yml b/extensions/molecule/vrf_firewall/converge.yml new file mode 100644 index 0000000..bdf90f7 --- /dev/null +++ b/extensions/molecule/vrf_firewall/converge.yml @@ -0,0 +1,7 @@ +--- +- name: Converge + hosts: vyos + gather_facts: false + roles: + - vyos.blueprints.base + - vyos.blueprints.vrf_firewall diff --git a/extensions/molecule/vrf_firewall/inventory.yml b/extensions/molecule/vrf_firewall/inventory.yml new file mode 100644 index 0000000..4d3b6f7 --- /dev/null +++ b/extensions/molecule/vrf_firewall/inventory.yml @@ -0,0 +1,54 @@ +--- +all: + children: + vyos: + hosts: + r1: + ansible_host: clab-bp-vrf-r1 + vars: + ansible_network_os: vyos.vyos.vyos + ansible_connection: ansible.netcommon.network_cli + ansible_user: admin + ansible_password: admin + base_interfaces: + - {name: eth1, addresses: [10.100.100.1/24]} + - {name: eth2} + - {name: eth2.150, addresses: [10.150.150.1/24]} + - {name: eth2.3500, addresses: [172.16.20.1/24]} + - {name: eth3, addresses: [203.0.113.1/24]} + vrf_firewall_vrfs: + - name: MGMT + table: 102 + interfaces: [eth1] + routes: + - {dest: 10.150.150.0/24, interface: eth2.150, vrf: LAN} + - {dest: 172.16.20.0/24, interface: eth2.3500, vrf: PROD} + - name: WAN + table: 101 + interfaces: [eth3] + routes: + - {dest: 10.150.150.0/24, interface: eth2.150, vrf: LAN} + - {dest: 172.16.20.0/24, interface: eth2.3500, vrf: PROD} + - name: LAN + table: 103 + interfaces: [eth2.150] + routes: + - {dest: 0.0.0.0/0, interface: eth3, vrf: WAN} + - {dest: 10.100.100.0/24, interface: eth1, vrf: MGMT} + - {dest: 172.16.20.0/24, interface: eth2.3500, vrf: PROD} + - name: PROD + table: 104 + interfaces: [eth2.3500] + routes: + - {dest: 0.0.0.0/0, interface: eth3, vrf: WAN} + - {dest: 10.100.100.0/24, interface: eth1, vrf: MGMT} + - {dest: 10.150.150.0/24, interface: eth2.150, vrf: LAN} + vrf_firewall_forward_rules: + - {number: 10, description: MGMT - Allow to LAN and PROD, inbound_interface: MGMT, outbound_interface: eth2*} + - {number: 99, action: drop, description: MGMT - Drop all going to mgmt, outbound_interface: eth1} + - {number: 120, description: LAN - Allow to PROD, inbound_interface: LAN, outbound_interface: eth2.3500} + - {number: 130, description: LAN - Allow internet, inbound_interface: LAN, outbound_interface: eth3} + vrf_firewall_input_rules: + # containerlab management; keeps Ansible's SSH session working + - {number: 5, description: containerlab management, inbound_interface: eth0} + - {number: 10, description: MGMT - Allow input, inbound_interface: MGMT} diff --git a/extensions/molecule/vrf_firewall/molecule.yml b/extensions/molecule/vrf_firewall/molecule.yml new file mode 100644 index 0000000..612af0a --- /dev/null +++ b/extensions/molecule/vrf_firewall/molecule.yml @@ -0,0 +1,27 @@ +--- +# VyOS runs as a container (containerlab kind vyosnetworks_vyos); +# the lab is deployed in prepare and destroyed in cleanup. +dependency: + name: galaxy + enabled: false +driver: + name: default + options: + managed: false +platforms: + - name: r1 +provisioner: + name: ansible + config_options: + defaults: + host_key_checking: false + persistent_connection: + command_timeout: 60 + inventory: + links: + hosts: inventory.yml + playbooks: + prepare: ../_shared/lab_up.yml + cleanup: ../_shared/lab_down.yml +verifier: + name: ansible diff --git a/extensions/molecule/vrf_firewall/topology.clab.yml b/extensions/molecule/vrf_firewall/topology.clab.yml new file mode 100644 index 0000000..567cd56 --- /dev/null +++ b/extensions/molecule/vrf_firewall/topology.clab.yml @@ -0,0 +1,43 @@ +name: bp-vrf +topology: + nodes: + r1: + kind: vyosnetworks_vyos + image: ${VYOS_IMAGE:=vyos:blueprints-ci} + mgmt: + kind: linux + image: alpine:3 + exec: ["ip addr add 10.100.100.10/24 dev eth1", "ip route replace default via 10.100.100.1"] + # VLAN-aware bridge for the eth2 trunk (vif 150 = LAN, vif 3500 = PROD) + sw: + kind: linux + image: alpine:3 + exec: + - ip link add br0 type bridge vlan_filtering 1 + - ip link set eth1 master br0 + - ip link set eth2 master br0 + - ip link set eth3 master br0 + - bridge vlan add dev eth1 vid 150 + - bridge vlan add dev eth1 vid 3500 + - bridge vlan add dev eth2 vid 150 pvid untagged + - bridge vlan add dev eth3 vid 3500 pvid untagged + - ip link set br0 up + lan: + kind: linux + image: alpine:3 + exec: ["ip addr add 10.150.150.10/24 dev eth1", "ip route replace default via 10.150.150.1"] + prod: + kind: linux + image: alpine:3 + exec: ["ip addr add 172.16.20.10/24 dev eth1", "ip route replace default via 172.16.20.1"] + # stands in for the page's PPPoE uplink + wan: + kind: linux + image: alpine:3 + exec: ["ip addr add 203.0.113.100/24 dev eth1", "ip route replace default via 203.0.113.1"] + links: + - endpoints: ["r1:eth1", "mgmt:eth1"] + - endpoints: ["r1:eth2", "sw:eth1"] + - endpoints: ["sw:eth2", "lan:eth1"] + - endpoints: ["sw:eth3", "prod:eth1"] + - endpoints: ["r1:eth3", "wan:eth1"] diff --git a/extensions/molecule/vrf_firewall/verify.yml b/extensions/molecule/vrf_firewall/verify.yml new file mode 100644 index 0000000..82989cc --- /dev/null +++ b/extensions/molecule/vrf_firewall/verify.yml @@ -0,0 +1,36 @@ +--- +- name: Verify role state + hosts: vyos + gather_facts: false + tasks: + - name: Run role checks + ansible.builtin.include_role: + name: vyos.blueprints.vrf_firewall + tasks_from: verify + +- name: Verify traffic between VRFs against the page's requirements + hosts: localhost + gather_facts: false + vars: + _flows: + - {from: mgmt, to: 10.150.150.10, allowed: true, why: "MGMT may connect to LAN"} + - {from: mgmt, to: 172.16.20.10, allowed: true, why: "MGMT may connect to PROD"} + - {from: mgmt, to: 203.0.113.100, allowed: false, why: "MGMT may not reach the internet"} + - {from: lan, to: 172.16.20.10, allowed: true, why: "LAN may connect to PROD"} + - {from: lan, to: 203.0.113.100, allowed: true, why: "LAN may reach the internet"} + - {from: lan, to: 10.100.100.10, allowed: false, why: "nothing may connect to MGMT"} + - {from: prod, to: 10.150.150.10, allowed: false, why: "PROD only accepts connections"} + # The page's text says WAN may connect to PROD, but its configuration has + # no rule for it, so the configuration (default drop) is what is tested. + - {from: wan, to: 172.16.20.10, allowed: false, why: "no WAN->PROD rule in the page's configuration"} + tasks: + - name: Ping across VRFs + ansible.builtin.command: + cmd: docker exec clab-bp-vrf-{{ item.from }} ping -c 2 -W 2 {{ item.to }} + become: "{{ lookup('ansible.builtin.env', 'CLAB_BECOME', default='true') | bool }}" + register: _ping + changed_when: false + failed_when: (_ping.rc == 0) != item.allowed + loop: "{{ _flows }}" + loop_control: + label: "{{ item.from }} -> {{ item.to }} ({{ item.why }})" diff --git a/extensions/molecule/zone_firewall/converge.yml b/extensions/molecule/zone_firewall/converge.yml new file mode 100644 index 0000000..03e3ad7 --- /dev/null +++ b/extensions/molecule/zone_firewall/converge.yml @@ -0,0 +1,7 @@ +--- +- name: Converge + hosts: vyos + gather_facts: false + roles: + - vyos.blueprints.base + - vyos.blueprints.zone_firewall diff --git a/extensions/molecule/zone_firewall/inventory.yml b/extensions/molecule/zone_firewall/inventory.yml new file mode 100644 index 0000000..6e9f461 --- /dev/null +++ b/extensions/molecule/zone_firewall/inventory.yml @@ -0,0 +1,33 @@ +--- +all: + children: + vyos: + hosts: + r1: + ansible_host: clab-bp-zfw-r1 + vars: + ansible_network_os: vyos.vyos.vyos + ansible_connection: ansible.netcommon.network_cli + ansible_user: admin + ansible_password: admin + base_interfaces: + - {name: eth1, addresses: [172.16.10.1/24]} + - {name: eth2, addresses: [192.168.100.1/24]} + - {name: eth3, addresses: [192.168.200.1/24]} + zone_firewall_zones: + # containerlab management; keeps Ansible's SSH session working + - {name: mgmt, interfaces: [eth0]} + - {name: wan, interfaces: [eth1]} + - {name: lan, interfaces: [eth2]} + - {name: dmz, interfaces: [eth3]} + - {name: local, local: true} + zone_firewall_policies: + - {from: mgmt, to: local, default_action: accept} + - from: wan + to: dmz + rules: + - {number: 200, protocol: tcp, destination: {address: 192.168.200.200, port: "80,443"}} + - from: lan + to: dmz + rules: + - {number: 200, protocol: tcp, destination: {port: "80,443"}} diff --git a/extensions/molecule/zone_firewall/molecule.yml b/extensions/molecule/zone_firewall/molecule.yml new file mode 100644 index 0000000..612af0a --- /dev/null +++ b/extensions/molecule/zone_firewall/molecule.yml @@ -0,0 +1,27 @@ +--- +# VyOS runs as a container (containerlab kind vyosnetworks_vyos); +# the lab is deployed in prepare and destroyed in cleanup. +dependency: + name: galaxy + enabled: false +driver: + name: default + options: + managed: false +platforms: + - name: r1 +provisioner: + name: ansible + config_options: + defaults: + host_key_checking: false + persistent_connection: + command_timeout: 60 + inventory: + links: + hosts: inventory.yml + playbooks: + prepare: ../_shared/lab_up.yml + cleanup: ../_shared/lab_down.yml +verifier: + name: ansible diff --git a/extensions/molecule/zone_firewall/topology.clab.yml b/extensions/molecule/zone_firewall/topology.clab.yml new file mode 100644 index 0000000..9be83a6 --- /dev/null +++ b/extensions/molecule/zone_firewall/topology.clab.yml @@ -0,0 +1,34 @@ +name: bp-zfw +topology: + nodes: + r1: + kind: vyosnetworks_vyos + image: ${VYOS_IMAGE:=vyos:blueprints-ci} + wan: + kind: linux + image: alpine:3 + exec: + - ip addr add 172.16.10.100/24 dev eth1 + - ip route replace default via 172.16.10.1 + - apk add --no-cache busybox-extras + - httpd -p 80 -h /tmp + lan: + kind: linux + image: alpine:3 + exec: + - ip addr add 192.168.100.10/24 dev eth1 + - ip route replace default via 192.168.100.1 + - apk add --no-cache busybox-extras + - httpd -p 80 -h /tmp + dmz: + kind: linux + image: alpine:3 + exec: + - ip addr add 192.168.200.200/24 dev eth1 + - ip route replace default via 192.168.200.1 + - apk add --no-cache busybox-extras + - httpd -p 80 -h /tmp + links: + - endpoints: ["r1:eth1", "wan:eth1"] + - endpoints: ["r1:eth2", "lan:eth1"] + - endpoints: ["r1:eth3", "dmz:eth1"] diff --git a/extensions/molecule/zone_firewall/verify.yml b/extensions/molecule/zone_firewall/verify.yml new file mode 100644 index 0000000..16584f3 --- /dev/null +++ b/extensions/molecule/zone_firewall/verify.yml @@ -0,0 +1,30 @@ +--- +- name: Verify role state + hosts: vyos + gather_facts: false + tasks: + - name: Run role checks + ansible.builtin.include_role: + name: vyos.blueprints.zone_firewall + tasks_from: verify + +- name: Verify traffic between zones + hosts: localhost + gather_facts: false + vars: + _flows: + - {from: lan, to: 192.168.200.200, allowed: true, why: "LAN can access DMZ resources"} + - {from: wan, to: 192.168.200.200, allowed: true, why: "inbound WAN connects to the DMZ host"} + - {from: dmz, to: 192.168.100.10, allowed: false, why: "DMZ cannot access LAN resources"} + - {from: wan, to: 192.168.100.10, allowed: false, why: "WAN cannot reach the LAN"} + tasks: + - name: Try HTTP across zones + ansible.builtin.command: + cmd: docker exec clab-bp-zfw-{{ item.from }} wget -q -T 3 -O /dev/null http://{{ item.to }}/ + become: "{{ lookup('ansible.builtin.env', 'CLAB_BECOME', default='true') | bool }}" + register: _http + changed_when: false + failed_when: (_http.rc == 0) != item.allowed + loop: "{{ _flows }}" + loop_control: + label: "{{ item.from }} -> {{ item.to }} ({{ item.why }})" |
