diff options
Diffstat (limited to 'smoketest')
117 files changed, 1864 insertions, 343 deletions
| diff --git a/smoketest/bin/vyos-configtest b/smoketest/bin/vyos-configtest index fbf4055ad..23cbd4e54 100755 --- a/smoketest/bin/vyos-configtest +++ b/smoketest/bin/vyos-configtest @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/bin/vyos-configtest-pki b/smoketest/bin/vyos-configtest-pki index 0f9ecdd41..ac6272cc4 100755 --- a/smoketest/bin/vyos-configtest-pki +++ b/smoketest/bin/vyos-configtest-pki @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2022-2024, VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/bin/vyos-smoketest b/smoketest/bin/vyos-smoketest index 135388afe..d197499a7 100755 --- a/smoketest/bin/vyos-smoketest +++ b/smoketest/bin/vyos-smoketest @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2019-2020 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/config-tests/basic-haproxy b/smoketest/config-tests/basic-haproxy new file mode 100644 index 000000000..7755fc4ea --- /dev/null +++ b/smoketest/config-tests/basic-haproxy @@ -0,0 +1,46 @@ +set interfaces dummy dum0 address '172.18.254.203/32' +set interfaces ethernet eth0 duplex 'auto' +set interfaces ethernet eth0 speed 'auto' +set interfaces ethernet eth0 vif 203 address '172.18.203.10/24' +set interfaces ethernet eth1 duplex 'auto' +set interfaces ethernet eth1 speed 'auto' +set interfaces ethernet eth2 duplex 'auto' +set interfaces ethernet eth2 speed 'auto' +set load-balancing haproxy backend webserver logging facility daemon +set load-balancing haproxy backend webserver logging facility user level 'info' +set load-balancing haproxy backend webserver server web01 address '192.0.2.1' +set load-balancing haproxy backend webserver server web01 port '443' +set load-balancing haproxy backend webserver ssl no-verify +set load-balancing haproxy global-parameters logging facility daemon +set load-balancing haproxy global-parameters logging facility user level 'info' +set load-balancing haproxy service frontend backend 'webserver' +set load-balancing haproxy service frontend logging facility daemon +set load-balancing haproxy service frontend logging facility user level 'info' +set load-balancing haproxy service frontend port '443' +set load-balancing haproxy service frontend ssl certificate 'dummy' +set pki certificate dummy certificate 'MIIDsTCCApmgAwIBAgIUegVgO1wIN2v44trXZ+Kb1t48uL0wDQYJKoZIhvcNAQELBQAwVzELMAkGA1UEBhMCR0IxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNvbWUtQ2l0eTENMAsGA1UECgwEVnlPUzEQMA4GA1UEAwwHdnlvcy5pbzAeFw0yNTA1MDUxODIzMTdaFw0yNjA1MDUxODIzMTdaMFcxCzAJBgNVBAYTAkdCMRMwEQYDVQQIDApTb21lLVN0YXRlMRIwEAYDVQQHDAlTb21lLUNpdHkxDTALBgNVBAoMBFZ5T1MxEDAOBgNVBAMMB3Z5b3MuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDEfMAwYLKKVhGlUXr9gkVC7uBi+0O9yyEgd5QzPByePXYw0FrSLWmLRfQuByFDPIVANcEa3FgIXIAeKmxItw7IhFRsG5soSOXXgBxdAH/qzEbWhwzgafnxZKJkmrQr8YA3IFtkFPr2+5s26WdjtwEM0tzIFkq6hmWSX1axUgvYlF2uCxjututMZ6I5JCa0uR3gBRuNONuGPH3Ko9zUEATffv53j9DbYVEM0lfVNewefPoVJmWz+oT0wP/kNx6tREf+aUAF4m+eBsqnggITftW2fyeFnoBPCcPp3HUgSwZhesunqz+YeW6Pk+WWb5vl+2QbMKKtz5qK6dI3q0z9yp4FAgMBAAGjdTBzMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMBMB0GA1UdDgQWBBSr4OYIWkb8UGuQnEFnjSbmvR+4vDAfBgNVHSMEGDAWgBSr4OYIWkb8UGuQnEFnjSbmvR+4vDANBgkqhkiG9w0BAQsFAAOCAQEAUmRWRPGXsvfuRT+53id3EufH1IJAdowrt6yBZsHobvqCXO2+YhG7oG6/UqUYiv5bHN5xEMQyWd7nyrLOUeFo2bpcMIOlpl6AoUIY65Gm2BqQ7FuPxLLO25RdpZ5WkMGX5kJsKY0/PcpamRKNz1khgFcRyxf9WGhCAIjDCWIWs8lkvPN3m75SFCW7MTuzzQOrzvI6nqqcHO4k8hRBznp26WLUW1rQKpNN09nZGOkeNYK5QbzKN/RUmtEHQZhlgLAIr09jUaA4RDLI1SdD6LR5nvpa9RJBTyS/kISF8BXKMgvUbDHN2nP+VUUrut2ZwoU+pxV4RVT2pS760HuYj4+sYQ==' +set pki certificate dummy private key 'MIIEuwIBADANBgkqhkiG9w0BAQEFAASCBKUwggShAgEAAoIBAQDEfMAwYLKKVhGlUXr9gkVC7uBi+0O9yyEgd5QzPByePXYw0FrSLWmLRfQuByFDPIVANcEa3FgIXIAeKmxItw7IhFRsG5soSOXXgBxdAH/qzEbWhwzgafnxZKJkmrQr8YA3IFtkFPr2+5s26WdjtwEM0tzIFkq6hmWSX1axUgvYlF2uCxjututMZ6I5JCa0uR3gBRuNONuGPH3Ko9zUEATffv53j9DbYVEM0lfVNewefPoVJmWz+oT0wP/kNx6tREf+aUAF4m+eBsqnggITftW2fyeFnoBPCcPp3HUgSwZhesunqz+YeW6Pk+WWb5vl+2QbMKKtz5qK6dI3q0z9yp4FAgMBAAECgf9plqCMg2pKEWRFl183bqWAm7lnLnsUOfABFNPYa3U+uKQUKZpboTBfzDfZqNak3XNQV0mTAR8pFfoMhQjQU9hUxH7ivjw1RUCHjixCF0vLBkTB34gL7FUbiEIFhR1NW3pCJY73OXOkIZG1Obh6Syb8KubDeu4bTmb90/TnDDAs6OYXJ5yo7ZDZLvLu5a3Dli+H4K5Qb5VJ74o/vtodBo3wmKBgy2Ey6JqF+y7/3HeE66rVhYNft5pURgemWnNYqh3oDTJASqpA/8n90o8ceYPVJugQ7029UiyTp0xgBRXFszgiYPkBlsNWB+9+ospopOmYU0owBykH+RtD/bQ0mwECgYEA4gxPdYbHg/GLihHrkv0t5V0pSEhBeBeTBdWG+P/6K90vXofpp7qISdOeYMGkh8mY+PfZNHksdu67d2ks5on5/dNf5YXWCm+LMMRiSsfOo11NISNdNHS6afqs18Wq1aKawv/rwotfxrakM4Gar692+jgz/l/X+FdOQwmE6uEus8ECgYEA3oW4eGtzGq28TiqyhTHduTkas0ckPWX8ulasyPnLxBKDNNohbXXpFIJIcrnl24QFJw3MJbo+R+OxZHgzPK8r64gIGVa7vLCR2fiU/RFoUa1Jo1pPOqXXWqf/Mvdokm2p0atrjRUX9VhjoFsDLcqTgAmfSCsVSqGucX6ER7Gy60UCgYAvmhoNjNFtFquk6rsqHAjTOTgdUaH/0S8T1nBy9SzQmeaEyKhKuvxCV78NbxnfwnNlUoQ6CZ50eTefINXkwn+TlTSnl/SIBA9SuLheOQ9p1ZcNeG4DQuWStcg6NBUSoghnMg+Ky2Di7slLU2qovpGWhcllMve/A1umwFVuRPdZwQKBgHS7mYYyd/Oq6HnpFDWjbzlXp5Yc3/oFooruJT5ZLHfzbjkvpRGTJW7I2dC1jMuXekx+hHXWOg3keI7IL7jJ/DRW7Ei+o0XdKuY57Y7ErwEJ8vNq0N1nWo4IS2wlNgp61PdVAdrFEgh3EexxUj2XY8FrSs/FKio4nxaS1Dn4EnAxAoGBAKqLvuPpmCMVwlIu57WGxL5d9i7EjIGY65l6HTKQYoHCzE51rkowH1La2fuUYz0IpExq2lcrLbOUtSyhXH7Zlktiz//Gu/P90SUfR/ZGcLeZi+EDyK2OctpnWBjs2Dmfg4D6vxk39yV8AB97pYG073GcJ/P54qRUuEitbpJwH+fB' +set service ntp allow-client address '0.0.0.0/0' +set service ntp allow-client address '::/0' +set service ntp server 172.16.100.10 +set service ntp server 172.16.100.20 +set service ntp server 172.16.110.30 +set service ssh disable-host-validation +set service ssh port '22' +set system config-management commit-revisions '200' +set system conntrack modules ftp +set system conntrack modules h323 +set system conntrack modules nfs +set system conntrack modules pptp +set system conntrack modules sip +set system conntrack modules sqlnet +set system conntrack modules tftp +set system console device ttyS0 speed '115200' +set system host-name 'vyos' +set system login user vyos authentication encrypted-password '$6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0' +set system login user vyos authentication plaintext-password '' +set system name-server '172.16.254.30' +set system option kernel disable-mitigations +set system syslog local facility all level 'info' +set system syslog local facility local7 level 'debug' +set system time-zone 'Europe/Berlin' diff --git a/smoketest/config-tests/basic-vyos b/smoketest/config-tests/basic-vyos index 4793e069e..aaf450e80 100644 --- a/smoketest/config-tests/basic-vyos +++ b/smoketest/config-tests/basic-vyos @@ -28,7 +28,21 @@ set protocols static arp interface eth2.200.201 address 100.64.201.20 mac '00:50  set protocols static arp interface eth2.200.202 address 100.64.202.30 mac '00:50:00:00:00:30'  set protocols static arp interface eth2.200.202 address 100.64.202.40 mac '00:50:00:00:00:40'  set protocols static route 0.0.0.0/0 next-hop 100.64.0.1 +set service dhcp-server dynamic-dns-update send-updates 'enable' +set service dhcp-server dynamic-dns-update conflict-resolution 'enable' +set service dhcp-server dynamic-dns-update tsig-key domain-lan-updates algorithm 'sha256' +set service dhcp-server dynamic-dns-update tsig-key domain-lan-updates secret 'SXQncyBXZWRuZXNkYXkgbWFoIGR1ZGVzIQ==' +set service dhcp-server dynamic-dns-update tsig-key reverse-0-168-192 algorithm 'sha256' +set service dhcp-server dynamic-dns-update tsig-key reverse-0-168-192 secret 'VGhhbmsgR29kIGl0J3MgRnJpZGF5IQ==' +set service dhcp-server dynamic-dns-update forward-domain domain.lan dns-server 1 address '192.168.0.1' +set service dhcp-server dynamic-dns-update forward-domain domain.lan dns-server 2 address '100.100.0.1' +set service dhcp-server dynamic-dns-update forward-domain domain.lan key-name 'domain-lan-updates' +set service dhcp-server dynamic-dns-update reverse-domain 0.168.192.in-addr.arpa dns-server 1 address '192.168.0.1' +set service dhcp-server dynamic-dns-update reverse-domain 0.168.192.in-addr.arpa dns-server 2 address '100.100.0.1' +set service dhcp-server dynamic-dns-update reverse-domain 0.168.192.in-addr.arpa key-name 'reverse-0-168-192'  set service dhcp-server shared-network-name LAN authoritative +set service dhcp-server shared-network-name LAN dynamic-dns-update send-updates 'enable' +set service dhcp-server shared-network-name LAN dynamic-dns-update ttl-percent '75'  set service dhcp-server shared-network-name LAN subnet 192.168.0.0/24 option default-router '192.168.0.1'  set service dhcp-server shared-network-name LAN subnet 192.168.0.0/24 option domain-name 'vyos.net'  set service dhcp-server shared-network-name LAN subnet 192.168.0.0/24 option domain-search 'vyos.net' @@ -46,6 +60,9 @@ set service dhcp-server shared-network-name LAN subnet 192.168.0.0/24 static-map  set service dhcp-server shared-network-name LAN subnet 192.168.0.0/24 static-mapping TEST2-2 ip-address '192.168.0.21'  set service dhcp-server shared-network-name LAN subnet 192.168.0.0/24 static-mapping TEST2-2 mac '00:01:02:03:04:22'  set service dhcp-server shared-network-name LAN subnet 192.168.0.0/24 subnet-id '1' +set service dhcp-server shared-network-name LAN subnet 192.168.0.0/24 dynamic-dns-update send-updates 'enable' +set service dhcp-server shared-network-name LAN subnet 192.168.0.0/24 dynamic-dns-update generated-prefix 'myhost' +set service dhcp-server shared-network-name LAN subnet 192.168.0.0/24 dynamic-dns-update qualifying-suffix 'lan1.domain.lan'  set service dhcpv6-server shared-network-name LAN6 subnet fe88::/56 interface 'eth0'  set service dhcpv6-server shared-network-name LAN6 subnet fe88::/56 option domain-search 'vyos.net'  set service dhcpv6-server shared-network-name LAN6 subnet fe88::/56 option name-server 'fe88::1' diff --git a/smoketest/config-tests/conntrack-basic b/smoketest/config-tests/conntrack-basic new file mode 100644 index 000000000..8c375d244 --- /dev/null +++ b/smoketest/config-tests/conntrack-basic @@ -0,0 +1,35 @@ +set firewall global-options timeout icmp '30' +set firewall global-options timeout other '600' +set firewall global-options timeout udp other '300' +set firewall global-options timeout udp stream '300' +set interfaces ethernet eth0 vif 5 address '192.0.2.1/24' +set interfaces ethernet eth1 vif 7 description 'FTTH-PPPoE' +set nat source rule 100 log +set nat source rule 100 outbound-interface name 'pppoe0' +set nat source rule 100 source address '192.0.2.0/24' +set nat source rule 100 translation address 'masquerade' +set service ntp allow-client address '172.16.0.0/12' +set service ntp server 0.pool.ntp.org +set service ntp server 1.pool.ntp.org +set service ntp server 2.pool.ntp.org +set system config-management commit-revisions '200' +set system conntrack expect-table-size '2048' +set system conntrack hash-size '1024' +set system conntrack modules ftp +set system conntrack modules h323 +set system conntrack modules nfs +set system conntrack modules pptp +set system conntrack modules sip +set system conntrack modules sqlnet +set system conntrack modules tftp +set system conntrack table-size '262144' +set system conntrack timeout +set system console device ttyS0 speed '115200' +set system domain-name 'vyos.net' +set system host-name 'vyos' +set system login user vyos authentication encrypted-password '$6$2Ta6TWHd/U$NmrX0x9kexCimeOcYK1MfhMpITF9ELxHcaBU/znBq.X2ukQOj61fVI2UYP/xBzP4QtiTcdkgs7WOQMHWsRymO/' +set system login user vyos authentication plaintext-password '' +set system name-server '172.16.254.30' +set system syslog local facility all level 'debug' +set system syslog local facility local7 level 'debug' +set system syslog remote 172.16.100.1 facility all level 'warning' diff --git a/smoketest/config-tests/firewall-bridged-global-options b/smoketest/config-tests/firewall-bridged-global-options new file mode 100644 index 000000000..1d960d6c1 --- /dev/null +++ b/smoketest/config-tests/firewall-bridged-global-options @@ -0,0 +1,21 @@ +set firewall bridge prerouting filter rule 10 action 'accept' +set firewall bridge prerouting filter rule 10 ethernet-type 'arp' +set firewall global-options apply-to-bridged-traffic accept-invalid ethernet-type 'dhcp' +set firewall global-options apply-to-bridged-traffic accept-invalid ethernet-type 'arp' +set firewall global-options apply-to-bridged-traffic accept-invalid ethernet-type 'pppoe-discovery' +set firewall global-options apply-to-bridged-traffic accept-invalid ethernet-type 'pppoe' +set firewall global-options apply-to-bridged-traffic accept-invalid ethernet-type '802.1q' +set firewall global-options apply-to-bridged-traffic accept-invalid ethernet-type '802.1ad' +set firewall global-options apply-to-bridged-traffic accept-invalid ethernet-type 'wol' +set firewall global-options state-policy established action 'accept' +set firewall global-options state-policy invalid action 'drop' +set firewall global-options state-policy related action 'accept' +set interfaces ethernet eth0 duplex 'auto' +set interfaces ethernet eth0 speed 'auto' +set interfaces ethernet eth1 duplex 'auto' +set interfaces ethernet eth1 speed 'auto' +set system console device ttyS0 speed '115200' +set system domain-name 'vyos-ci-test.net' +set system host-name 'vyos' +set system login user vyos authentication encrypted-password '$6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0' +set system login user vyos authentication plaintext-password '' diff --git a/smoketest/configs/basic-haproxy b/smoketest/configs/basic-haproxy new file mode 100644 index 000000000..83fffbac6 --- /dev/null +++ b/smoketest/configs/basic-haproxy @@ -0,0 +1,153 @@ +interfaces { +    dummy dum0 { +        address "172.18.254.203/32" +    } +    ethernet eth0 { +        duplex "auto" +        speed "auto" +        vif 203 { +            address "172.18.203.10/24" +        } +    } +    ethernet eth1 { +        duplex "auto" +        speed "auto" +    } +    ethernet eth2 { +        duplex "auto" +        speed "auto" +    } +} +load-balancing { +    reverse-proxy { +        backend webserver { +            logging { +                facility all { +                    level "all" +                } +                facility daemon { +                    level "all" +                } +                facility user { +                    level "info" +                } +            } +            server web01 { +                address "192.0.2.1" +                port "443" +            } +            ssl { +                no-verify +            } +        } +        global-parameters { +            logging { +                facility all { +                    level "all" +                } +                facility daemon { +                    level "all" +                } +                facility user { +                    level "info" +                } +            } +        } +        service frontend { +            backend "webserver" +            logging { +                facility all { +                    level "all" +                } +                facility daemon { +                    level "all" +                } +                facility user { +                    level "info" +                } +            } +            port "443" +            ssl { +                certificate "dummy" +            } +        } +    } +} +pki { +    certificate dummy { +        certificate "MIIDsTCCApmgAwIBAgIUegVgO1wIN2v44trXZ+Kb1t48uL0wDQYJKoZIhvcNAQELBQAwVzELMAkGA1UEBhMCR0IxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQBgNVBAcMCVNvbWUtQ2l0eTENMAsGA1UECgwEVnlPUzEQMA4GA1UEAwwHdnlvcy5pbzAeFw0yNTA1MDUxODIzMTdaFw0yNjA1MDUxODIzMTdaMFcxCzAJBgNVBAYTAkdCMRMwEQYDVQQIDApTb21lLVN0YXRlMRIwEAYDVQQHDAlTb21lLUNpdHkxDTALBgNVBAoMBFZ5T1MxEDAOBgNVBAMMB3Z5b3MuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDEfMAwYLKKVhGlUXr9gkVC7uBi+0O9yyEgd5QzPByePXYw0FrSLWmLRfQuByFDPIVANcEa3FgIXIAeKmxItw7IhFRsG5soSOXXgBxdAH/qzEbWhwzgafnxZKJkmrQr8YA3IFtkFPr2+5s26WdjtwEM0tzIFkq6hmWSX1axUgvYlF2uCxjututMZ6I5JCa0uR3gBRuNONuGPH3Ko9zUEATffv53j9DbYVEM0lfVNewefPoVJmWz+oT0wP/kNx6tREf+aUAF4m+eBsqnggITftW2fyeFnoBPCcPp3HUgSwZhesunqz+YeW6Pk+WWb5vl+2QbMKKtz5qK6dI3q0z9yp4FAgMBAAGjdTBzMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMBMB0GA1UdDgQWBBSr4OYIWkb8UGuQnEFnjSbmvR+4vDAfBgNVHSMEGDAWgBSr4OYIWkb8UGuQnEFnjSbmvR+4vDANBgkqhkiG9w0BAQsFAAOCAQEAUmRWRPGXsvfuRT+53id3EufH1IJAdowrt6yBZsHobvqCXO2+YhG7oG6/UqUYiv5bHN5xEMQyWd7nyrLOUeFo2bpcMIOlpl6AoUIY65Gm2BqQ7FuPxLLO25RdpZ5WkMGX5kJsKY0/PcpamRKNz1khgFcRyxf9WGhCAIjDCWIWs8lkvPN3m75SFCW7MTuzzQOrzvI6nqqcHO4k8hRBznp26WLUW1rQKpNN09nZGOkeNYK5QbzKN/RUmtEHQZhlgLAIr09jUaA4RDLI1SdD6LR5nvpa9RJBTyS/kISF8BXKMgvUbDHN2nP+VUUrut2ZwoU+pxV4RVT2pS760HuYj4+sYQ==" +        private { +            key "MIIEuwIBADANBgkqhkiG9w0BAQEFAASCBKUwggShAgEAAoIBAQDEfMAwYLKKVhGlUXr9gkVC7uBi+0O9yyEgd5QzPByePXYw0FrSLWmLRfQuByFDPIVANcEa3FgIXIAeKmxItw7IhFRsG5soSOXXgBxdAH/qzEbWhwzgafnxZKJkmrQr8YA3IFtkFPr2+5s26WdjtwEM0tzIFkq6hmWSX1axUgvYlF2uCxjututMZ6I5JCa0uR3gBRuNONuGPH3Ko9zUEATffv53j9DbYVEM0lfVNewefPoVJmWz+oT0wP/kNx6tREf+aUAF4m+eBsqnggITftW2fyeFnoBPCcPp3HUgSwZhesunqz+YeW6Pk+WWb5vl+2QbMKKtz5qK6dI3q0z9yp4FAgMBAAECgf9plqCMg2pKEWRFl183bqWAm7lnLnsUOfABFNPYa3U+uKQUKZpboTBfzDfZqNak3XNQV0mTAR8pFfoMhQjQU9hUxH7ivjw1RUCHjixCF0vLBkTB34gL7FUbiEIFhR1NW3pCJY73OXOkIZG1Obh6Syb8KubDeu4bTmb90/TnDDAs6OYXJ5yo7ZDZLvLu5a3Dli+H4K5Qb5VJ74o/vtodBo3wmKBgy2Ey6JqF+y7/3HeE66rVhYNft5pURgemWnNYqh3oDTJASqpA/8n90o8ceYPVJugQ7029UiyTp0xgBRXFszgiYPkBlsNWB+9+ospopOmYU0owBykH+RtD/bQ0mwECgYEA4gxPdYbHg/GLihHrkv0t5V0pSEhBeBeTBdWG+P/6K90vXofpp7qISdOeYMGkh8mY+PfZNHksdu67d2ks5on5/dNf5YXWCm+LMMRiSsfOo11NISNdNHS6afqs18Wq1aKawv/rwotfxrakM4Gar692+jgz/l/X+FdOQwmE6uEus8ECgYEA3oW4eGtzGq28TiqyhTHduTkas0ckPWX8ulasyPnLxBKDNNohbXXpFIJIcrnl24QFJw3MJbo+R+OxZHgzPK8r64gIGVa7vLCR2fiU/RFoUa1Jo1pPOqXXWqf/Mvdokm2p0atrjRUX9VhjoFsDLcqTgAmfSCsVSqGucX6ER7Gy60UCgYAvmhoNjNFtFquk6rsqHAjTOTgdUaH/0S8T1nBy9SzQmeaEyKhKuvxCV78NbxnfwnNlUoQ6CZ50eTefINXkwn+TlTSnl/SIBA9SuLheOQ9p1ZcNeG4DQuWStcg6NBUSoghnMg+Ky2Di7slLU2qovpGWhcllMve/A1umwFVuRPdZwQKBgHS7mYYyd/Oq6HnpFDWjbzlXp5Yc3/oFooruJT5ZLHfzbjkvpRGTJW7I2dC1jMuXekx+hHXWOg3keI7IL7jJ/DRW7Ei+o0XdKuY57Y7ErwEJ8vNq0N1nWo4IS2wlNgp61PdVAdrFEgh3EexxUj2XY8FrSs/FKio4nxaS1Dn4EnAxAoGBAKqLvuPpmCMVwlIu57WGxL5d9i7EjIGY65l6HTKQYoHCzE51rkowH1La2fuUYz0IpExq2lcrLbOUtSyhXH7Zlktiz//Gu/P90SUfR/ZGcLeZi+EDyK2OctpnWBjs2Dmfg4D6vxk39yV8AB97pYG073GcJ/P54qRUuEitbpJwH+fB" +        } +    } +} +service { +    ntp { +        allow-client { +            address "0.0.0.0/0" +            address "::/0" +        } +        server 172.16.100.10 { +        } +        server 172.16.100.20 { +        } +        server 172.16.110.30 { +        } +    } +    ssh { +        disable-host-validation +        port "22" +    } +} +system { +    config-management { +        commit-revisions "200" +    } +    console { +        device ttyS0 { +            speed 115200 +        } +    } +    conntrack { +        modules { +            ftp +            h323 +            nfs +            pptp +            sip +            sqlnet +            tftp +        } +    } +    host-name vyos +    login { +        user vyos { +            authentication { +                encrypted-password $6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0 +                plaintext-password "" +            } +        } +    } +    name-server "172.16.254.30" +    option { +        kernel { +            disable-mitigations +        } +    } +    syslog { +        global { +            facility all { +                level "info" +            } +            facility local7 { +                level "debug" +            } +        } +    } +    time-zone "Europe/Berlin" +} + + +// Warning: Do not remove the following line. +// vyos-config-version: "bgp@5:broadcast-relay@1:cluster@2:config-management@1:conntrack@5:conntrack-sync@2:container@2:dhcp-relay@2:dhcp-server@8:dhcpv6-server@1:dns-dynamic@4:dns-forwarding@4:firewall@15:flow-accounting@1:https@6:ids@1:interfaces@32:ipoe-server@3:ipsec@13:isis@3:l2tp@9:lldp@2:mdns@1:monitoring@1:nat@8:nat66@3:ntp@3:openconnect@3:ospf@2:pim@1:policy@8:pppoe-server@10:pptp@5:qos@2:quagga@11:reverse-proxy@1:rip@1:rpki@2:salt@1:snmp@3:ssh@2:sstp@6:system@27:vrf@3:vrrp@4:vyos-accel-ppp@2:wanloadbalance@3:webproxy@2" +// Release version: 1.4.1 diff --git a/smoketest/configs/basic-vyos b/smoketest/configs/basic-vyos index a6cd3b6e1..5f7a71237 100644 --- a/smoketest/configs/basic-vyos +++ b/smoketest/configs/basic-vyos @@ -99,33 +99,77 @@ protocols {  }  service {      dhcp-server { +        dynamic-dns-update { +            send-updates enable +            forward-domain domain.lan { +                dns-server 1 { +                    address 192.168.0.1 +                } +                dns-server 2 { +                    address 100.100.0.1 +                } +                key-name domain-lan-updates +            } +            reverse-domain 0.168.192.in-addr.arpa { +                dns-server 1 { +                    address 192.168.0.1 +                } +                dns-server 2 { +                    address 100.100.0.1 +                } +                key-name reverse-0-168-192 +            } +            tsig-key domain-lan-updates { +                algorithm sha256 +                secret SXQncyBXZWRuZXNkYXkgbWFoIGR1ZGVzIQ== +            } +            tsig-key reverse-0-168-192 { +                algorithm sha256 +                secret VGhhbmsgR29kIGl0J3MgRnJpZGF5IQ== +            } +            conflict-resolution enable +        }          shared-network-name LAN {              authoritative +            dynamic-dns-update { +                send-updates enable +                ttl-percent 75 +            }              subnet 192.168.0.0/24 { -                default-router 192.168.0.1 -                dns-server 192.168.0.1 -                domain-name vyos.net -                domain-search vyos.net +                dynamic-dns-update { +                    send-updates enable +                    generated-prefix myhost +                    qualifying-suffix lan1.domain.lan +                } +                option { +                    default-router 192.168.0.1 +                    domain-name vyos.net +                    domain-search vyos.net +                    name-server 192.168.0.1 +                }                  range LANDynamic {                      start 192.168.0.30                      stop 192.168.0.240                  }                  static-mapping TEST1-1 {                      ip-address 192.168.0.11 -                    mac-address 00:01:02:03:04:05 +                    mac 00:01:02:03:04:05                  }                  static-mapping TEST1-2 { +                    disable                      ip-address 192.168.0.12 -                    mac-address 00:01:02:03:04:05 +                    mac 00:01:02:03:04:05                  }                  static-mapping TEST2-1 {                      ip-address 192.168.0.21 -                    mac-address 00:01:02:03:04:21 +                    mac 00:01:02:03:04:21                  }                  static-mapping TEST2-2 { +                    disable                      ip-address 192.168.0.21 -                    mac-address 00:01:02:03:04:22 +                    mac 00:01:02:03:04:22                  } +                subnet-id 1              }          }      } diff --git a/smoketest/configs/conntrack-basic b/smoketest/configs/conntrack-basic new file mode 100644 index 000000000..8ecb78aeb --- /dev/null +++ b/smoketest/configs/conntrack-basic @@ -0,0 +1,92 @@ +interfaces { +    ethernet eth0 { +        duplex auto +        speed auto +        vif 5 { +            address 192.0.2.1/24 +        } +    } +    ethernet eth1 { +        vif 7 { +            description FTTH-PPPoE +        } +    } +} +nat { +    source { +        rule 100 { +            log +            outbound-interface pppoe0 +            source { +                address 192.0.2.0/24 +            } +            translation { +                address masquerade +            } +        } +    } +} +system { +    config-management { +        commit-revisions 200 +    } +    conntrack { +        expect-table-size 2048 +        hash-size 1023 +        table-size 262144 +        timeout { +            icmp 30 +            other 600 +            udp { +                other 300 +                stream 300 +            } +        } +    } +    console { +        device ttyS0 { +            speed 115200 +        } +    } +    domain-name vyos.net +    host-name vyos +    login { +        user vyos { +            authentication { +                encrypted-password $6$2Ta6TWHd/U$NmrX0x9kexCimeOcYK1MfhMpITF9ELxHcaBU/znBq.X2ukQOj61fVI2UYP/xBzP4QtiTcdkgs7WOQMHWsRymO/ +                plaintext-password "" +            } +        } +    } +    name-server 172.16.254.30 +    ntp { +        allow-clients { +            address 172.16.0.0/12 +        } +        server 0.pool.ntp.org { +        } +        server 1.pool.ntp.org { +        } +        server 2.pool.ntp.org { +        } +    } +    syslog { +        global { +            facility all { +                level debug +            } +            facility protocols { +                level debug +            } +        } +        host 172.16.100.1 { +            facility all { +                level warning +            } +        } +    } +} + +// Warning: Do not remove the following line. +// vyos-config-version: "broadcast-relay@1:cluster@1:config-management@1:conntrack@1:conntrack-sync@1:dhcp-relay@2:dhcp-server@5:dhcpv6-server@1:dns-forwarding@3:firewall@5:https@2:interfaces@18:ipoe-server@1:ipsec@5:l2tp@3:lldp@1:mdns@1:nat@5:ntp@1:pppoe-server@5:pptp@2:qos@1:quagga@6:salt@1:snmp@2:ssh@2:sstp@3:system@20:vrrp@2:vyos-accel-ppp@2:wanloadbalance@3:webproxy@2:zone-policy@1" +// Release version: 1.3-beta-202101091250 diff --git a/smoketest/configs/firewall-bridged-global-options b/smoketest/configs/firewall-bridged-global-options new file mode 100644 index 000000000..a7e1428d8 --- /dev/null +++ b/smoketest/configs/firewall-bridged-global-options @@ -0,0 +1,60 @@ +firewall { +    bridge { +        prerouting { +            filter { +                rule 10 { +                    action "accept" +                    ethernet-type "arp" +                } +            } +        } +    } +    global-options { +        apply-to-bridged-traffic { +            invalid-connections { +            } +        } +        state-policy { +            established { +                action "accept" +            } +            invalid { +                action "drop" +            } +            related { +                action "accept" +            } +        } +    } +} +interfaces { +    ethernet eth0 { +        duplex "auto" +        speed "auto" +    } +    ethernet eth1 { +        duplex auto +        speed auto +    } +} +system { +    console { +        device ttyS0 { +            speed 115200 +        } +    } +    domain-name vyos-ci-test.net +    host-name vyos +    login { +        user vyos { +            authentication { +                encrypted-password $6$O5gJRlDYQpj$MtrCV9lxMnZPMbcxlU7.FI793MImNHznxGoMFgm3Q6QP3vfKJyOSRCt3Ka/GzFQyW1yZS4NS616NLHaIPPFHc0 +                plaintext-password "" +            } +        } +    } +} + +// Warning: Do not remove the following line. +// vyos-config-version: "bgp@6:broadcast-relay@1:cluster@2:config-management@1:conntrack@6:conntrack-sync@2:container@2:dhcp-relay@2:dhcp-server@11:dhcpv6-server@6:dns-dynamic@4:dns-forwarding@4:firewall@18:flow-accounting@2:https@7:ids@2:interfaces@33:ipoe-server@4:ipsec@13:isis@3:l2tp@9:lldp@3:mdns@1:monitoring@2:nat@8:nat66@3:nhrp@1:ntp@3:openconnect@3:openvpn@4:ospf@2:pim@1:policy@9:pppoe-server@11:pptp@5:qos@3:quagga@12:reverse-proxy@3:rip@1:rpki@2:salt@1:snmp@3:ssh@2:sstp@6:system@29:vpp@1:vrf@3:vrrp@4:vyos-accel-ppp@2:wanloadbalance@4:webproxy@2" +// Release version: 2025.06.17-0020-rolling diff --git a/smoketest/scripts/cli/base_accel_ppp_test.py b/smoketest/scripts/cli/base_accel_ppp_test.py index 750702e98..ddaed80ad 100644 --- a/smoketest/scripts/cli/base_accel_ppp_test.py +++ b/smoketest/scripts/cli/base_accel_ppp_test.py @@ -1,4 +1,4 @@ -# Copyright (C) 2020-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/base_interfaces_test.py b/smoketest/scripts/cli/base_interfaces_test.py index 3e2653a2f..54547e62d 100644 --- a/smoketest/scripts/cli/base_interfaces_test.py +++ b/smoketest/scripts/cli/base_interfaces_test.py @@ -1,4 +1,4 @@ -# Copyright (C) 2019-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -14,6 +14,7 @@  import re +from json import loads  from netifaces import AF_INET  from netifaces import AF_INET6  from netifaces import ifaddresses @@ -1067,6 +1068,7 @@ class BasicInterfaceTest:              dad_transmits = '10'              accept_dad = '0'              source_validation = 'strict' +            interface_identifier = '::fffe'              for interface in self._interfaces:                  path = self._base_path + [interface] @@ -1089,6 +1091,9 @@ class BasicInterfaceTest:                  if cli_defined(self._base_path + ['ipv6'], 'source-validation'):                      self.cli_set(path + ['ipv6', 'source-validation', source_validation]) +                if cli_defined(self._base_path + ['ipv6', 'address'], 'interface-identifier'): +                    self.cli_set(path + ['ipv6', 'address', 'interface-identifier', interface_identifier]) +              self.cli_commit()              for interface in self._interfaces: @@ -1120,6 +1125,13 @@ class BasicInterfaceTest:                              self.assertIn('fib saddr . iif oif 0', line)                              self.assertIn('drop', line) +                if cli_defined(self._base_path + ['ipv6', 'address'], 'interface-identifier'): +                    tmp = cmd(f'ip -j token show dev {interface}') +                    tmp = loads(tmp)[0] +                    self.assertEqual(tmp['token'], interface_identifier) +                    self.assertEqual(tmp['ifname'], interface) + +          def test_dhcpv6_client_options(self):              if not self._test_ipv6_dhcpc6:                  self.skipTest(MSG_TESTCASE_UNSUPPORTED) diff --git a/smoketest/scripts/cli/base_vyostest_shim.py b/smoketest/scripts/cli/base_vyostest_shim.py index f0674f187..526b24c46 100644 --- a/smoketest/scripts/cli/base_vyostest_shim.py +++ b/smoketest/scripts/cli/base_vyostest_shim.py @@ -1,4 +1,4 @@ -# Copyright (C) 2021-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -152,12 +152,14 @@ class VyOSUnitTestSHIM:              return out          @staticmethod -        def ssh_send_cmd(command, username, password, hostname='localhost'): +        def ssh_send_cmd(command, username, password, key_filename=None, +                         hostname='localhost'):              """ SSH command execution helper """              # Try to login via SSH              ssh_client = paramiko.SSHClient()              ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) -            ssh_client.connect(hostname=hostname, username=username, password=password) +            ssh_client.connect(hostname=hostname, username=username, +                               password=password, key_filename=key_filename)              _, stdout, stderr = ssh_client.exec_command(command)              output = stdout.read().decode().strip()              error = stderr.read().decode().strip() diff --git a/smoketest/scripts/cli/test_backslash_escape.py b/smoketest/scripts/cli/test_backslash_escape.py index e94e9ab0a..0fe71cdef 100755 --- a/smoketest/scripts/cli/test_backslash_escape.py +++ b/smoketest/scripts/cli/test_backslash_escape.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_cgnat.py b/smoketest/scripts/cli/test_cgnat.py index 02dad3de5..2cec401ae 100755 --- a/smoketest/scripts/cli/test_cgnat.py +++ b/smoketest/scripts/cli/test_cgnat.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_config_dependency.py b/smoketest/scripts/cli/test_config_dependency.py index 99e807ac5..5cc62fbd1 100755 --- a/smoketest/scripts/cli/test_config_dependency.py +++ b/smoketest/scripts/cli/test_config_dependency.py @@ -1,5 +1,5 @@  #!/usr/bin/env python3 -# Copyright 2024 VyOS maintainers and contributors <maintainers@vyos.io> +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This library is free software; you can redistribute it and/or  # modify it under the terms of the GNU Lesser General Public diff --git a/smoketest/scripts/cli/test_configd_init.py b/smoketest/scripts/cli/test_configd_init.py index 245c03824..aa6d18d39 100755 --- a/smoketest/scripts/cli/test_configd_init.py +++ b/smoketest/scripts/cli/test_configd_init.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2023 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_container.py b/smoketest/scripts/cli/test_container.py index 36622cad1..7590ed1cd 100755 --- a/smoketest/scripts/cli/test_container.py +++ b/smoketest/scripts/cli/test_container.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -33,11 +33,13 @@ PROCESS_PIDFILE = '/run/vyos-container-{0}.service.pid'  busybox_image = 'busybox:stable'  busybox_image_path = '/usr/share/vyos/busybox-stable.tar' +  def cmd_to_json(command):      c = cmd(command + ' --format=json')      data = json.loads(c)[0]      return data +  class TestContainer(VyOSUnitTestSHIM.TestCase):      @classmethod      def setUpClass(cls): @@ -73,14 +75,27 @@ class TestContainer(VyOSUnitTestSHIM.TestCase):          cont_name = 'c1'          self.cli_set(['interfaces', 'ethernet', 'eth0', 'address', '10.0.2.15/24']) -        self.cli_set(['protocols', 'static', 'route', '0.0.0.0/0', 'next-hop', '10.0.2.2']) +        self.cli_set( +            ['protocols', 'static', 'route', '0.0.0.0/0', 'next-hop', '10.0.2.2'] +        )          self.cli_set(['system', 'name-server', '1.1.1.1'])          self.cli_set(['system', 'name-server', '8.8.8.8'])          self.cli_set(base_path + ['name', cont_name, 'image', busybox_image])          self.cli_set(base_path + ['name', cont_name, 'allow-host-networks']) -        self.cli_set(base_path + ['name', cont_name, 'sysctl', 'parameter', 'kernel.msgmax', 'value', '4096']) - +        self.cli_set( +            base_path +            + [ +                'name', +                cont_name, +                'sysctl', +                'parameter', +                'kernel.msgmax', +                'value', +                '4096', +            ] +        ) +        self.cli_set(base_path + ['name', cont_name, 'log-driver', 'journald'])          # commit changes          self.cli_commit() @@ -95,6 +110,10 @@ class TestContainer(VyOSUnitTestSHIM.TestCase):          tmp = cmd(f'sudo podman exec -it {cont_name} sysctl kernel.msgmax')          self.assertEqual(tmp, 'kernel.msgmax = 4096') +        l = cmd_to_json(f'sudo podman container inspect {cont_name}') +        self.assertEqual(l['HostConfig']['LogConfig']['Type'], 'journald') + +      def test_name_server(self):          cont_name = 'dns-test'          net_name = 'net-test' @@ -105,7 +124,17 @@ class TestContainer(VyOSUnitTestSHIM.TestCase):          self.cli_set(base_path + ['name', cont_name, 'image', busybox_image])          self.cli_set(base_path + ['name', cont_name, 'name-server', name_server]) -        self.cli_set(base_path + ['name', cont_name, 'network', net_name, 'address', str(ip_interface(prefix).ip + 2)]) +        self.cli_set( +            base_path +            + [ +                'name', +                cont_name, +                'network', +                net_name, +                'address', +                str(ip_interface(prefix).ip + 2), +            ] +        )          # verify() - name server has no effect when container network has dns enabled          with self.assertRaises(ConfigSessionError): @@ -146,7 +175,17 @@ class TestContainer(VyOSUnitTestSHIM.TestCase):          for ii in range(1, 6):              name = f'{base_name}-{ii}'              self.cli_set(base_path + ['name', name, 'image', busybox_image]) -            self.cli_set(base_path + ['name', name, 'network', net_name, 'address', str(ip_interface(prefix).ip + ii)]) +            self.cli_set( +                base_path +                + [ +                    'name', +                    name, +                    'network', +                    net_name, +                    'address', +                    str(ip_interface(prefix).ip + ii), +                ] +            )          # verify() - first IP address of a prefix can not be used by a container          with self.assertRaises(ConfigSessionError): @@ -163,8 +202,14 @@ class TestContainer(VyOSUnitTestSHIM.TestCase):          for ii in range(2, 6):              name = f'{base_name}-{ii}'              c = cmd_to_json(f'sudo podman container inspect {name}') -            self.assertEqual(c['NetworkSettings']['Networks'][net_name]['Gateway']  , str(ip_interface(prefix).ip + 1)) -            self.assertEqual(c['NetworkSettings']['Networks'][net_name]['IPAddress'], str(ip_interface(prefix).ip + ii)) +            self.assertEqual( +                c['NetworkSettings']['Networks'][net_name]['Gateway'], +                str(ip_interface(prefix).ip + 1), +            ) +            self.assertEqual( +                c['NetworkSettings']['Networks'][net_name]['IPAddress'], +                str(ip_interface(prefix).ip + ii), +            )      def test_ipv6_network(self):          prefix = '2001:db8::/64' @@ -176,7 +221,17 @@ class TestContainer(VyOSUnitTestSHIM.TestCase):          for ii in range(1, 6):              name = f'{base_name}-{ii}'              self.cli_set(base_path + ['name', name, 'image', busybox_image]) -            self.cli_set(base_path + ['name', name, 'network', net_name, 'address', str(ip_interface(prefix).ip + ii)]) +            self.cli_set( +                base_path +                + [ +                    'name', +                    name, +                    'network', +                    net_name, +                    'address', +                    str(ip_interface(prefix).ip + ii), +                ] +            )          # verify() - first IP address of a prefix can not be used by a container          with self.assertRaises(ConfigSessionError): @@ -193,8 +248,14 @@ class TestContainer(VyOSUnitTestSHIM.TestCase):          for ii in range(2, 6):              name = f'{base_name}-{ii}'              c = cmd_to_json(f'sudo podman container inspect {name}') -            self.assertEqual(c['NetworkSettings']['Networks'][net_name]['IPv6Gateway']      , str(ip_interface(prefix).ip + 1)) -            self.assertEqual(c['NetworkSettings']['Networks'][net_name]['GlobalIPv6Address'], str(ip_interface(prefix).ip + ii)) +            self.assertEqual( +                c['NetworkSettings']['Networks'][net_name]['IPv6Gateway'], +                str(ip_interface(prefix).ip + 1), +            ) +            self.assertEqual( +                c['NetworkSettings']['Networks'][net_name]['GlobalIPv6Address'], +                str(ip_interface(prefix).ip + ii), +            )      def test_dual_stack_network(self):          prefix4 = '192.0.2.0/24' @@ -208,8 +269,28 @@ class TestContainer(VyOSUnitTestSHIM.TestCase):          for ii in range(1, 6):              name = f'{base_name}-{ii}'              self.cli_set(base_path + ['name', name, 'image', busybox_image]) -            self.cli_set(base_path + ['name', name, 'network', net_name, 'address', str(ip_interface(prefix4).ip + ii)]) -            self.cli_set(base_path + ['name', name, 'network', net_name, 'address', str(ip_interface(prefix6).ip + ii)]) +            self.cli_set( +                base_path +                + [ +                    'name', +                    name, +                    'network', +                    net_name, +                    'address', +                    str(ip_interface(prefix4).ip + ii), +                ] +            ) +            self.cli_set( +                base_path +                + [ +                    'name', +                    name, +                    'network', +                    net_name, +                    'address', +                    str(ip_interface(prefix6).ip + ii), +                ] +            )          # verify() - first IP address of a prefix can not be used by a container          with self.assertRaises(ConfigSessionError): @@ -227,10 +308,22 @@ class TestContainer(VyOSUnitTestSHIM.TestCase):          for ii in range(2, 6):              name = f'{base_name}-{ii}'              c = cmd_to_json(f'sudo podman container inspect {name}') -            self.assertEqual(c['NetworkSettings']['Networks'][net_name]['IPv6Gateway']      , str(ip_interface(prefix6).ip + 1)) -            self.assertEqual(c['NetworkSettings']['Networks'][net_name]['GlobalIPv6Address'], str(ip_interface(prefix6).ip + ii)) -            self.assertEqual(c['NetworkSettings']['Networks'][net_name]['Gateway']          , str(ip_interface(prefix4).ip + 1)) -            self.assertEqual(c['NetworkSettings']['Networks'][net_name]['IPAddress']        , str(ip_interface(prefix4).ip + ii)) +            self.assertEqual( +                c['NetworkSettings']['Networks'][net_name]['IPv6Gateway'], +                str(ip_interface(prefix6).ip + 1), +            ) +            self.assertEqual( +                c['NetworkSettings']['Networks'][net_name]['GlobalIPv6Address'], +                str(ip_interface(prefix6).ip + ii), +            ) +            self.assertEqual( +                c['NetworkSettings']['Networks'][net_name]['Gateway'], +                str(ip_interface(prefix4).ip + 1), +            ) +            self.assertEqual( +                c['NetworkSettings']['Networks'][net_name]['IPAddress'], +                str(ip_interface(prefix4).ip + ii), +            )      def test_no_name_server(self):          prefix = '192.0.2.0/24' @@ -242,7 +335,17 @@ class TestContainer(VyOSUnitTestSHIM.TestCase):          name = f'{base_name}-2'          self.cli_set(base_path + ['name', name, 'image', busybox_image]) -        self.cli_set(base_path + ['name', name, 'network', net_name, 'address', str(ip_interface(prefix).ip + 2)]) +        self.cli_set( +            base_path +            + [ +                'name', +                name, +                'network', +                net_name, +                'address', +                str(ip_interface(prefix).ip + 2), +            ] +        )          self.cli_commit()          n = cmd_to_json(f'sudo podman network inspect {net_name}') @@ -258,7 +361,17 @@ class TestContainer(VyOSUnitTestSHIM.TestCase):          name = f'{base_name}-2'          self.cli_set(base_path + ['name', name, 'image', busybox_image]) -        self.cli_set(base_path + ['name', name, 'network', net_name, 'address', str(ip_interface(prefix).ip + 2)]) +        self.cli_set( +            base_path +            + [ +                'name', +                name, +                'network', +                net_name, +                'address', +                str(ip_interface(prefix).ip + 2), +            ] +        )          self.cli_commit()          n = cmd_to_json(f'sudo podman network inspect {net_name}') @@ -298,11 +411,14 @@ class TestContainer(VyOSUnitTestSHIM.TestCase):          self.cli_commit()          # Query API about running containers -        tmp = cmd("sudo curl --unix-socket /run/podman/podman.sock -H 'content-type: application/json' -sf http://localhost/containers/json") +        tmp = cmd( +            "sudo curl --unix-socket /run/podman/podman.sock -H 'content-type: application/json' -sf http://localhost/containers/json" +        )          tmp = json.loads(tmp)          # We expect the same amount of containers from the API that we started above          self.assertEqual(len(container_list), len(tmp)) +  if __name__ == '__main__':      unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_firewall.py b/smoketest/scripts/cli/test_firewall.py index 69de0c326..24d30f89e 100755 --- a/smoketest/scripts/cli/test_firewall.py +++ b/smoketest/scripts/cli/test_firewall.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -728,7 +728,13 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):          self.cli_set(['firewall', 'group', 'ipv6-address-group', 'AGV6', 'address', '2001:db1::1'])          self.cli_set(['firewall', 'global-options', 'state-policy', 'established', 'action', 'accept'])          self.cli_set(['firewall', 'global-options', 'apply-to-bridged-traffic', 'ipv4']) -        self.cli_set(['firewall', 'global-options', 'apply-to-bridged-traffic', 'invalid-connections']) +        self.cli_set(['firewall', 'global-options', 'apply-to-bridged-traffic', 'accept-invalid', 'ethernet-type', 'dhcp']) +        self.cli_set(['firewall', 'global-options', 'apply-to-bridged-traffic', 'accept-invalid', 'ethernet-type', 'arp']) +        self.cli_set(['firewall', 'global-options', 'apply-to-bridged-traffic', 'accept-invalid', 'ethernet-type', 'pppoe']) +        self.cli_set(['firewall', 'global-options', 'apply-to-bridged-traffic', 'accept-invalid', 'ethernet-type', 'pppoe-discovery']) +        self.cli_set(['firewall', 'global-options', 'apply-to-bridged-traffic', 'accept-invalid', 'ethernet-type', '802.1q']) +        self.cli_set(['firewall', 'global-options', 'apply-to-bridged-traffic', 'accept-invalid', 'ethernet-type', '802.1ad']) +        self.cli_set(['firewall', 'global-options', 'apply-to-bridged-traffic', 'accept-invalid', 'ethernet-type', 'wol'])          self.cli_set(['firewall', 'bridge', 'name', name, 'default-action', 'accept'])          self.cli_set(['firewall', 'bridge', 'name', name, 'default-log']) @@ -783,7 +789,11 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):              ['type filter hook output priority filter; policy accept;'],              ['ct state invalid', 'udp sport 67', 'udp dport 68', 'accept'],              ['ct state invalid', 'ether type arp', 'accept'], +            ['ct state invalid', 'ether type 8021q', 'accept'], +            ['ct state invalid', 'ether type 8021ad', 'accept'], +            ['ct state invalid', 'ether type 0x8863', 'accept'],              ['ct state invalid', 'ether type 0x8864', 'accept'], +            ['ct state invalid', 'ether type 0x0842', 'accept'],              ['chain VYOS_PREROUTING_filter'],              ['type filter hook prerouting priority filter; policy accept;'],              ['ip6 daddr @A6_AGV6', 'notrack'], @@ -1113,6 +1123,12 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):          self.verify_nftables_chain([['accept']], 'ip vyos_conntrack', 'FW_CONNTRACK')          self.verify_nftables_chain([['accept']], 'ip6 vyos_conntrack', 'FW_CONNTRACK') +        # Test interface deletion +        self.cli_delete(['interfaces', 'ethernet', 'eth0', 'vif', '10']) + +        with self.assertRaises(ConfigSessionError): +            self.cli_commit() +      def test_zone_flow_offload(self):          self.cli_set(['firewall', 'flowtable', 'smoketest', 'interface', 'eth0'])          self.cli_set(['firewall', 'flowtable', 'smoketest', 'offload', 'hardware']) @@ -1295,7 +1311,7 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):              ['R_group01'],              ['type ipv4_addr'],              ['flags interval'], -            ['meta l4proto', 'daddr @R_group01', "ipv4-INP-filter-10"] +            ['meta l4proto', 'daddr @R_group01', 'ipv4-INP-filter-10']          ]          self.verify_nftables(nftables_search, 'ip vyos_filter') @@ -1314,5 +1330,79 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):          self.cli_discard() +    def test_ipv6_remote_group(self): +        # Setup base config for test +        self.cli_set(['firewall', 'group', 'remote-group', 'group01', 'url', 'http://127.0.0.1:80/list.txt']) +        self.cli_set(['firewall', 'group', 'remote-group', 'group01', 'description', 'Example Group 01']) +        self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '10', 'action', 'drop']) +        self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '10', 'protocol', 'tcp']) +        self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '10', 'destination', 'group', 'remote-group', 'group01']) + +        self.cli_commit() + +        # Test remote-group had been loaded correctly in nft +        nftables_search = [ +            ['R6_group01'], +            ['type ipv6_addr'], +            ['flags interval'], +            ['meta l4proto', 'daddr @R6_group01', 'ipv6-INP-filter-10'] +        ] +        self.verify_nftables(nftables_search, 'ip6 vyos_filter') + +        # Test remote-group cannot be configured without a URL +        self.cli_delete(['firewall', 'group', 'remote-group', 'group01', 'url']) + +        with self.assertRaises(ConfigSessionError): +            self.cli_commit() +        self.cli_discard() + +        # Test remote-group cannot be set alongside address in rules +        self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '10', 'destination', 'address', '2001:db8::1']) + +        with self.assertRaises(ConfigSessionError): +            self.cli_commit() +        self.cli_discard() + + +    def test_remote_group(self): +        # Setup base config for test adding remote group to both ipv4 and ipv6 rules +        self.cli_set(['firewall', 'group', 'remote-group', 'group01', 'url', 'http://127.0.0.1:80/list.txt']) +        self.cli_set(['firewall', 'group', 'remote-group', 'group01', 'description', 'Example Group 01']) +        self.cli_set(['firewall', 'ipv4', 'output', 'filter', 'rule', '10', 'action', 'drop']) +        self.cli_set(['firewall', 'ipv4', 'output', 'filter', 'rule', '10', 'protocol', 'tcp']) +        self.cli_set(['firewall', 'ipv4', 'output', 'filter', 'rule', '10', 'destination', 'group', 'remote-group', 'group01']) +        self.cli_set(['firewall', 'ipv4', 'input', 'filter', 'rule', '10', 'action', 'drop']) +        self.cli_set(['firewall', 'ipv4', 'input', 'filter', 'rule', '10', 'protocol', 'tcp']) +        self.cli_set(['firewall', 'ipv4', 'input', 'filter', 'rule', '10', 'source', 'group', 'remote-group', 'group01']) +        self.cli_set(['firewall', 'ipv6', 'output', 'filter', 'rule', '10', 'action', 'drop']) +        self.cli_set(['firewall', 'ipv6', 'output', 'filter', 'rule', '10', 'protocol', 'tcp']) +        self.cli_set(['firewall', 'ipv6', 'output', 'filter', 'rule', '10', 'destination', 'group', 'remote-group', 'group01']) +        self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '10', 'action', 'drop']) +        self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '10', 'protocol', 'tcp']) +        self.cli_set(['firewall', 'ipv6', 'input', 'filter', 'rule', '10', 'source', 'group', 'remote-group', 'group01']) + +        self.cli_commit() + +        # Test remote-group had been loaded correctly in nft ip table +        nftables_v4_search = [ +            ['R_group01'], +            ['type ipv4_addr'], +            ['flags interval'], +            ['meta l4proto', 'daddr @R_group01', 'ipv4-OUT-filter-10'], +            ['meta l4proto', 'saddr @R_group01', 'ipv4-INP-filter-10'], +        ] +        self.verify_nftables(nftables_v4_search, 'ip vyos_filter') + +        # Test remote-group had been loaded correctly in nft ip6 table +        nftables_v6_search = [ +            ['R6_group01'], +            ['type ipv6_addr'], +            ['flags interval'], +            ['meta l4proto', 'daddr @R6_group01', 'ipv6-OUT-filter-10'], +            ['meta l4proto', 'saddr @R6_group01', 'ipv6-INP-filter-10'], +        ] +        self.verify_nftables(nftables_v6_search, 'ip6 vyos_filter') + +  if __name__ == '__main__':      unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_high-availability_virtual-server.py b/smoketest/scripts/cli/test_high-availability_virtual-server.py index 2dbf4a5f2..70c400555 100755 --- a/smoketest/scripts/cli/test_high-availability_virtual-server.py +++ b/smoketest/scripts/cli/test_high-availability_virtual-server.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_high-availability_vrrp.py b/smoketest/scripts/cli/test_high-availability_vrrp.py index aa9fa432e..e76fe69f7 100755 --- a/smoketest/scripts/cli/test_high-availability_vrrp.py +++ b/smoketest/scripts/cli/test_high-availability_vrrp.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_interfaces_bonding.py b/smoketest/scripts/cli/test_interfaces_bonding.py index f99fd0363..2473bc732 100755 --- a/smoketest/scripts/cli/test_interfaces_bonding.py +++ b/smoketest/scripts/cli/test_interfaces_bonding.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2023 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_interfaces_bridge.py b/smoketest/scripts/cli/test_interfaces_bridge.py index 4041b3ef3..8502e6b2d 100755 --- a/smoketest/scripts/cli/test_interfaces_bridge.py +++ b/smoketest/scripts/cli/test_interfaces_bridge.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -508,6 +508,31 @@ class BridgeInterfaceTest(BasicInterfaceTest.TestCase):          self.cli_delete(['interfaces', 'vxlan', vxlan_if])          self.cli_delete(['interfaces', 'ethernet', 'eth0', 'address', eth0_addr]) +    def test_bridge_root_bpdu_guard(self): +        # Test if both bpdu_guard and root_guard configured +        self.cli_set(['interfaces', 'bridge', 'br0', 'stp']) +        self.cli_set(['interfaces', 'bridge', 'br0', 'member', 'interface', 'eth0', 'bpdu-guard']) +        self.cli_set(['interfaces', 'bridge', 'br0', 'member', 'interface', 'eth0', 'root-guard']) +        with self.assertRaises(ConfigSessionError): +            self.cli_commit() +        self.cli_discard() + +        # Test if bpdu_guard configured +        self.cli_set(['interfaces', 'bridge', 'br0', 'stp']) +        self.cli_set(['interfaces', 'bridge', 'br0', 'member', 'interface', 'eth0', 'bpdu-guard']) +        self.cli_commit() + +        tmp = read_file(f'/sys/class/net/eth0/brport/bpdu_guard') +        self.assertEqual(tmp, '1') + +        # Test if root_guard configured +        self.cli_delete(['interfaces', 'bridge', 'br0']) +        self.cli_set(['interfaces', 'bridge', 'br0', 'stp']) +        self.cli_set(['interfaces', 'bridge', 'br0', 'member', 'interface', 'eth0', 'root-guard']) +        self.cli_commit() + +        tmp = read_file(f'/sys/class/net/eth0/brport/root_block') +        self.assertEqual(tmp, '1')  if __name__ == '__main__':      unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_interfaces_dummy.py b/smoketest/scripts/cli/test_interfaces_dummy.py index d96ec2c5d..c9cc6124f 100755 --- a/smoketest/scripts/cli/test_interfaces_dummy.py +++ b/smoketest/scripts/cli/test_interfaces_dummy.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2021 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_interfaces_ethernet.py b/smoketest/scripts/cli/test_interfaces_ethernet.py index 2b421e942..780399159 100755 --- a/smoketest/scripts/cli/test_interfaces_ethernet.py +++ b/smoketest/scripts/cli/test_interfaces_ethernet.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_interfaces_geneve.py b/smoketest/scripts/cli/test_interfaces_geneve.py index 5f8fae91e..bb3d7c00d 100755 --- a/smoketest/scripts/cli/test_interfaces_geneve.py +++ b/smoketest/scripts/cli/test_interfaces_geneve.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2022 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_interfaces_input.py b/smoketest/scripts/cli/test_interfaces_input.py index 3ddf86000..611d2985b 100755 --- a/smoketest/scripts/cli/test_interfaces_input.py +++ b/smoketest/scripts/cli/test_interfaces_input.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2023 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_interfaces_l2tpv3.py b/smoketest/scripts/cli/test_interfaces_l2tpv3.py index 28165736b..510be8938 100755 --- a/smoketest/scripts/cli/test_interfaces_l2tpv3.py +++ b/smoketest/scripts/cli/test_interfaces_l2tpv3.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_interfaces_loopback.py b/smoketest/scripts/cli/test_interfaces_loopback.py index f4b6038c5..290cda64b 100755 --- a/smoketest/scripts/cli/test_interfaces_loopback.py +++ b/smoketest/scripts/cli/test_interfaces_loopback.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_interfaces_macsec.py b/smoketest/scripts/cli/test_interfaces_macsec.py index d73895b7f..6465f234c 100755 --- a/smoketest/scripts/cli/test_interfaces_macsec.py +++ b/smoketest/scripts/cli/test_interfaces_macsec.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_interfaces_openvpn.py b/smoketest/scripts/cli/test_interfaces_openvpn.py index e087b8735..ec17d71bf 100755 --- a/smoketest/scripts/cli/test_interfaces_openvpn.py +++ b/smoketest/scripts/cli/test_interfaces_openvpn.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -826,7 +826,6 @@ class TestInterfacesOpenVPN(VyOSUnitTestSHIM.TestCase):          gw_subnet = "192.168.0.1"          self.cli_set(['interfaces', 'bridge', br_if, 'member', 'interface', vtun_if]) -        self.cli_set(path + ['device-type', 'tap'])          self.cli_set(path + ['encryption', 'data-ciphers', 'aes192'])          self.cli_set(path + ['hash', auth_hash])          self.cli_set(path + ['mode', 'server']) @@ -840,6 +839,10 @@ class TestInterfacesOpenVPN(VyOSUnitTestSHIM.TestCase):          self.cli_set(path + ['tls', 'certificate', 'ovpn_test'])          self.cli_set(path + ['tls', 'dh-params', 'ovpn_test']) +        with self.assertRaises(ConfigSessionError): +            self.cli_commit() + +        self.cli_set(path + ['device-type', 'tap'])          self.cli_commit()          config_file = f'/run/openvpn/{vtun_if}.conf' diff --git a/smoketest/scripts/cli/test_interfaces_pppoe.py b/smoketest/scripts/cli/test_interfaces_pppoe.py index 2683a3122..dbc70ebd4 100755 --- a/smoketest/scripts/cli/test_interfaces_pppoe.py +++ b/smoketest/scripts/cli/test_interfaces_pppoe.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2019-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_interfaces_pseudo-ethernet.py b/smoketest/scripts/cli/test_interfaces_pseudo-ethernet.py index 0d6f5bc1f..749c90420 100755 --- a/smoketest/scripts/cli/test_interfaces_pseudo-ethernet.py +++ b/smoketest/scripts/cli/test_interfaces_pseudo-ethernet.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2022 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_interfaces_tunnel.py b/smoketest/scripts/cli/test_interfaces_tunnel.py index dd9f1d2d1..43c98532a 100755 --- a/smoketest/scripts/cli/test_interfaces_tunnel.py +++ b/smoketest/scripts/cli/test_interfaces_tunnel.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2022 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_interfaces_virtual-ethernet.py b/smoketest/scripts/cli/test_interfaces_virtual-ethernet.py index b2af86139..82155dfa7 100755 --- a/smoketest/scripts/cli/test_interfaces_virtual-ethernet.py +++ b/smoketest/scripts/cli/test_interfaces_virtual-ethernet.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2023-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_interfaces_vti.py b/smoketest/scripts/cli/test_interfaces_vti.py index 8d90ca5ad..067c1fb34 100755 --- a/smoketest/scripts/cli/test_interfaces_vti.py +++ b/smoketest/scripts/cli/test_interfaces_vti.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2023-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_interfaces_vxlan.py b/smoketest/scripts/cli/test_interfaces_vxlan.py index 694c24e4d..e7cbf6c0e 100755 --- a/smoketest/scripts/cli/test_interfaces_vxlan.py +++ b/smoketest/scripts/cli/test_interfaces_vxlan.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -125,19 +125,17 @@ class VXLANInterfaceTest(BasicInterfaceTest.TestCase):              'source-interface eth0',              'vni 60'          ] -        params = []          for option in options:              opts = option.split() -            params.append(opts[0]) -            self.cli_set(self._base_path + [ intf ] + opts) +            self.cli_set(self._base_path + [intf] + opts) -        with self.assertRaises(ConfigSessionError) as cm: +        # verify() - Both group and remote cannot be specified +        with self.assertRaises(ConfigSessionError):              self.cli_commit() -        exception = cm.exception -        self.assertIn('Both group and remote cannot be specified', str(exception)) -        for param in params: -            self.cli_delete(self._base_path + [intf, param]) +        # Remove blocking CLI option +        self.cli_delete(self._base_path + [intf, 'group']) +        self.cli_commit()      def test_vxlan_external(self): diff --git a/smoketest/scripts/cli/test_interfaces_wireguard.py b/smoketest/scripts/cli/test_interfaces_wireguard.py index f8cd18cf2..55e3added 100755 --- a/smoketest/scripts/cli/test_interfaces_wireguard.py +++ b/smoketest/scripts/cli/test_interfaces_wireguard.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -154,13 +154,15 @@ class WireGuardInterfaceTest(BasicInterfaceTest.TestCase):              tmp = read_file(f'/sys/class/net/{intf}/threaded')              self.assertTrue(tmp, "1") -    def test_wireguard_peer_pubkey_change(self): +    def test_wireguard_peer_change(self):          # T5707 changing WireGuard CLI public key of a peer - it's not removed +        # Also check if allowed-ips update -        def get_peers(interface) -> list: +        def get_peers(interface) -> list[tuple]:              tmp = cmd(f'sudo wg show {interface} dump')              first_line = True              peers = [] +            allowed_ips = []              for line in tmp.split('\n'):                  if not line:                      continue # Skip empty lines and last line @@ -170,24 +172,27 @@ class WireGuardInterfaceTest(BasicInterfaceTest.TestCase):                      first_line = False                  else:                      peers.append(items[0]) -            return peers +                    allowed_ips.append(items[3]) +            return peers, allowed_ips          interface = 'wg1337'          port = '1337'          privkey = 'iJi4lb2HhkLx2KSAGOjji2alKkYsJjSPkHkrcpxgEVU='          pubkey_1 = 'srQ8VF6z/LDjKCzpxBzFpmaNUOeuHYzIfc2dcmoc/h4='          pubkey_2 = '8pbMHiQ7NECVP7F65Mb2W8+4ldGG2oaGvDSpSEsOBn8=' +        allowed_ips_1 = '10.205.212.10/32' +        allowed_ips_2 = '10.205.212.11/32'          self.cli_set(base_path + [interface, 'address', '172.16.0.1/24'])          self.cli_set(base_path + [interface, 'port', port])          self.cli_set(base_path + [interface, 'private-key', privkey])          self.cli_set(base_path + [interface, 'peer', 'VyOS', 'public-key', pubkey_1]) -        self.cli_set(base_path + [interface, 'peer', 'VyOS', 'allowed-ips', '10.205.212.10/32']) +        self.cli_set(base_path + [interface, 'peer', 'VyOS', 'allowed-ips', allowed_ips_1])          self.cli_commit() -        peers = get_peers(interface) +        peers, _ = get_peers(interface)          self.assertIn(pubkey_1, peers)          self.assertNotIn(pubkey_2, peers) @@ -196,10 +201,20 @@ class WireGuardInterfaceTest(BasicInterfaceTest.TestCase):          self.cli_commit()          # Verify config -        peers = get_peers(interface) +        peers, _ = get_peers(interface)          self.assertNotIn(pubkey_1, peers)          self.assertIn(pubkey_2, peers) +        # Update allowed-ips +        self.cli_delete(base_path + [interface, 'peer', 'VyOS', 'allowed-ips', allowed_ips_1]) +        self.cli_set(base_path + [interface, 'peer', 'VyOS', 'allowed-ips', allowed_ips_2]) +        self.cli_commit() + +        # Verify config +        _, allowed_ips = get_peers(interface) +        self.assertNotIn(allowed_ips_1, allowed_ips) +        self.assertIn(allowed_ips_2, allowed_ips) +      def test_wireguard_hostname(self):          # T4930: Test dynamic endpoint support          interface = 'wg1234' diff --git a/smoketest/scripts/cli/test_interfaces_wireless.py b/smoketest/scripts/cli/test_interfaces_wireless.py index 1c69c1be5..e00d96e35 100755 --- a/smoketest/scripts/cli/test_interfaces_wireless.py +++ b/smoketest/scripts/cli/test_interfaces_wireless.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_load-balancing_haproxy.py b/smoketest/scripts/cli/test_load-balancing_haproxy.py index 077f1974f..a63a3e7f1 100755 --- a/smoketest/scripts/cli/test_load-balancing_haproxy.py +++ b/smoketest/scripts/cli/test_load-balancing_haproxy.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2023 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -14,11 +14,14 @@  # You should have received a copy of the GNU General Public License  # along with this program.  If not, see <http://www.gnu.org/licenses/>. +import re +import textwrap  import unittest  from base_vyostest_shim import VyOSUnitTestSHIM  from vyos.configsession import ConfigSessionError +from vyos.template import get_default_port  from vyos.utils.process import process_named_running  from vyos.utils.file import read_file @@ -131,7 +134,25 @@ ZXLrtgVJR9W020qTurO2f91qfU8646n11hR9ObBB1IYbagOU0Pw1Nrq/FRp/u2tx  7i7xFz2WEiQeSCPaKYOiqM3t  """ +haproxy_service_name = 'https_front' +haproxy_backend_name = 'bk-01' +def parse_haproxy_config() -> dict: +    config_str = read_file(HAPROXY_CONF) +    section_pattern = re.compile(r'^(global|defaults|frontend\s+\S+|backend\s+\S+)', re.MULTILINE) +    sections = {} + +    matches = list(section_pattern.finditer(config_str)) + +    for i, match in enumerate(matches): +        section_name = match.group(1).strip() +        start = match.end() +        end = matches[i + 1].start() if i + 1 < len(matches) else len(config_str) +        section_body = config_str[start:end] +        dedented_body = textwrap.dedent(section_body).strip() +        sections[section_name] = dedented_body + +    return sections  class TestLoadBalancingReverseProxy(VyOSUnitTestSHIM.TestCase):      def tearDown(self):          # Check for running process @@ -146,14 +167,14 @@ class TestLoadBalancingReverseProxy(VyOSUnitTestSHIM.TestCase):          self.assertFalse(process_named_running(PROCESS_NAME))      def base_config(self): -        self.cli_set(base_path + ['service', 'https_front', 'mode', 'http']) -        self.cli_set(base_path + ['service', 'https_front', 'port', '4433']) -        self.cli_set(base_path + ['service', 'https_front', 'backend', 'bk-01']) +        self.cli_set(base_path + ['service', haproxy_service_name, 'mode', 'http']) +        self.cli_set(base_path + ['service', haproxy_service_name, 'port', '4433']) +        self.cli_set(base_path + ['service', haproxy_service_name, 'backend', haproxy_backend_name]) -        self.cli_set(base_path + ['backend', 'bk-01', 'mode', 'http']) -        self.cli_set(base_path + ['backend', 'bk-01', 'server', 'bk-01', 'address', '192.0.2.11']) -        self.cli_set(base_path + ['backend', 'bk-01', 'server', 'bk-01', 'port', '9090']) -        self.cli_set(base_path + ['backend', 'bk-01', 'server', 'bk-01', 'send-proxy']) +        self.cli_set(base_path + ['backend', haproxy_backend_name, 'mode', 'http']) +        self.cli_set(base_path + ['backend', haproxy_backend_name, 'server', haproxy_backend_name, 'address', '192.0.2.11']) +        self.cli_set(base_path + ['backend', haproxy_backend_name, 'server', haproxy_backend_name, 'port', '9090']) +        self.cli_set(base_path + ['backend', haproxy_backend_name, 'server', haproxy_backend_name, 'send-proxy'])          self.cli_set(base_path + ['global-parameters', 'max-connections', '1000']) @@ -167,15 +188,15 @@ class TestLoadBalancingReverseProxy(VyOSUnitTestSHIM.TestCase):          self.cli_set(['pki', 'certificate', 'smoketest', 'certificate', valid_cert.replace('\n','')])          self.cli_set(['pki', 'certificate', 'smoketest', 'private', 'key', valid_cert_private_key.replace('\n','')]) -    def test_01_lb_reverse_proxy_domain(self): +    def test_reverse_proxy_domain(self):          domains_bk_first = ['n1.example.com', 'n2.example.com', 'n3.example.com']          domain_bk_second = 'n5.example.com' -        frontend = 'https_front' +        frontend = 'vyos_smoketest'          front_port = '4433'          bk_server_first = '192.0.2.11'          bk_server_second = '192.0.2.12' -        bk_first_name = 'bk-01' -        bk_second_name = 'bk-02' +        bk_first_name = 'vyosbk-01' +        bk_second_name = 'vyosbk-02'          bk_server_port = '9090'          mode = 'http'          rule_ten = '10' @@ -241,9 +262,9 @@ class TestLoadBalancingReverseProxy(VyOSUnitTestSHIM.TestCase):          self.assertIn(f'server {bk_second_name} {bk_server_second}:{bk_server_port}', config)          self.assertIn(f'server {bk_second_name} {bk_server_second}:{bk_server_port} backup', config) -    def test_02_lb_reverse_proxy_cert_not_exists(self): +    def test_reverse_proxy_cert_not_exists(self):          self.base_config() -        self.cli_set(base_path + ['service', 'https_front', 'ssl', 'certificate', 'cert']) +        self.cli_set(base_path + ['service', haproxy_service_name, 'ssl', 'certificate', 'cert'])          with self.assertRaises(ConfigSessionError) as e:              self.cli_commit() @@ -253,19 +274,19 @@ class TestLoadBalancingReverseProxy(VyOSUnitTestSHIM.TestCase):          self.configure_pki()          self.base_config() -        self.cli_set(base_path + ['service', 'https_front', 'ssl', 'certificate', 'cert']) +        self.cli_set(base_path + ['service', haproxy_service_name, 'ssl', 'certificate', 'cert'])          with self.assertRaises(ConfigSessionError) as e:              self.cli_commit()          # self.assertIn('\nCertificate "cert" does not exist\n', str(e.exception)) -        self.cli_delete(base_path + ['service', 'https_front', 'ssl', 'certificate', 'cert']) -        self.cli_set(base_path + ['service', 'https_front', 'ssl', 'certificate', 'smoketest']) +        self.cli_delete(base_path + ['service', haproxy_service_name, 'ssl', 'certificate', 'cert']) +        self.cli_set(base_path + ['service', haproxy_service_name, 'ssl', 'certificate', 'smoketest'])          self.cli_commit() -    def test_03_lb_reverse_proxy_ca_not_exists(self): +    def test_reverse_proxy_ca_not_exists(self):          self.base_config() -        self.cli_set(base_path + ['backend', 'bk-01', 'ssl', 'ca-certificate', 'ca-test']) +        self.cli_set(base_path + ['backend', haproxy_backend_name, 'ssl', 'ca-certificate', 'ca-test'])          with self.assertRaises(ConfigSessionError) as e:              self.cli_commit() @@ -275,40 +296,40 @@ class TestLoadBalancingReverseProxy(VyOSUnitTestSHIM.TestCase):          self.configure_pki()          self.base_config() -        self.cli_set(base_path + ['backend', 'bk-01', 'ssl', 'ca-certificate', 'ca-test']) +        self.cli_set(base_path + ['backend', haproxy_backend_name, 'ssl', 'ca-certificate', 'ca-test'])          with self.assertRaises(ConfigSessionError) as e:              self.cli_commit()          # self.assertIn('\nCA certificate "ca-test" does not exist\n', str(e.exception)) -        self.cli_delete(base_path + ['backend', 'bk-01', 'ssl', 'ca-certificate', 'ca-test']) -        self.cli_set(base_path + ['backend', 'bk-01', 'ssl', 'ca-certificate', 'smoketest']) +        self.cli_delete(base_path + ['backend', haproxy_backend_name, 'ssl', 'ca-certificate', 'ca-test']) +        self.cli_set(base_path + ['backend', haproxy_backend_name, 'ssl', 'ca-certificate', 'smoketest'])          self.cli_commit() -    def test_04_lb_reverse_proxy_backend_ssl_no_verify(self): +    def test_reverse_proxy_backend_ssl_no_verify(self):          # Setup base          self.configure_pki()          self.base_config()          # Set no-verify option -        self.cli_set(base_path + ['backend', 'bk-01', 'ssl', 'no-verify']) +        self.cli_set(base_path + ['backend', haproxy_backend_name, 'ssl', 'no-verify'])          self.cli_commit()          # Test no-verify option          config = read_file(HAPROXY_CONF) -        self.assertIn('server bk-01 192.0.2.11:9090 send-proxy ssl verify none', config) +        self.assertIn(f'server {haproxy_backend_name} 192.0.2.11:9090 send-proxy ssl verify none', config)          # Test setting ca-certificate alongside no-verify option fails, to test config validation -        self.cli_set(base_path + ['backend', 'bk-01', 'ssl', 'ca-certificate', 'smoketest']) +        self.cli_set(base_path + ['backend', haproxy_backend_name, 'ssl', 'ca-certificate', 'smoketest'])          with self.assertRaises(ConfigSessionError) as e:              self.cli_commit() -    def test_05_lb_reverse_proxy_backend_http_check(self): +    def test_reverse_proxy_backend_http_check(self):          # Setup base          self.base_config()          # Set http-check -        self.cli_set(base_path + ['backend', 'bk-01', 'http-check', 'method', 'get']) +        self.cli_set(base_path + ['backend', haproxy_backend_name, 'http-check', 'method', 'get'])          self.cli_commit()          # Test http-check @@ -317,8 +338,8 @@ class TestLoadBalancingReverseProxy(VyOSUnitTestSHIM.TestCase):          self.assertIn('http-check send meth GET', config)          # Set http-check with uri and status -        self.cli_set(base_path + ['backend', 'bk-01', 'http-check', 'uri', '/health']) -        self.cli_set(base_path + ['backend', 'bk-01', 'http-check', 'expect', 'status', '200']) +        self.cli_set(base_path + ['backend', haproxy_backend_name, 'http-check', 'uri', '/health']) +        self.cli_set(base_path + ['backend', haproxy_backend_name, 'http-check', 'expect', 'status', '200'])          self.cli_commit()          # Test http-check with uri and status @@ -328,8 +349,8 @@ class TestLoadBalancingReverseProxy(VyOSUnitTestSHIM.TestCase):          self.assertIn('http-check expect status 200', config)          # Set http-check with string -        self.cli_delete(base_path + ['backend', 'bk-01', 'http-check', 'expect', 'status', '200']) -        self.cli_set(base_path + ['backend', 'bk-01', 'http-check', 'expect', 'string', 'success']) +        self.cli_delete(base_path + ['backend', haproxy_backend_name, 'http-check', 'expect', 'status', '200']) +        self.cli_set(base_path + ['backend', haproxy_backend_name, 'http-check', 'expect', 'string', 'success'])          self.cli_commit()          # Test http-check with string @@ -339,11 +360,11 @@ class TestLoadBalancingReverseProxy(VyOSUnitTestSHIM.TestCase):          self.assertIn('http-check expect string success', config)          # Test configuring both http-check & health-check fails validation script -        self.cli_set(base_path + ['backend', 'bk-01', 'health-check', 'ldap']) +        self.cli_set(base_path + ['backend', haproxy_backend_name, 'health-check', 'ldap'])          with self.assertRaises(ConfigSessionError) as e:              self.cli_commit() -    def test_06_lb_reverse_proxy_tcp_mode(self): +    def test_reverse_proxy_tcp_mode(self):          frontend = 'tcp_8443'          mode = 'tcp'          front_port = '8433' @@ -390,27 +411,27 @@ class TestLoadBalancingReverseProxy(VyOSUnitTestSHIM.TestCase):          self.assertIn(f'mode {mode}', config)          self.assertIn(f'server {bk_name} {bk_server}:{bk_server_port}', config) -    def test_07_lb_reverse_proxy_http_response_headers(self): +    def test_reverse_proxy_http_response_headers(self):          # Setup base          self.configure_pki()          self.base_config()          # Set example headers in both frontend and backend -        self.cli_set(base_path + ['service', 'https_front', 'http-response-headers', 'Cache-Control', 'value', 'max-age=604800']) -        self.cli_set(base_path + ['backend', 'bk-01',  'http-response-headers', 'Proxy-Backend-ID', 'value', 'bk-01']) +        self.cli_set(base_path + ['service', haproxy_service_name, 'http-response-headers', 'Cache-Control', 'value', 'max-age=604800']) +        self.cli_set(base_path + ['backend', haproxy_backend_name,  'http-response-headers', 'Proxy-Backend-ID', 'value', haproxy_backend_name])          self.cli_commit()          # Test headers are present in generated configuration file          config = read_file(HAPROXY_CONF)          self.assertIn('http-response set-header Cache-Control \'max-age=604800\'', config) -        self.assertIn('http-response set-header Proxy-Backend-ID \'bk-01\'', config) +        self.assertIn(f'http-response set-header Proxy-Backend-ID \'{haproxy_backend_name}\'', config)          # Test setting alongside modes other than http is blocked by validation conditions -        self.cli_set(base_path + ['service', 'https_front', 'mode', 'tcp']) +        self.cli_set(base_path + ['service', haproxy_service_name, 'mode', 'tcp'])          with self.assertRaises(ConfigSessionError) as e:              self.cli_commit() -    def test_08_lb_reverse_proxy_tcp_health_checks(self): +    def test_reverse_proxy_tcp_health_checks(self):          # Setup PKI          self.configure_pki() @@ -458,7 +479,7 @@ class TestLoadBalancingReverseProxy(VyOSUnitTestSHIM.TestCase):          config = read_file(HAPROXY_CONF)          self.assertIn(f'option smtpchk', config) -    def test_09_lb_reverse_proxy_logging(self): +    def test_reverse_proxy_logging(self):          # Setup base          self.base_config()          self.cli_commit() @@ -477,7 +498,7 @@ class TestLoadBalancingReverseProxy(VyOSUnitTestSHIM.TestCase):          self.assertIn('log /dev/log local2 warning', config)          # Test backend logging options -        backend_path = base_path + ['backend', 'bk-01'] +        backend_path = base_path + ['backend', haproxy_backend_name]          self.cli_set(backend_path + ['logging', 'facility', 'local3', 'level', 'debug'])          self.cli_set(backend_path + ['logging', 'facility', 'local4', 'level', 'info'])          self.cli_commit() @@ -488,7 +509,7 @@ class TestLoadBalancingReverseProxy(VyOSUnitTestSHIM.TestCase):          self.assertIn('log /dev/log local4 info', config)          # Test service logging options -        service_path = base_path + ['service', 'https_front'] +        service_path = base_path + ['service', haproxy_service_name]          self.cli_set(service_path + ['logging', 'facility', 'local5', 'level', 'notice'])          self.cli_set(service_path + ['logging', 'facility', 'local6', 'level', 'crit'])          self.cli_commit() @@ -498,16 +519,17 @@ class TestLoadBalancingReverseProxy(VyOSUnitTestSHIM.TestCase):          self.assertIn('log /dev/log local5 notice', config)          self.assertIn('log /dev/log local6 crit', config) -    def test_10_lb_reverse_proxy_http_compression(self): +    def test_reverse_proxy_http_compression(self):          # Setup base          self.configure_pki()          self.base_config()          # Configure compression in frontend -        self.cli_set(base_path + ['service', 'https_front', 'http-compression', 'algorithm', 'gzip']) -        self.cli_set(base_path + ['service', 'https_front', 'http-compression', 'mime-type', 'text/html']) -        self.cli_set(base_path + ['service', 'https_front', 'http-compression', 'mime-type', 'text/javascript']) -        self.cli_set(base_path + ['service', 'https_front', 'http-compression', 'mime-type', 'text/plain']) +        http_comp_path = base_path + ['service', haproxy_service_name, 'http-compression'] +        self.cli_set(http_comp_path + ['algorithm', 'gzip']) +        self.cli_set(http_comp_path + ['mime-type', 'text/html']) +        self.cli_set(http_comp_path + ['mime-type', 'text/javascript']) +        self.cli_set(http_comp_path + ['mime-type', 'text/plain'])          self.cli_commit()          # Test compression is present in generated configuration file @@ -517,11 +539,11 @@ class TestLoadBalancingReverseProxy(VyOSUnitTestSHIM.TestCase):          self.assertIn('compression type text/html text/javascript text/plain', config)          # Test setting compression without specifying any mime-types fails verification -        self.cli_delete(base_path + ['service', 'https_front', 'http-compression', 'mime-type']) +        self.cli_delete(base_path + ['service', haproxy_service_name, 'http-compression', 'mime-type'])          with self.assertRaises(ConfigSessionError) as e:              self.cli_commit() -    def test_11_lb_haproxy_timeout(self): +    def test_reverse_proxy_timeout(self):          t_default_check = '5'          t_default_client = '50'          t_default_connect = '10' @@ -551,7 +573,7 @@ class TestLoadBalancingReverseProxy(VyOSUnitTestSHIM.TestCase):          self.cli_set(base_path + ['timeout', 'client', t_client])          self.cli_set(base_path + ['timeout', 'connect', t_connect])          self.cli_set(base_path + ['timeout', 'server', t_server]) -        self.cli_set(base_path + ['service', 'https_front', 'timeout', 'client', t_front_client]) +        self.cli_set(base_path + ['service', haproxy_service_name, 'timeout', 'client', t_front_client])          self.cli_commit() @@ -569,5 +591,25 @@ class TestLoadBalancingReverseProxy(VyOSUnitTestSHIM.TestCase):          for config_entry in config_entries:              self.assertIn(config_entry, config) +    def test_reverse_proxy_http_redirect(self): +        self.base_config() +        self.cli_set(base_path + ['service', haproxy_service_name, 'redirect-http-to-https']) + +        self.cli_commit() + +        config = parse_haproxy_config() +        frontend_name = f'frontend {haproxy_service_name}-http' +        self.assertIn(frontend_name, config.keys()) +        self.assertIn('mode http', config[frontend_name]) +        self.assertIn('bind [::]:80 v4v6', config[frontend_name]) +        self.assertIn('acl acme_acl path_beg /.well-known/acme-challenge/', config[frontend_name]) +        self.assertIn('use_backend buildin_acme_certbot if acme_acl', config[frontend_name]) +        self.assertIn('redirect scheme https code 301 if !acme_acl', config[frontend_name]) + +        backend_name = 'backend buildin_acme_certbot' +        self.assertIn(backend_name, config.keys()) +        port = get_default_port('certbot_haproxy') +        self.assertIn(f'server localhost 127.0.0.1:{port}', config[backend_name]) +  if __name__ == '__main__':      unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_load-balancing_wan.py b/smoketest/scripts/cli/test_load-balancing_wan.py index 32e5f6915..88a6f0ad7 100755 --- a/smoketest/scripts/cli/test_load-balancing_wan.py +++ b/smoketest/scripts/cli/test_load-balancing_wan.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2022-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -171,8 +171,8 @@ class TestLoadBalancingWan(VyOSUnitTestSHIM.TestCase):          nat_wanloadbalance = """table ip vyos_wanloadbalance {  	chain wlb_nat_postrouting {  		type nat hook postrouting priority srcnat - 1; policy accept; -		ct mark 0x000000c9 counter snat to 203.0.113.10 -		ct mark 0x000000ca counter snat to 192.0.2.10 +		ct mark 0x000000c9 oifname "veth1" counter snat to 203.0.113.10 +		ct mark 0x000000ca oifname "veth2" counter snat to 192.0.2.10  	}  }""" diff --git a/smoketest/scripts/cli/test_nat.py b/smoketest/scripts/cli/test_nat.py index b33ef2617..a370f4779 100755 --- a/smoketest/scripts/cli/test_nat.py +++ b/smoketest/scripts/cli/test_nat.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_nat64.py b/smoketest/scripts/cli/test_nat64.py index 5c907f6cb..1c5f62874 100755 --- a/smoketest/scripts/cli/test_nat64.py +++ b/smoketest/scripts/cli/test_nat64.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2023-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_nat66.py b/smoketest/scripts/cli/test_nat66.py index 52ad8e3ef..bec023ca9 100755 --- a/smoketest/scripts/cli/test_nat66.py +++ b/smoketest/scripts/cli/test_nat66.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -227,6 +227,35 @@ class TestNAT66(VyOSUnitTestSHIM.TestCase):          self.verify_nftables(nftables_search, 'ip6 vyos_nat') +    def test_source_nat66_network_group(self): +        address_group = 'smoketest_addr' +        address_group_member = 'fc00::1' +        network_group = 'smoketest_net' +        network_group_member = 'fc00::/64' +        translation_prefix = 'fc01::/64' + +        self.cli_set(['firewall', 'group', 'ipv6-address-group', address_group, 'address', address_group_member]) +        self.cli_set(['firewall', 'group', 'ipv6-network-group', network_group, 'network', network_group_member]) + +        self.cli_set(src_path + ['rule', '1', 'destination', 'group', 'address-group', address_group]) +        self.cli_set(src_path + ['rule', '1', 'translation', 'address', translation_prefix]) + +        self.cli_set(src_path + ['rule', '2', 'destination', 'group', 'network-group', network_group]) +        self.cli_set(src_path + ['rule', '2', 'translation', 'address', translation_prefix]) + +        self.cli_commit() + +        nftables_search = [ +            [f'set A6_{address_group}'], +            [f'elements = {{ {address_group_member} }}'], +            [f'set N6_{network_group}'], +            [f'elements = {{ {network_group_member} }}'], +            ['ip6 daddr', f'@A6_{address_group}', 'snat prefix to fc01::/64'], +            ['ip6 daddr', f'@N6_{network_group}', 'snat prefix to fc01::/64'] +        ] + +        self.verify_nftables(nftables_search, 'ip6 vyos_nat') +      def test_nat66_no_rules(self):          # T3206: deleting all rules but keep the direction 'destination' or          # 'source' resulteds in KeyError: 'rule'. diff --git a/smoketest/scripts/cli/test_netns.py b/smoketest/scripts/cli/test_netns.py index 2ac603a69..9ed85ef7a 100755 --- a/smoketest/scripts/cli/test_netns.py +++ b/smoketest/scripts/cli/test_netns.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_op-mode_show.py b/smoketest/scripts/cli/test_op-mode_show.py index 62f8e88da..10dbe0330 100755 --- a/smoketest/scripts/cli/test_op-mode_show.py +++ b/smoketest/scripts/cli/test_op-mode_show.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_pki.py b/smoketest/scripts/cli/test_pki.py index 02beafb26..a43d92b08 100755 --- a/smoketest/scripts/cli/test_pki.py +++ b/smoketest/scripts/cli/test_pki.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_policy.py b/smoketest/scripts/cli/test_policy.py index 985097726..8849ee182 100755 --- a/smoketest/scripts/cli/test_policy.py +++ b/smoketest/scripts/cli/test_policy.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_policy_local-route.py b/smoketest/scripts/cli/test_policy_local-route.py index a4239b8a1..5b3f84cc1 100644 --- a/smoketest/scripts/cli/test_policy_local-route.py +++ b/smoketest/scripts/cli/test_policy_local-route.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2024-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_policy_route.py b/smoketest/scripts/cli/test_policy_route.py index 53761b7d6..5a0eb7f7c 100755 --- a/smoketest/scripts/cli/test_policy_route.py +++ b/smoketest/scripts/cli/test_policy_route.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -307,5 +307,39 @@ class TestPolicyRoute(VyOSUnitTestSHIM.TestCase):          self.verify_nftables(nftables6_search, 'ip6 vyos_mangle') +    def test_geoip(self): +        self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'action', 'drop']) +        self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'source', 'geoip', 'country-code', 'se']) +        self.cli_set(['policy', 'route', 'smoketest', 'rule', '1', 'source', 'geoip', 'country-code', 'gb']) +        self.cli_set(['policy', 'route', 'smoketest', 'rule', '2', 'action', 'accept']) +        self.cli_set(['policy', 'route', 'smoketest', 'rule', '2', 'source', 'geoip', 'country-code', 'de']) +        self.cli_set(['policy', 'route', 'smoketest', 'rule', '2', 'source', 'geoip', 'country-code', 'fr']) +        self.cli_set(['policy', 'route', 'smoketest', 'rule', '2', 'source', 'geoip', 'inverse-match']) + +        self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '1', 'action', 'drop']) +        self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '1', 'source', 'geoip', 'country-code', 'se']) +        self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '1', 'source', 'geoip', 'country-code', 'gb']) +        self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '2', 'action', 'accept']) +        self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '2', 'source', 'geoip', 'country-code', 'de']) +        self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '2', 'source', 'geoip', 'country-code', 'fr']) +        self.cli_set(['policy', 'route6', 'smoketest6', 'rule', '2', 'source', 'geoip', 'inverse-match']) + +        self.cli_commit() + +        nftables_search = [ +            ['ip saddr @GEOIP_CC_route_smoketest_1', 'drop'], +            ['ip saddr != @GEOIP_CC_route_smoketest_2', 'accept'], +        ] + +        # -t prevents 1000+ GeoIP elements being returned +        self.verify_nftables(nftables_search, 'ip vyos_mangle', args='-t') + +        nftables_search = [ +            ['ip6 saddr @GEOIP_CC6_route6_smoketest6_1', 'drop'], +            ['ip6 saddr != @GEOIP_CC6_route6_smoketest6_2', 'accept'], +        ] + +        self.verify_nftables(nftables_search, 'ip6 vyos_mangle', args='-t') +  if __name__ == '__main__':      unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_protocols_babel.py b/smoketest/scripts/cli/test_protocols_babel.py index 3a9ee2d62..0032a5688 100755 --- a/smoketest/scripts/cli/test_protocols_babel.py +++ b/smoketest/scripts/cli/test_protocols_babel.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2024-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_protocols_bfd.py b/smoketest/scripts/cli/test_protocols_bfd.py index 2205cd9de..59b0abfac 100755 --- a/smoketest/scripts/cli/test_protocols_bfd.py +++ b/smoketest/scripts/cli/test_protocols_bfd.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py index 8403dcc37..be48e6aaa 100755 --- a/smoketest/scripts/cli/test_protocols_bgp.py +++ b/smoketest/scripts/cli/test_protocols_bgp.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -358,6 +358,7 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):          self.cli_set(base_path + ['parameters', 'no-suppress-duplicates'])          self.cli_set(base_path + ['parameters', 'reject-as-sets'])          self.cli_set(base_path + ['parameters', 'route-reflector-allow-outbound-policy']) +        self.cli_set(base_path + ['parameters', 'no-ipv6-auto-ra'])          self.cli_set(base_path + ['parameters', 'shutdown'])          self.cli_set(base_path + ['parameters', 'suppress-fib-pending'])          self.cli_set(base_path + ['parameters', 'tcp-keepalive', 'idle', tcp_keepalive_idle]) @@ -396,6 +397,7 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):          self.assertIn(f' bgp minimum-holdtime {min_hold_time}', frrconfig)          self.assertIn(f' bgp reject-as-sets', frrconfig)          self.assertIn(f' bgp route-reflector allow-outbound-policy', frrconfig) +        self.assertIn(f' no bgp ipv6-auto-ra', frrconfig)          self.assertIn(f' bgp shutdown', frrconfig)          self.assertIn(f' bgp suppress-fib-pending', frrconfig)          self.assertIn(f' bgp tcp-keepalive {tcp_keepalive_idle} {tcp_keepalive_interval} {tcp_keepalive_probes}', frrconfig) diff --git a/smoketest/scripts/cli/test_protocols_igmp-proxy.py b/smoketest/scripts/cli/test_protocols_igmp-proxy.py index df10442ea..c705132bb 100755 --- a/smoketest/scripts/cli/test_protocols_igmp-proxy.py +++ b/smoketest/scripts/cli/test_protocols_igmp-proxy.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2019-2023 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_protocols_isis.py b/smoketest/scripts/cli/test_protocols_isis.py index 14e833fd9..18f475fa9 100755 --- a/smoketest/scripts/cli/test_protocols_isis.py +++ b/smoketest/scripts/cli/test_protocols_isis.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_protocols_mpls.py b/smoketest/scripts/cli/test_protocols_mpls.py index 3840c24f4..a83a41df7 100755 --- a/smoketest/scripts/cli/test_protocols_mpls.py +++ b/smoketest/scripts/cli/test_protocols_mpls.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_protocols_nhrp.py b/smoketest/scripts/cli/test_protocols_nhrp.py index 73a760945..5f99cd92f 100755 --- a/smoketest/scripts/cli/test_protocols_nhrp.py +++ b/smoketest/scripts/cli/test_protocols_nhrp.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_protocols_openfabric.py b/smoketest/scripts/cli/test_protocols_openfabric.py index 323b6cd74..e44711993 100644 --- a/smoketest/scripts/cli/test_protocols_openfabric.py +++ b/smoketest/scripts/cli/test_protocols_openfabric.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_protocols_ospf.py b/smoketest/scripts/cli/test_protocols_ospf.py index ea55fa031..7a0f087e1 100755 --- a/smoketest/scripts/cli/test_protocols_ospf.py +++ b/smoketest/scripts/cli/test_protocols_ospf.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -574,5 +574,23 @@ class TestProtocolsOSPF(VyOSUnitTestSHIM.TestCase):          self.assertIn(f'router ospf', frrconfig)          self.assertIn(f' network {network} area {area1}', frrconfig) +    def test_ospf_18_area_translate_no_summary(self): +        area = '11' +        area_type = 'nssa' +        network = '100.64.0.0/10' + +        self.cli_set(base_path + ['area', area, 'area-type', area_type, 'no-summary']) +        self.cli_set(base_path + ['area', area, 'area-type', area_type, 'translate', 'never']) +        self.cli_set(base_path + ['area', area, 'network', network]) + +        # commit changes +        self.cli_commit() + +        # Verify FRR ospfd configuration +        frrconfig = self.getFRRconfig('router ospf', endsection='^exit') +        self.assertIn(f'router ospf', frrconfig) +        self.assertIn(f' area {area} {area_type} translate-never no-summary', frrconfig) +        self.assertIn(f' network {network} area {area}', frrconfig) +  if __name__ == '__main__':      unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_protocols_ospfv3.py b/smoketest/scripts/cli/test_protocols_ospfv3.py index 5da4c7c98..484bd2acc 100755 --- a/smoketest/scripts/cli/test_protocols_ospfv3.py +++ b/smoketest/scripts/cli/test_protocols_ospfv3.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_protocols_pim.py b/smoketest/scripts/cli/test_protocols_pim.py index cc62769b3..f1c6053e7 100755 --- a/smoketest/scripts/cli/test_protocols_pim.py +++ b/smoketest/scripts/cli/test_protocols_pim.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2023 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_protocols_pim6.py b/smoketest/scripts/cli/test_protocols_pim6.py index 4ed8fcf7a..d10a3efc2 100755 --- a/smoketest/scripts/cli/test_protocols_pim6.py +++ b/smoketest/scripts/cli/test_protocols_pim6.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2023 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_protocols_rip.py b/smoketest/scripts/cli/test_protocols_rip.py index 27b543803..67da2382c 100755 --- a/smoketest/scripts/cli/test_protocols_rip.py +++ b/smoketest/scripts/cli/test_protocols_rip.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_protocols_ripng.py b/smoketest/scripts/cli/test_protocols_ripng.py index d2066b825..830c8bb3a 100755 --- a/smoketest/scripts/cli/test_protocols_ripng.py +++ b/smoketest/scripts/cli/test_protocols_ripng.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_protocols_rpki.py b/smoketest/scripts/cli/test_protocols_rpki.py index 0addf7fee..50a157fd0 100755 --- a/smoketest/scripts/cli/test_protocols_rpki.py +++ b/smoketest/scripts/cli/test_protocols_rpki.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -25,6 +25,11 @@ from vyos.utils.file import read_file  from vyos.utils.process import process_named_running  base_path = ['protocols', 'rpki'] +base_frr_config_args = {'string': 'rpki', 'endsection': '^exit'} +vrf = 'blue' +vrf_path = ['vrf', 'name', vrf] +vrf_frr_config_args = {'string': f'vrf {vrf}', 'endsection':'^exit-vrf', +                'substring': ' rpki', 'endsubsection': '^ exit'}  rpki_key_name = 'rpki-smoketest'  rpki_key_type = 'ssh-rsa' @@ -112,14 +117,19 @@ class TestProtocolsRPKI(VyOSUnitTestSHIM.TestCase):          # ensure we can also run this test on a live system - so lets clean          # out the current configuration :)          cls.cli_delete(cls, base_path) +        cls.cli_delete(cls, vrf_path)          # Enable CSTORE guard time required by FRR related tests          cls._commit_guard_time = CSTORE_GUARD_TIME      def tearDown(self):          self.cli_delete(base_path) +        self.cli_delete(vrf_path)          self.cli_commit() -        frrconfig = self.getFRRconfig('rpki', endsection='^exit') +        frrconfig = self.getFRRconfig(**base_frr_config_args) +        self.assertNotIn(f'rpki', frrconfig) + +        frrconfig = self.getFRRconfig(**vrf_frr_config_args)          self.assertNotIn(f'rpki', frrconfig)          # check process health and continuity @@ -144,27 +154,33 @@ class TestProtocolsRPKI(VyOSUnitTestSHIM.TestCase):              },          } -        self.cli_set(base_path + ['expire-interval', expire_interval]) -        self.cli_set(base_path + ['polling-period', polling_period]) -        self.cli_set(base_path + ['retry-interval', retry_interval]) +        for test_set in [ {'path': base_path, 'frrargs': base_frr_config_args}, +                          {'path': vrf_path + base_path, 'frrargs': vrf_frr_config_args} ]: -        for peer, peer_config in cache.items(): -            self.cli_set(base_path + ['cache', peer, 'port', peer_config['port']]) -            self.cli_set(base_path + ['cache', peer, 'preference', peer_config['preference']]) +            if 'vrf' in test_set['path']: +                self.cli_set(vrf_path + ['table', '1000']) -        # commit changes -        self.cli_commit() +            self.cli_set(test_set['path'] + ['expire-interval', expire_interval]) +            self.cli_set(test_set['path'] + ['polling-period', polling_period]) +            self.cli_set(test_set['path'] + ['retry-interval', retry_interval]) + +            for peer, peer_config in cache.items(): +                self.cli_set(test_set['path'] + ['cache', peer, 'port', peer_config['port']]) +                self.cli_set(test_set['path'] + ['cache', peer, 'preference', peer_config['preference']]) + +            # commit changes +            self.cli_commit() -        # Verify FRR configuration -        frrconfig = self.getFRRconfig('rpki', endsection='^exit') -        self.assertIn(f'rpki expire_interval {expire_interval}', frrconfig) -        self.assertIn(f'rpki polling_period {polling_period}', frrconfig) -        self.assertIn(f'rpki retry_interval {retry_interval}', frrconfig) +            # Verify FRR configuration +            frrconfig = self.getFRRconfig(**test_set['frrargs']) +            self.assertIn(f'rpki expire_interval {expire_interval}', frrconfig) +            self.assertIn(f'rpki polling_period {polling_period}', frrconfig) +            self.assertIn(f'rpki retry_interval {retry_interval}', frrconfig) -        for peer, peer_config in cache.items(): -            port = peer_config['port'] -            preference = peer_config['preference'] -            self.assertIn(f'rpki cache tcp {peer} {port} preference {preference}', frrconfig) +            for peer, peer_config in cache.items(): +                port = peer_config['port'] +                preference = peer_config['preference'] +                self.assertIn(f'rpki cache tcp {peer} {port} preference {preference}', frrconfig)      def test_rpki_ssh(self):          polling = '7200' @@ -185,28 +201,34 @@ class TestProtocolsRPKI(VyOSUnitTestSHIM.TestCase):          self.cli_set(['pki', 'openssh', rpki_key_name, 'public', 'key', rpki_ssh_pub.replace('\n','')])          self.cli_set(['pki', 'openssh', rpki_key_name, 'public', 'type', rpki_key_type]) -        for cache_name, cache_config in cache.items(): -            self.cli_set(base_path + ['cache', cache_name, 'port', cache_config['port']]) -            self.cli_set(base_path + ['cache', cache_name, 'preference', cache_config['preference']]) -            self.cli_set(base_path + ['cache', cache_name, 'ssh', 'username', cache_config['username']]) -            self.cli_set(base_path + ['cache', cache_name, 'ssh', 'key', rpki_key_name]) +        for test_set in [ {'path': base_path, 'frrargs': base_frr_config_args}, +                          {'path': vrf_path + base_path, 'frrargs': vrf_frr_config_args} ]: -        # commit changes -        self.cli_commit() +            if 'vrf' in test_set['path']: +                self.cli_set(vrf_path + ['table', '1000']) + +            for cache_name, cache_config in cache.items(): +                self.cli_set(test_set['path'] + ['cache', cache_name, 'port', cache_config['port']]) +                self.cli_set(test_set['path'] + ['cache', cache_name, 'preference', cache_config['preference']]) +                self.cli_set(test_set['path'] + ['cache', cache_name, 'ssh', 'username', cache_config['username']]) +                self.cli_set(test_set['path'] + ['cache', cache_name, 'ssh', 'key', rpki_key_name]) + +            # commit changes +            self.cli_commit() -        # Verify FRR configuration -        frrconfig = self.getFRRconfig('rpki', endsection='^exit') -        for cache_name, cache_config in cache.items(): -            port = cache_config['port'] -            preference = cache_config['preference'] -            username = cache_config['username'] -            self.assertIn(f'rpki cache ssh {cache_name} {port} {username} /run/frr/id_rpki_{cache_name} /run/frr/id_rpki_{cache_name}.pub preference {preference}', frrconfig) +            # Verify FRR configuration +            frrconfig = self.getFRRconfig(**test_set['frrargs']) +            for cache_name, cache_config in cache.items(): +                port = cache_config['port'] +                preference = cache_config['preference'] +                username = cache_config['username'] +                self.assertIn(f'rpki cache ssh {cache_name} {port} {username} /run/frr/id_rpki_{cache_name} /run/frr/id_rpki_{cache_name}.pub preference {preference}', frrconfig) -            # Verify content of SSH keys -            tmp = read_file(f'/run/frr/id_rpki_{cache_name}') -            self.assertIn(rpki_ssh_key.replace('\n',''), tmp) -            tmp = read_file(f'/run/frr/id_rpki_{cache_name}.pub') -            self.assertIn(rpki_ssh_pub.replace('\n',''), tmp) +                # Verify content of SSH keys +                tmp = read_file(f'/run/frr/id_rpki_{cache_name}') +                self.assertIn(rpki_ssh_key.replace('\n',''), tmp) +                tmp = read_file(f'/run/frr/id_rpki_{cache_name}.pub') +                self.assertIn(rpki_ssh_pub.replace('\n',''), tmp)          # Change OpenSSH key and verify it was properly written to filesystem          self.cli_set(['pki', 'openssh', rpki_key_name, 'private', 'key', rpki_ssh_key_replacement.replace('\n','')]) @@ -214,17 +236,21 @@ class TestProtocolsRPKI(VyOSUnitTestSHIM.TestCase):          # commit changes          self.cli_commit() -        for cache_name, cache_config in cache.items(): -            port = cache_config['port'] -            preference = cache_config['preference'] -            username = cache_config['username'] -            self.assertIn(f'rpki cache ssh {cache_name} {port} {username} /run/frr/id_rpki_{cache_name} /run/frr/id_rpki_{cache_name}.pub preference {preference}', frrconfig) +        for test_set in [ {'path': base_path, 'frrargs': base_frr_config_args}, +                          {'path': vrf_path + base_path, 'frrargs': vrf_frr_config_args} ]: -            # Verify content of SSH keys -            tmp = read_file(f'/run/frr/id_rpki_{cache_name}') -            self.assertIn(rpki_ssh_key_replacement.replace('\n',''), tmp) -            tmp = read_file(f'/run/frr/id_rpki_{cache_name}.pub') -            self.assertIn(rpki_ssh_pub_replacement.replace('\n',''), tmp) +            frrconfig = self.getFRRconfig(**test_set['frrargs']) +            for cache_name, cache_config in cache.items(): +                port = cache_config['port'] +                preference = cache_config['preference'] +                username = cache_config['username'] +                self.assertIn(f'rpki cache ssh {cache_name} {port} {username} /run/frr/id_rpki_{cache_name} /run/frr/id_rpki_{cache_name}.pub preference {preference}', frrconfig) + +                # Verify content of SSH keys +                tmp = read_file(f'/run/frr/id_rpki_{cache_name}') +                self.assertIn(rpki_ssh_key_replacement.replace('\n',''), tmp) +                tmp = read_file(f'/run/frr/id_rpki_{cache_name}.pub') +                self.assertIn(rpki_ssh_pub_replacement.replace('\n',''), tmp)          self.cli_delete(['pki', 'openssh']) @@ -240,13 +266,19 @@ class TestProtocolsRPKI(VyOSUnitTestSHIM.TestCase):              },          } -        for peer, peer_config in cache.items(): -            self.cli_set(base_path + ['cache', peer, 'port', peer_config['port']]) -            self.cli_set(base_path + ['cache', peer, 'preference', peer_config['preference']]) +        for test_set in [ {'path': base_path, 'frrargs': base_frr_config_args}, +                          {'path': vrf_path + base_path, 'frrargs': vrf_frr_config_args} ]: -        # check validate() - preferences must be unique -        with self.assertRaises(ConfigSessionError): -            self.cli_commit() +            if 'vrf' in test_set['path']: +                self.cli_set(vrf_path + ['table', '1000']) + +            for peer, peer_config in cache.items(): +                self.cli_set(test_set['path'] + ['cache', peer, 'port', peer_config['port']]) +                self.cli_set(test_set['path'] + ['cache', peer, 'preference', peer_config['preference']]) + +            # check validate() - preferences must be unique +            with self.assertRaises(ConfigSessionError): +                self.cli_commit()      def test_rpki_source_address(self):          peer = '192.0.2.1' @@ -257,31 +289,38 @@ class TestProtocolsRPKI(VyOSUnitTestSHIM.TestCase):          self.cli_set(['interfaces', 'ethernet', 'eth0', 'address', f'{source_address}/24']) -        # Configure a TCP cache server -        self.cli_set(base_path + ['cache', peer, 'port', port]) -        self.cli_set(base_path + ['cache', peer, 'preference', preference]) -        self.cli_set(base_path + ['cache', peer, 'source-address', source_address]) -        self.cli_commit() -        # Verify FRR configuration -        frrconfig = self.getFRRconfig('rpki') -        self.assertIn(f'rpki cache tcp {peer} {port} source {source_address} preference {preference}', frrconfig) +        for test_set in [ {'path': base_path, 'frrargs': base_frr_config_args}, +                          {'path': vrf_path + base_path, 'frrargs': vrf_frr_config_args} ]: -        self.cli_set(['pki', 'openssh', rpki_key_name, 'private', 'key', rpki_ssh_key.replace('\n', '')]) -        self.cli_set(['pki', 'openssh', rpki_key_name, 'public', 'key', rpki_ssh_pub.replace('\n', '')]) -        self.cli_set(['pki', 'openssh', rpki_key_name, 'public', 'type', rpki_key_type]) +            if 'vrf' in test_set['path']: +                self.cli_set(vrf_path + ['table', '1000']) -        # Configure a SSH cache server -        self.cli_set(base_path + ['cache', peer, 'ssh', 'username', username]) -        self.cli_set(base_path + ['cache', peer, 'ssh', 'key', rpki_key_name]) -        self.cli_commit() +            # Configure a TCP cache server +            self.cli_set(test_set['path'] + ['cache', peer, 'port', port]) +            self.cli_set(test_set['path'] + ['cache', peer, 'preference', preference]) +            self.cli_set(test_set['path'] + ['cache', peer, 'source-address', source_address]) +            self.cli_commit() + +            # Verify FRR configuration +            frrconfig = self.getFRRconfig(**test_set['frrargs']) +            self.assertIn(f'rpki cache tcp {peer} {port} source {source_address} preference {preference}', frrconfig) + +            self.cli_set(['pki', 'openssh', rpki_key_name, 'private', 'key', rpki_ssh_key.replace('\n', '')]) +            self.cli_set(['pki', 'openssh', rpki_key_name, 'public', 'key', rpki_ssh_pub.replace('\n', '')]) +            self.cli_set(['pki', 'openssh', rpki_key_name, 'public', 'type', rpki_key_type]) + +            # Configure a SSH cache server +            self.cli_set(test_set['path'] + ['cache', peer, 'ssh', 'username', username]) +            self.cli_set(test_set['path'] + ['cache', peer, 'ssh', 'key', rpki_key_name]) +            self.cli_commit() -        # Verify FRR configuration -        frrconfig = self.getFRRconfig('rpki') -        self.assertIn( -            f'rpki cache ssh {peer} {port} {username} /run/frr/id_rpki_{peer} /run/frr/id_rpki_{peer}.pub source {source_address} preference {preference}', -            frrconfig, -        ) +            # Verify FRR configuration +            frrconfig = self.getFRRconfig(**test_set['frrargs']) +            self.assertIn( +                f'rpki cache ssh {peer} {port} {username} /run/frr/id_rpki_{peer} /run/frr/id_rpki_{peer}.pub source {source_address} preference {preference}', +                frrconfig, +            )  if __name__ == '__main__': diff --git a/smoketest/scripts/cli/test_protocols_segment-routing.py b/smoketest/scripts/cli/test_protocols_segment-routing.py index 94c808733..94e769bb1 100755 --- a/smoketest/scripts/cli/test_protocols_segment-routing.py +++ b/smoketest/scripts/cli/test_protocols_segment-routing.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2023-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_protocols_static.py b/smoketest/scripts/cli/test_protocols_static.py index 79d6b3af4..66fb880c5 100755 --- a/smoketest/scripts/cli/test_protocols_static.py +++ b/smoketest/scripts/cli/test_protocols_static.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_protocols_static_arp.py b/smoketest/scripts/cli/test_protocols_static_arp.py index 7f8047249..c0d62ecb5 100755 --- a/smoketest/scripts/cli/test_protocols_static_arp.py +++ b/smoketest/scripts/cli/test_protocols_static_arp.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2022 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_qos.py b/smoketest/scripts/cli/test_qos.py index 231743344..03160ec7e 100755 --- a/smoketest/scripts/cli/test_qos.py +++ b/smoketest/scripts/cli/test_qos.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2022-2023 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -355,10 +355,10 @@ class TestQoS(VyOSUnitTestSHIM.TestCase):              tc_details = get_tc_filter_details(interface, 'ingress')              self.assertTrue('filter parent ffff: protocol all pref 20 u32 chain 0' in tc_details) -            self.assertTrue('rate 1Gbit burst 15125b mtu 2Kb action drop overhead 0b linklayer ethernet' in tc_details) +            self.assertTrue('rate 1Gbit burst 15Kb mtu 2Kb action drop overhead 0b linklayer ethernet' in tc_details)              self.assertTrue('filter parent ffff: protocol all pref 15 u32 chain 0' in tc_details) -            self.assertTrue('rate 3Gbit burst 102000b mtu 1600b action pipe/continue overhead 0b linklayer ethernet' in tc_details) -            self.assertTrue('rate 500Mbit burst 204687b mtu 3000b action drop overhead 0b linklayer ethernet' in tc_details) +            self.assertTrue('rate 3Gbit burst 100Kb mtu 1600b action pipe/continue overhead 0b linklayer ethernet' in tc_details) +            self.assertTrue('rate 500Mbit burst 200Kb mtu 3000b action drop overhead 0b linklayer ethernet' in tc_details)              self.assertTrue('filter parent ffff: protocol all pref 255 basic chain 0' in tc_details)      def test_06_network_emulator(self): @@ -773,7 +773,7 @@ class TestQoS(VyOSUnitTestSHIM.TestCase):          tc_filters = cmd(f'tc filter show dev {self._interfaces[0]} ingress')          # class 100          self.assertIn('filter parent ffff: protocol all pref 20 fw chain 0', tc_filters) -        self.assertIn('action order 1:  police 0x1 rate 20Gbit burst 3847500b mtu 2Kb action drop overhead 0b', tc_filters) +        self.assertIn('action order 1:  police 0x1 rate 20Gbit burst 3760Kb mtu 2Kb action drop overhead 0b', tc_filters)          # default          self.assertIn('filter parent ffff: protocol all pref 255 basic chain 0', tc_filters)          self.assertIn('action order 1:  police 0x2 rate 1Gbit burst 125000000b mtu 2Kb action drop overhead 0b', tc_filters) @@ -884,6 +884,8 @@ class TestQoS(VyOSUnitTestSHIM.TestCase):              base_path + ['policy', 'cake', policy_name, 'bandwidth', str(bandwidth)]          )          self.cli_set(base_path + ['policy', 'cake', policy_name, 'rtt', str(rtt)]) +        self.cli_set(base_path + ['policy', 'cake', policy_name, 'no-split-gso']) +        self.cli_set(base_path + ['policy', 'cake', policy_name, 'ack-filter', 'aggressive'])          # commit changes          self.cli_commit() @@ -899,6 +901,23 @@ class TestQoS(VyOSUnitTestSHIM.TestCase):          self.assertFalse(tmp['options']['ingress'])          self.assertFalse(tmp['options']['nat'])          self.assertTrue(tmp['options']['raw']) +        self.assertFalse(tmp['options']['split_gso']) +        self.assertEqual(tmp['options']['ack-filter'], 'aggressive') + +        self.cli_delete(base_path + ['policy', 'cake', policy_name, 'ack-filter', 'aggressive']) +        self.cli_commit() +        tmp = get_tc_qdisc_json(interface) +        self.assertEqual(tmp['options']['ack-filter'], 'enabled') + +        self.cli_delete(base_path + ['policy', 'cake', policy_name, 'ack-filter']) +        self.cli_commit() +        tmp = get_tc_qdisc_json(interface) +        self.assertEqual(tmp['options']['ack-filter'], 'disabled') + +        self.cli_delete(base_path + ['policy', 'cake', policy_name, 'no-split-gso']) +        self.cli_commit() +        tmp = get_tc_qdisc_json(interface) +        self.assertTrue(tmp['options']['split_gso'])          nat = True          for flow_isolation in [ @@ -1232,7 +1251,7 @@ class TestQoS(VyOSUnitTestSHIM.TestCase):          # class 100          self.assertIn('filter parent ffff: protocol all pref 20 basic chain 0', tc_filters)          self.assertIn(f'meta(rt_iif eq {iif})', tc_filters) -        self.assertIn('action order 1:  police 0x1 rate 20Gbit burst 3847500b mtu 2Kb action drop overhead 0b', tc_filters) +        self.assertIn('action order 1:  police 0x1 rate 20Gbit burst 3760Kb mtu 2Kb action drop overhead 0b', tc_filters)          # default          self.assertIn('filter parent ffff: protocol all pref 255 basic chain 0', tc_filters)          self.assertIn('action order 1:  police 0x2 rate 1Gbit burst 125000000b mtu 2Kb action drop overhead 0b', tc_filters) diff --git a/smoketest/scripts/cli/test_service_broadcast-relay.py b/smoketest/scripts/cli/test_service_broadcast-relay.py index 87901869e..7f877869a 100755 --- a/smoketest/scripts/cli/test_service_broadcast-relay.py +++ b/smoketest/scripts/cli/test_service_broadcast-relay.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2019-2020 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_service_dhcp-relay.py b/smoketest/scripts/cli/test_service_dhcp-relay.py index 59c4b59a9..6d4e79817 100755 --- a/smoketest/scripts/cli/test_service_dhcp-relay.py +++ b/smoketest/scripts/cli/test_service_dhcp-relay.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_service_dhcp-server.py b/smoketest/scripts/cli/test_service_dhcp-server.py index 935be6227..dcd6a5720 100755 --- a/smoketest/scripts/cli/test_service_dhcp-server.py +++ b/smoketest/scripts/cli/test_service_dhcp-server.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -32,7 +32,10 @@ from vyos.template import inc_ip  from vyos.template import dec_ip  PROCESS_NAME = 'kea-dhcp4' +D2_PROCESS_NAME = 'kea-dhcp-ddns' +CTRL_PROCESS_NAME = 'kea-ctrl-agent'  KEA4_CONF = '/run/kea/kea-dhcp4.conf' +KEA4_D2_CONF = '/run/kea/kea-dhcp-ddns.conf'  KEA4_CTRL = '/run/kea/dhcp4-ctrl-socket'  HOSTSD_CLIENT = '/usr/bin/vyos-hostsd-client'  base_path = ['service', 'dhcp-server'] @@ -1116,6 +1119,133 @@ class TestServiceDHCPServer(VyOSUnitTestSHIM.TestCase):          # Check for running process          self.verify_service_running() +    def test_dhcp_dynamic_dns_update(self): +        shared_net_name = 'SMOKE-1DDNS' + +        range_0_start = inc_ip(subnet, 10) +        range_0_stop  = inc_ip(subnet, 20) + +        self.cli_set(base_path + ['listen-interface', interface]) + +        ddns = base_path + ['dynamic-dns-update'] + +        self.cli_set(ddns + ['send-updates', 'enable']) +        self.cli_set(ddns + ['conflict-resolution', 'enable']) +        self.cli_set(ddns + ['override-no-update', 'enable']) +        self.cli_set(ddns + ['override-client-update', 'enable']) +        self.cli_set(ddns + ['replace-client-name', 'always']) +        self.cli_set(ddns + ['update-on-renew', 'enable']) + +        self.cli_set(ddns + ['tsig-key', 'domain-lan-updates', 'algorithm', 'sha256']) +        self.cli_set(ddns + ['tsig-key', 'domain-lan-updates', 'secret', 'SXQncyBXZWRuZXNkYXkgbWFoIGR1ZGVzIQ==']) +        self.cli_set(ddns + ['tsig-key', 'reverse-0-168-192', 'algorithm', 'sha256']) +        self.cli_set(ddns + ['tsig-key', 'reverse-0-168-192', 'secret', 'VGhhbmsgR29kIGl0J3MgRnJpZGF5IQ==']) +        self.cli_set(ddns + ['forward-domain', 'domain.lan', 'dns-server', '1', 'address', '192.168.0.1']) +        self.cli_set(ddns + ['forward-domain', 'domain.lan', 'dns-server', '2', 'address', '100.100.0.1']) +        self.cli_set(ddns + ['forward-domain', 'domain.lan', 'key-name', 'domain-lan-updates']) +        self.cli_set(ddns + ['reverse-domain', '0.168.192.in-addr.arpa', 'dns-server', '1', 'address', '192.168.0.1']) +        self.cli_set(ddns + ['reverse-domain', '0.168.192.in-addr.arpa', 'dns-server', '1', 'port', '1053']) +        self.cli_set(ddns + ['reverse-domain', '0.168.192.in-addr.arpa', 'dns-server', '2', 'address', '100.100.0.1']) +        self.cli_set(ddns + ['reverse-domain', '0.168.192.in-addr.arpa', 'dns-server', '2', 'port', '1153']) +        self.cli_set(ddns + ['reverse-domain', '0.168.192.in-addr.arpa', 'key-name', 'reverse-0-168-192']) + +        shared = base_path + ['shared-network-name', shared_net_name] + +        self.cli_set(shared + ['dynamic-dns-update', 'send-updates', 'enable']) +        self.cli_set(shared + ['dynamic-dns-update', 'conflict-resolution', 'enable']) +        self.cli_set(shared + ['dynamic-dns-update', 'ttl-percent', '75']) + +        pool = shared + [ 'subnet', subnet] + +        self.cli_set(pool + ['subnet-id', '1']) + +        self.cli_set(pool + ['range', '0', 'start', range_0_start]) +        self.cli_set(pool + ['range', '0', 'stop', range_0_stop]) + +        self.cli_set(pool + ['dynamic-dns-update', 'send-updates', 'enable']) +        self.cli_set(pool + ['dynamic-dns-update', 'generated-prefix', 'myfunnyprefix']) +        self.cli_set(pool + ['dynamic-dns-update', 'qualifying-suffix', 'suffix.lan']) +        self.cli_set(pool + ['dynamic-dns-update', 'hostname-char-set', 'xXyYzZ']) +        self.cli_set(pool + ['dynamic-dns-update', 'hostname-char-replacement', '_xXx_']) + +        self.cli_commit() + +        config = read_file(KEA4_CONF) +        d2_config = read_file(KEA4_D2_CONF) + +        obj = loads(config) +        d2_obj = loads(d2_config) + +        # Verify global DDNS parameters in the main config file +        self.verify_config_value( +            obj, +            ['Dhcp4'], 'dhcp-ddns', +            {'enable-updates': True, 'server-ip': '127.0.0.1', 'server-port': 53001, 'sender-ip': '', 'sender-port': 0, +                'max-queue-size': 1024, 'ncr-protocol': 'UDP', 'ncr-format': 'JSON'}) + +        self.verify_config_value(obj, ['Dhcp4'], 'ddns-send-updates', True) +        self.verify_config_value(obj, ['Dhcp4'], 'ddns-use-conflict-resolution', True) +        self.verify_config_value(obj, ['Dhcp4'], 'ddns-override-no-update', True) +        self.verify_config_value(obj, ['Dhcp4'], 'ddns-override-client-update', True) +        self.verify_config_value(obj, ['Dhcp4'], 'ddns-replace-client-name', 'always') +        self.verify_config_value(obj, ['Dhcp4'], 'ddns-update-on-renew', True) + +        # Verify scoped DDNS parameters in the main config file +        self.verify_config_value(obj, ['Dhcp4', 'shared-networks'], 'name', shared_net_name) +        self.verify_config_value(obj, ['Dhcp4', 'shared-networks'], 'ddns-send-updates', True) +        self.verify_config_value(obj, ['Dhcp4', 'shared-networks'], 'ddns-use-conflict-resolution', True) +        self.verify_config_value(obj, ['Dhcp4', 'shared-networks'], 'ddns-ttl-percent', 0.75) + +        self.verify_config_value(obj, ['Dhcp4', 'shared-networks', 0, 'subnet4'], 'subnet', subnet) +        self.verify_config_value(obj, ['Dhcp4', 'shared-networks', 0, 'subnet4'], 'id', 1) +        self.verify_config_value(obj, ['Dhcp4', 'shared-networks', 0, 'subnet4'], 'ddns-send-updates', True) +        self.verify_config_value(obj, ['Dhcp4', 'shared-networks', 0, 'subnet4'], 'ddns-generated-prefix', 'myfunnyprefix') +        self.verify_config_value(obj, ['Dhcp4', 'shared-networks', 0, 'subnet4'], 'ddns-qualifying-suffix', 'suffix.lan') +        self.verify_config_value(obj, ['Dhcp4', 'shared-networks', 0, 'subnet4'], 'hostname-char-set', 'xXyYzZ') +        self.verify_config_value(obj, ['Dhcp4', 'shared-networks', 0, 'subnet4'], 'hostname-char-replacement', '_xXx_') + +        # Verify keys and domains configuration in the D2 config +        self.verify_config_object( +            d2_obj, +            ['DhcpDdns', 'tsig-keys'], +            {'name': 'domain-lan-updates', 'algorithm': 'HMAC-SHA256', 'secret': 'SXQncyBXZWRuZXNkYXkgbWFoIGR1ZGVzIQ=='} +        ) +        self.verify_config_object( +            d2_obj, +            ['DhcpDdns', 'tsig-keys'], +            {'name': 'reverse-0-168-192', 'algorithm': 'HMAC-SHA256', 'secret': 'VGhhbmsgR29kIGl0J3MgRnJpZGF5IQ=='} +        ) + +        self.verify_config_value(d2_obj, ['DhcpDdns', 'forward-ddns', 'ddns-domains', 0], 'name', 'domain.lan') +        self.verify_config_value(d2_obj, ['DhcpDdns', 'forward-ddns', 'ddns-domains', 0], 'key-name', 'domain-lan-updates') +        self.verify_config_object( +            d2_obj, +            ['DhcpDdns', 'forward-ddns', 'ddns-domains', 0, 'dns-servers'], +            {'ip-address': '192.168.0.1'} +            ) +        self.verify_config_object( +            d2_obj, +            ['DhcpDdns', 'forward-ddns', 'ddns-domains', 0, 'dns-servers'], +            {'ip-address': '100.100.0.1'} +            ) + +        self.verify_config_value(d2_obj, ['DhcpDdns', 'reverse-ddns', 'ddns-domains', 0], 'name', '0.168.192.in-addr.arpa') +        self.verify_config_value(d2_obj, ['DhcpDdns', 'reverse-ddns', 'ddns-domains', 0], 'key-name', 'reverse-0-168-192') +        self.verify_config_object( +            d2_obj, +            ['DhcpDdns', 'reverse-ddns', 'ddns-domains', 0, 'dns-servers'], +            {'ip-address': '192.168.0.1', 'port': 1053} +            ) +        self.verify_config_object( +            d2_obj, +            ['DhcpDdns', 'reverse-ddns', 'ddns-domains', 0, 'dns-servers'], +            {'ip-address': '100.100.0.1', 'port': 1153} +            ) + +        # Check for running process +        self.assertTrue(process_named_running(PROCESS_NAME)) +        self.assertTrue(process_named_running(D2_PROCESS_NAME)) +      def test_dhcp_on_interface_with_vrf(self):          self.cli_set(['interfaces', 'ethernet', 'eth1', 'address', '10.1.1.1/30'])          self.cli_set(['interfaces', 'ethernet', 'eth1', 'vrf', 'SMOKE-DHCP']) diff --git a/smoketest/scripts/cli/test_service_dhcpv6-relay.py b/smoketest/scripts/cli/test_service_dhcpv6-relay.py index e634a011f..da826615d 100755 --- a/smoketest/scripts/cli/test_service_dhcpv6-relay.py +++ b/smoketest/scripts/cli/test_service_dhcpv6-relay.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_service_dhcpv6-server.py b/smoketest/scripts/cli/test_service_dhcpv6-server.py index 6535ca72d..ab4604165 100755 --- a/smoketest/scripts/cli/test_service_dhcpv6-server.py +++ b/smoketest/scripts/cli/test_service_dhcpv6-server.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2023 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_service_dns_dynamic.py b/smoketest/scripts/cli/test_service_dns_dynamic.py index 522102e67..61141762d 100755 --- a/smoketest/scripts/cli/test_service_dns_dynamic.py +++ b/smoketest/scripts/cli/test_service_dns_dynamic.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2019-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_service_dns_forwarding.py b/smoketest/scripts/cli/test_service_dns_forwarding.py index 9a3f4933e..995f5cb25 100755 --- a/smoketest/scripts/cli/test_service_dns_forwarding.py +++ b/smoketest/scripts/cli/test_service_dns_forwarding.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2019-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_service_https.py b/smoketest/scripts/cli/test_service_https.py index 04c4a2e51..df7657685 100755 --- a/smoketest/scripts/cli/test_service_https.py +++ b/smoketest/scripts/cli/test_service_https.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2019-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -16,6 +16,7 @@  import unittest  import json +import psutil  from requests import request  from urllib3.exceptions import InsecureRequestWarning @@ -113,6 +114,29 @@ class TestHTTPSService(VyOSUnitTestSHIM.TestCase):          # Check for stopped  process          self.assertFalse(process_named_running(PROCESS_NAME)) +    def test_listen_address(self): +        test_prefix = ['192.0.2.1/26', '2001:db8:1::ffff/64'] +        test_addr = [ i.split('/')[0] for i in test_prefix ] +        for i, addr in enumerate(test_prefix): +            self.cli_set(['interfaces', 'dummy', f'dum{i}', 'address', addr]) + +        key = 'MySuperSecretVyOS' +        self.cli_set(base_path + ['api', 'keys', 'id', 'key-01', 'key', key]) +        # commit base config first, for testing update of listen-address +        self.cli_commit() + +        for addr in test_addr: +            self.cli_set(base_path + ['listen-address', addr]) +        self.cli_commit() + +        res = set() +        t = psutil.net_connections(kind="tcp") +        for c in t: +            if c.laddr.port == 443: +                res.add(c.laddr.ip) + +        self.assertEqual(res, set(test_addr)) +      def test_certificate(self):          cert_name = 'test_https'          dh_name = 'dh-test' diff --git a/smoketest/scripts/cli/test_service_ipoe-server.py b/smoketest/scripts/cli/test_service_ipoe-server.py index 3b3c205cd..3943d686a 100755 --- a/smoketest/scripts/cli/test_service_ipoe-server.py +++ b/smoketest/scripts/cli/test_service_ipoe-server.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2022-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_service_lldp.py b/smoketest/scripts/cli/test_service_lldp.py index c73707e0d..6566bdb39 100755 --- a/smoketest/scripts/cli/test_service_lldp.py +++ b/smoketest/scripts/cli/test_service_lldp.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2022-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_service_mdns_repeater.py b/smoketest/scripts/cli/test_service_mdns_repeater.py index 30e48683f..47b8e4dc5 100755 --- a/smoketest/scripts/cli/test_service_mdns_repeater.py +++ b/smoketest/scripts/cli/test_service_mdns_repeater.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2023 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_service_monitoring_network_event.py b/smoketest/scripts/cli/test_service_monitoring_network_event.py index 3c9b4bf7f..0bd4b93a6 100644 --- a/smoketest/scripts/cli/test_service_monitoring_network_event.py +++ b/smoketest/scripts/cli/test_service_monitoring_network_event.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_service_monitoring_prometheus.py b/smoketest/scripts/cli/test_service_monitoring_prometheus.py index 6e7f8c808..328c8d6b2 100755 --- a/smoketest/scripts/cli/test_service_monitoring_prometheus.py +++ b/smoketest/scripts/cli/test_service_monitoring_prometheus.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_service_monitoring_telegraf.py b/smoketest/scripts/cli/test_service_monitoring_telegraf.py index 886b88683..05a2103b2 100755 --- a/smoketest/scripts/cli/test_service_monitoring_telegraf.py +++ b/smoketest/scripts/cli/test_service_monitoring_telegraf.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_service_monitoring_zabbix-agent.py b/smoketest/scripts/cli/test_service_monitoring_zabbix-agent.py index 522f9df0f..1b2d37f1f 100755 --- a/smoketest/scripts/cli/test_service_monitoring_zabbix-agent.py +++ b/smoketest/scripts/cli/test_service_monitoring_zabbix-agent.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2023-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_service_ndp-proxy.py b/smoketest/scripts/cli/test_service_ndp-proxy.py index dfdb3f6aa..1e66fc331 100755 --- a/smoketest/scripts/cli/test_service_ndp-proxy.py +++ b/smoketest/scripts/cli/test_service_ndp-proxy.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2023-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_service_ntp.py b/smoketest/scripts/cli/test_service_ntp.py index 469d44eaa..a84b9cec8 100755 --- a/smoketest/scripts/cli/test_service_ntp.py +++ b/smoketest/scripts/cli/test_service_ntp.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2019-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_service_pppoe-server.py b/smoketest/scripts/cli/test_service_pppoe-server.py index 8cd87e0f2..7a43acfca 100755 --- a/smoketest/scripts/cli/test_service_pppoe-server.py +++ b/smoketest/scripts/cli/test_service_pppoe-server.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2022-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_service_router-advert.py b/smoketest/scripts/cli/test_service_router-advert.py index 6dbb6add4..56e05c317 100755 --- a/smoketest/scripts/cli/test_service_router-advert.py +++ b/smoketest/scripts/cli/test_service_router-advert.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2019-2022 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -252,6 +252,118 @@ class TestServiceRADVD(VyOSUnitTestSHIM.TestCase):          tmp = get_config_value('AdvIntervalOpt')          self.assertEqual(tmp, 'off') +    def test_auto_ignore(self): +        isp_prefix = '2001:db8::/64' +        ula_prefixes = ['fd00::/64', 'fd01::/64'] + +        # configure wildcard prefix +        self.cli_set(base_path + ['prefix', '::/64']) + +        # test auto-ignore CLI behaviors with no prefix overrides +        # set auto-ignore for all three prefixes +        self.cli_set(base_path + ['auto-ignore', isp_prefix]) + +        for ula_prefix in ula_prefixes: +            self.cli_set(base_path + ['auto-ignore', ula_prefix]) +         +        # commit and reload config +        self.cli_commit() +        config = read_file(RADVD_CONF) + +        # ensure autoignoreprefixes block is generated in config file +        tmp = f'autoignoreprefixes' + ' {' +        self.assertIn(tmp, config) + +        # ensure all three prefixes are contained in the block +        self.assertIn(f'        {isp_prefix};', config) +        for ula_prefix in ula_prefixes: +            self.assertIn(f'        {ula_prefix};', config) +         +        # remove a prefix and verify it's gone +        self.cli_delete(base_path + ['auto-ignore', ula_prefixes[1]]) +         +        # commit and reload config +        self.cli_commit() +        config = read_file(RADVD_CONF) + +        self.assertNotIn(f'        {ula_prefixes[1]};', config) + +        # ensure remaining two prefixes are still present +        self.assertIn(f'        {ula_prefixes[0]};', config) +        self.assertIn(f'        {isp_prefix};', config) + +        # remove the remaining two prefixes and verify the config block is gone +        self.cli_delete(base_path + ['auto-ignore', ula_prefixes[0]]) +        self.cli_delete(base_path + ['auto-ignore', isp_prefix]) + +        # commit and reload config +        self.cli_commit() +        config = read_file(RADVD_CONF) + +        tmp = f'autoignoreprefixes' + ' {' +        self.assertNotIn(tmp, config) + +        # test wildcard prefix overrides, with and without auto-ignore CLI configuration +        newline = '\n' +        left_curly = '{' +        right_curly = '}' + +        # override ULA prefixes +        for ula_prefix in ula_prefixes: +            self.cli_set(base_path + ['prefix', ula_prefix]) + +        # commit and reload config +        self.cli_commit() +        config = read_file(RADVD_CONF) + +        # ensure autoignoreprefixes block is generated in config file with both prefixes +        tmp = f'autoignoreprefixes' + f' {left_curly}{newline}        {ula_prefixes[0]};{newline}        {ula_prefixes[1]};{newline}    {right_curly};' +        self.assertIn(tmp, config) + +        # remove a ULA prefix and ensure there is only one prefix in the config block +        self.cli_delete(base_path + ['prefix', ula_prefixes[0]]) + +        # commit and reload config +        self.cli_commit() +        config = read_file(RADVD_CONF) + +        # ensure autoignoreprefixes block is generated in config file with only one prefix +        tmp = f'autoignoreprefixes' + f' {left_curly}{newline}        {ula_prefixes[1]};{newline}    {right_curly};' +        self.assertIn(tmp, config) + +        # exclude a prefix with auto-ignore CLI syntax +        self.cli_set(base_path + ['auto-ignore', ula_prefixes[0]]) + +        # commit and reload config +        self.cli_commit() +        config = read_file(RADVD_CONF) + +        # verify that both prefixes appear in config block once again +        tmp = f'autoignoreprefixes' + f' {left_curly}{newline}        {ula_prefixes[0]};{newline}        {ula_prefixes[1]};{newline}    {right_curly};' +        self.assertIn(tmp, config) + +        # override first ULA prefix again +        # first ULA is auto-ignored in CLI, it must appear only once in config +        self.cli_set(base_path + ['prefix', ula_prefixes[0]]) + +        # commit and reload config +        self.cli_commit() +        config = read_file(RADVD_CONF) + +        # verify that both prefixes appear uniquely +        tmp = f'autoignoreprefixes' + f' {left_curly}{newline}        {ula_prefixes[0]};{newline}        {ula_prefixes[1]};{newline}    {right_curly};' +        self.assertIn(tmp, config) + +        # remove wildcard prefix and verify config block is gone +        self.cli_delete(base_path + ['prefix', '::/64']) + +        # commit and reload config +        self.cli_commit() +        config = read_file(RADVD_CONF) + +        # verify config block is gone +        tmp = f'autoignoreprefixes' + ' {' +        self.assertNotIn(tmp, config)  if __name__ == '__main__':      unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_service_salt-minion.py b/smoketest/scripts/cli/test_service_salt-minion.py index 48a588b72..1ad1333f0 100755 --- a/smoketest/scripts/cli/test_service_salt-minion.py +++ b/smoketest/scripts/cli/test_service_salt-minion.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2022-2023 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_service_snmp.py b/smoketest/scripts/cli/test_service_snmp.py index 7d5eaa440..d2221908c 100755 --- a/smoketest/scripts/cli/test_service_snmp.py +++ b/smoketest/scripts/cli/test_service_snmp.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2019-2021 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_service_ssh.py b/smoketest/scripts/cli/test_service_ssh.py index fa08a5b32..32bc3cc89 100755 --- a/smoketest/scripts/cli/test_service_ssh.py +++ b/smoketest/scripts/cli/test_service_ssh.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2019-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -24,10 +24,12 @@ from pwd import getpwall  from base_vyostest_shim import VyOSUnitTestSHIM  from vyos.configsession import ConfigSessionError +from vyos.defaults import config_files  from vyos.utils.process import cmd  from vyos.utils.process import is_systemd_service_running  from vyos.utils.process import process_named_running  from vyos.utils.file import read_file +from vyos.utils.file import write_file  from vyos.xml_ref import default_value  PROCESS_NAME = 'sshd' @@ -38,26 +40,101 @@ pki_path = ['pki']  key_rsa = '/etc/ssh/ssh_host_rsa_key'  key_dsa = '/etc/ssh/ssh_host_dsa_key'  key_ed25519 = '/etc/ssh/ssh_host_ed25519_key' -trusted_user_ca_key = '/etc/ssh/trusted_user_ca_key' - +trusted_user_ca = config_files['sshd_user_ca'] +test_command = 'uname -a'  def get_config_value(key):      tmp = read_file(SSHD_CONF)      tmp = re.findall(f'\n?{key}\s+(.*)', tmp)      return tmp +trusted_user_ca_path = base_path + ['trusted-user-ca'] +# CA and signed user key generated using: +# ssh-keygen -f vyos-ssh-ca.key +# ssh-keygen -f vyos_testca  -C "vyos_tesca@vyos.net" +# ssh-keygen -s vyos-ssh-ca.key -I vyos_testca@vyos.net -n vyos,vyos_testca -V +520w vyos_testca.pub +ca_cert_data = """ +AAAAB3NzaC1yc2EAAAADAQABAAABgQCTBa7+TTefsMLTHuuLPUmmm7SGAuoK03oZEIi2/O +sww1uhCdKrm7bFvSUFpWvq3gX8TSS+yO5kNKz3BTMBu7oq01/Ewjyw0jR+fUog76x7mCzd +2iI4QmPj4lNHSUFquaELt2aBwY4f7LtjxRCCgtWgirq/Qk+P27uJKErvndyYc95v9no15z +lQFSdUid6tF8IjYljK8pXP0JshFp3XnFV2Rg80j7O66mRtVFC4tt2vluyIFeIID+5fL03v +LXbT/2zNdoH6QiI9NGWkxhS7zFYziVd/rzG5xlEB1ezs2Sz4zjMPgV3GiMINb6tjEWNJhM +KtDWIt+3UDpx+2T9PrhDBDFMlneiHCD6MxRv2sLbicevSj0PV7/fRnwoHs6hDKCU5eS2Mc +CTxXr4jaboLZ6q3sbGHCHZo/PuA8Sl9iZCM4GCxx5bgvRRmGpgZv4PfFzA2b/wTHkKnf6E +kuthoAJufmNxPaZQRQKF34SdmTKgSJTCY1gqwCH2iNg0PVKU+vN8c= +""" -ca_root_cert_data = """ -MIIBcTCCARagAwIBAgIUDcAf1oIQV+6WRaW7NPcSnECQ/lUwCgYIKoZIzj0EAwIw -HjEcMBoGA1UEAwwTVnlPUyBzZXJ2ZXIgcm9vdCBDQTAeFw0yMjAyMTcxOTQxMjBa -Fw0zMjAyMTUxOTQxMjBaMB4xHDAaBgNVBAMME1Z5T1Mgc2VydmVyIHJvb3QgQ0Ew -WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ0y24GzKQf4aM2Ir12tI9yITOIzAUj -ZXyJeCmYI6uAnyAMqc4Q4NKyfq3nBi4XP87cs1jlC1P2BZ8MsjL5MdGWozIwMDAP -BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRwC/YaieMEnjhYa7K3Flw/o0SFuzAK -BggqhkjOPQQDAgNJADBGAiEAh3qEj8vScsjAdBy5shXzXDVVOKWCPTdGrPKnu8UW -a2cCIQDlDgkzWmn5ujc5ATKz1fj+Se/aeqwh4QyoWCVTFLIxhQ== +cert_user_key = """-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn +NhAAAAAwEAAQAAAYEArnIlFpMwSQax7+qH3+/gbv65mem6Ur+gepNYC8TYaE91xJxMoE5M +Pyh1s8Kr/WYNF6aN43qdDnjvGy38oFng4lEfxG475AqpTIGmP4GvEOlnNLhjCcOHrOFuzg +uRtDDvn0/TPhdqLTlbvgZ326WO7xQkCX11qmdGUUtC9Byd7p+EmnTe0oP8N6MeyYY78qa4 +HnzMd6EPb3vyWdASpPZjQE0OJCeAx6Mne2kOnKxUcW1UlczOa1PPIQMU+Rp1PWDtkdiYAd +nbTbIdxDN8Bn3mC3JXD642EcwXSJ1+kov/8u8bBuYNt3t3nf/krSebx4Ge7ObYnURj31j0 +8L8Vv3fgv+T7pY8iyMh8dYfrZPAWQGN1pe8ZkDaM1QGKJncF+8N0UB4EVFBHNLt7W8+oHt +LPMqYw13djZHg5Q1NxSxc1srOmEBZrWCBZgDGGiqtKo+lF+oVvqvBh/hncOBlDX5RFM8qw +Qt4mem9TEZZrIvC9q1dcVpQUrt8BvBOSnGnBb7yTAAAFkEdBIUlHQSFJAAAAB3NzaC1yc2 +EAAAGBAK5yJRaTMEkGse/qh9/v4G7+uZnpulK/oHqTWAvE2GhPdcScTKBOTD8odbPCq/1m +DRemjeN6nQ547xst/KBZ4OJRH8RuO+QKqUyBpj+BrxDpZzS4YwnDh6zhbs4LkbQw759P0z +4Xai05W74Gd9ulju8UJAl9dapnRlFLQvQcne6fhJp03tKD/DejHsmGO/KmuB58zHehD297 +8lnQEqT2Y0BNDiQngMejJ3tpDpysVHFtVJXMzmtTzyEDFPkadT1g7ZHYmAHZ202yHcQzfA +Z95gtyVw+uNhHMF0idfpKL//LvGwbmDbd7d53/5K0nm8eBnuzm2J1EY99Y9PC/Fb934L/k ++6WPIsjIfHWH62TwFkBjdaXvGZA2jNUBiiZ3BfvDdFAeBFRQRzS7e1vPqB7SzzKmMNd3Y2 +R4OUNTcUsXNbKzphAWa1ggWYAxhoqrSqPpRfqFb6rwYf4Z3DgZQ1+URTPKsELeJnpvUxGW +ayLwvatXXFaUFK7fAbwTkpxpwW+8kwAAAAMBAAEAAAGAEeZQe+0vyoPPWkjRwbQBbszgX9 +9QaRE/TD82N5mZLbWJkK+2WnSY9O9tNGbIncBiSNz5ji/p/FmDCgzr8SAyfRvJ4K6sTTfy +1eYvwtscYDsy2ywDAuDMrnvrPLqJ1tghSP2N4BR9ppT4yZosTkjB+TIzMxjBLB0GEBgNj1 +19rxswe2YmlFSgBVgi3pbRgT0uLfgBmvzXHUoLPL/8ScT7u4Csmh/GN7Xmuo5gcMnArcAu +1Q17g3PJZcpv1Ser2VfKnVAwrURCLW8dlji5xat/3E/PLsrLvszVS6U0hFf3MaOixprxsz +wc0n2Y4lAgkgkCZQ0Ty9TSXI/8TQWL8cPFej1TK15NWXlfElZxI+lhwcsnWmNy3mXD746/ +YZLH+OCs9isvewZWryQEkdVCU42MM/7L4Hoeqh2diGDV9wtKDW5FjHq/VRNOMVt59eCFlv +eujh89/KY6wPxHoDoY3+olhggiKDGw1wUUpEXKNQhhTjx1g0xn7AFYz+Bp2svM9EdhAAAA +wQDBq+zeOhsS/VrrVRkmOYYXnBSe0WcckjcYOly/8FLTPkq19aVY5eOmo6teegqvkWscGP +Wisl7DW+kFNolIvwc6shf/8+PXC1KlADd9S1uoXvSmVoe3wSsIKRCsUuLZiiJkv4nqQ/BK +T6ijvNG2Wu3YGsP8Tj+OcTebqk1vDItaickhKtFxCx6PBcV+RrDeK1TT6uAHd1AsGikTva +V/BDMmtoDz7qFQbj9Vj2np88MakxYfm7u4DzKu082GHDBC44sAAADBAN8ATvmmfxqk5GFg ++2rbIW+qMJ2GwWXiTFLjH7u4HEhsmHbHYsQ0v+cGu2dKfBUVWoq/N2ltDQ0QYTgkmsxKvm +I8AjVhLHhFB1DtPBMHibsF/rtBRgsItR+PveUtRYOmeY1PzJ3ygVNJpPJ87st0T4JVNQiE ++bFEhnJ/RcTHxzAAt8+gTn0PTen3+hn9Jk2YFHWFb51YDw2h00LL9XT9Enz4xkc6gTPL3M +0IKULJWnyYGOLueSsQxJiaAUcsZg8W2QAAAMEAyEJ45HtbUqZ5xd2K5ZfY8cd1dC9uAx6a +cSdENUvMW4yE3QEJ4xdonDUn9OQYR7GpseQWuXBrTO2PSsse7P6eHUsRhaUkFOvLzHSVzO +bI9HDJAq6+KCPhm2eixfBiMs2meEle8MvNiiONwaY3JnPnGdsTpEjcm6oulyC52xRvHhvc +nCuoRTqX7xcIka4jCXInYBS7GhlF5iAmIAAVkvfWjjNwZ3S0mnGUUOYgknidBhK+x0zCWt +IXOeoIfjb/C4NLAAAAE3Z5b3NfdGVzY2FAdnlvcy5uZXQBAgMEBQYH +-----END OPENSSH PRIVATE KEY-----  """ +cert_user_signed = """ +ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb2 +0AAAAglE+kjRPqsck/y2ywO+owv1FTeU6QFNPywFqD8aoEcA8AAAADAQABAAABgQCuciUWk +zBJBrHv6off7+Bu/rmZ6bpSv6B6k1gLxNhoT3XEnEygTkw/KHWzwqv9Zg0Xpo3jep0OeO8b +LfygWeDiUR/EbjvkCqlMgaY/ga8Q6Wc0uGMJw4es4W7OC5G0MO+fT9M+F2otOVu+BnfbpY7 +vFCQJfXWqZ0ZRS0L0HJ3un4SadN7Sg/w3ox7JhjvyprgefMx3oQ9ve/JZ0BKk9mNATQ4kJ4 +DHoyd7aQ6crFRxbVSVzM5rU88hAxT5GnU9YO2R2JgB2dtNsh3EM3wGfeYLclcPrjYRzBdIn +X6Si//y7xsG5g23e3ed/+StJ5vHgZ7s5tidRGPfWPTwvxW/d+C/5PuljyLIyHx1h+tk8BZA +Y3Wl7xmQNozVAYomdwX7w3RQHgRUUEc0u3tbz6ge0s8ypjDXd2NkeDlDU3FLFzWys6YQFmt +YIFmAMYaKq0qj6UX6hW+q8GH+Gdw4GUNflEUzyrBC3iZ6b1MRlmsi8L2rV1xWlBSu3wG8E5 +KcacFvvJMAAAAAAAAAAAAAAAEAAAAUdnlvc190ZXN0Y2FAdnlvcy5uZXQAAAAXAAAABHZ5b +3MAAAALdnlvc190ZXN0Y2EAAAAAaDg66AAAAAB69w9WAAAAAAAAAIIAAAAVcGVybWl0LVgx +MS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGV +ybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LX +VzZXItcmMAAAAAAAAAAAAAAZcAAAAHc3NoLXJzYQAAAAMBAAEAAAGBAJMFrv5NN5+wwtMe6 +4s9SaabtIYC6grTehkQiLb86zDDW6EJ0qubtsW9JQWla+reBfxNJL7I7mQ0rPcFMwG7uirT +X8TCPLDSNH59SiDvrHuYLN3aIjhCY+PiU0dJQWq5oQu3ZoHBjh/su2PFEIKC1aCKur9CT4/ +bu4koSu+d3Jhz3m/2ejXnOVAVJ1SJ3q0XwiNiWMrylc/QmyEWndecVXZGDzSPs7rqZG1UUL +i23a+W7IgV4ggP7l8vTe8tdtP/bM12gfpCIj00ZaTGFLvMVjOJV3+vMbnGUQHV7OzZLPjOM +w+BXcaIwg1vq2MRY0mEwq0NYi37dQOnH7ZP0+uEMEMUyWd6IcIPozFG/awtuJx69KPQ9Xv9 +9GfCgezqEMoJTl5LYxwJPFeviNpugtnqrexsYcIdmj8+4DxKX2JkIzgYLHHluC9FGYamBm/ +g98XMDZv/BMeQqd/oSS62GgAm5+Y3E9plBFAoXfhJ2ZMqBIlMJjWCrAIfaI2DQ9UpT683xw +AAAZQAAAAMcnNhLXNoYTItNTEyAAABgINZAr9M9ZYWDhhf5uWNkUBKq12OlJ3ImvHg5161P +BAAL6crGS3WzyAs9LerxFcdMJ0gzMgUixR59MgGMAzfN+DjoSmgcLVT0eVoI5GMBkdiq8T5 +h3qjeXTc5BfLJiACbu7tOPhuIsIDreDnCVYmGr2z+rAPaqMETJa4L0submx4DqnahSY0ZSH +WjTrjWCSPIdySh9HUXbpq3tYdNlqmpSY5YzvDmMC46kGMF10G5ycc58asWfUMwLMGsTEt2t +R5DKRDw/iJch3r+L0xLMCSmEXnu6/Gl7Yq1XJdWm9cA1SvDyxEuB4yKIDkunXrPiuPn3zyv +z1a/bY0hvuF+fyL+tRCbmrfOLreHuYh9aFg6e22MoKhrez5wP8Eoy1T+rlQrmlgCRDShBgj +wMMhc+2fdrzTR07Ctnmv339p/SY5wBruzNM9R1mzyEuuJDE6OkKBTI8kuQu6ypGv+bLqSSt +wujcNqOI4Vz61HiOsRSTUa7tA5q4hBwFqq7FB8+N0Ylfa5A== vyos_tesca@vyos.net +"""  class TestServiceSSH(VyOSUnitTestSHIM.TestCase):      @classmethod @@ -207,23 +284,12 @@ class TestServiceSSH(VyOSUnitTestSHIM.TestCase):          # run natively.          #          # We also try to login as an invalid user - this is not allowed to work. -          test_user = 'ssh_test'          test_pass = 'v2i57DZs8idUwMN3VC92' -        test_command = 'uname -a'          self.cli_set(base_path) -        self.cli_set( -            [ -                'system', -                'login', -                'user', -                test_user, -                'authentication', -                'plaintext-password', -                test_pass, -            ] -        ) +        self.cli_set(['system', 'login', 'user', test_user, 'authentication', +                      'plaintext-password', test_pass])          # commit changes          self.cli_commit() @@ -236,9 +302,8 @@ class TestServiceSSH(VyOSUnitTestSHIM.TestCase):          # Login with invalid credentials          with self.assertRaises(paramiko.ssh_exception.AuthenticationException): -            output, error = self.ssh_send_cmd( -                test_command, 'invalid_user', 'invalid_password' -            ) +            output, error = self.ssh_send_cmd(test_command, 'invalid_user', +                                              'invalid_password')          self.cli_delete(['system', 'login', 'user', test_user])          self.cli_commit() @@ -359,40 +424,74 @@ class TestServiceSSH(VyOSUnitTestSHIM.TestCase):          tmp_sshd_conf = read_file(SSHD_CONF)          self.assertIn(expected, tmp_sshd_conf) -    def test_ssh_trusted_user_ca_key(self): +    def test_ssh_trusted_user_ca(self):          ca_cert_name = 'test_ca' +        public_key_type = 'ssh-rsa' +        public_key_data = ca_cert_data.replace('\n', '') +        test_user = 'vyos_testca' +        principal = 'vyos' +        user_auth_base = ['system', 'login', 'user', test_user] + +        # create user account +        self.cli_set(user_auth_base) +        self.cli_set(pki_path + ['openssh', ca_cert_name, 'public', +                                 'key', public_key_data]) +        self.cli_set(pki_path + ['openssh', ca_cert_name, 'public', +                                 'type', public_key_type]) +        self.cli_set(trusted_user_ca_path, value=ca_cert_name) +        self.cli_commit() + +        trusted_user_ca_config = get_config_value('TrustedUserCAKeys') +        self.assertIn(trusted_user_ca, trusted_user_ca_config) + +        authorize_principals_file_config = get_config_value('AuthorizedPrincipalsFile') +        self.assertIn('none', authorize_principals_file_config) + +        ca_key_contents = read_file(trusted_user_ca).lstrip().rstrip() +        self.assertIn(f'{public_key_type} {public_key_data}', ca_key_contents) -        # set pki ca <ca_cert_name> certificate <ca_key_data> -        # set service ssh trusted-user-ca-key ca-certificate <ca_cert_name> -        self.cli_set( -            pki_path -            + [ -                'ca', -                ca_cert_name, -                'certificate', -                ca_root_cert_data.replace('\n', ''), -            ] -        ) -        self.cli_set( -            base_path + ['trusted-user-ca-key', 'ca-certificate', ca_cert_name] -        ) +        # Verify functionality by logging into the system using signed user key +        key_filename = f'/tmp/{test_user}' +        write_file(key_filename, cert_user_key, mode=0o600) +        write_file(f'{key_filename}-cert.pub', cert_user_signed.replace('\n', '')) + +        # Login with proper credentials +        output, error = self.ssh_send_cmd(test_command, test_user, password=None, +                                          key_filename=key_filename) +        # Verify login +        self.assertFalse(error) +        self.assertEqual(output, cmd(test_command)) + +        # Enable user principal name - logins only allowed if certificate contains +        # said principal name +        self.cli_set(user_auth_base + ['authentication', 'principal', principal])          self.cli_commit() -        trusted_user_ca_key_config = get_config_value('TrustedUserCAKeys') -        self.assertIn(trusted_user_ca_key, trusted_user_ca_key_config) +        # Verify generated SSH principals +        authorized_principals_file = f'/home/{test_user}/.ssh/authorized_principals' +        authorized_principals = read_file(authorized_principals_file, sudo=True) +        self.assertIn(principal, authorized_principals) -        with open(trusted_user_ca_key, 'r') as file: -            ca_key_contents = file.read() -        self.assertIn(ca_root_cert_data, ca_key_contents) +        # Login with proper credentials +        output, error = self.ssh_send_cmd(test_command, test_user, password=None, +                                          key_filename=key_filename) +        # Verify login +        self.assertFalse(error) +        self.assertEqual(output, cmd(test_command)) -        self.cli_delete(base_path + ['trusted-user-ca-key']) +        self.cli_delete(trusted_user_ca_path) +        self.cli_delete(user_auth_base)          self.cli_delete(['pki', 'ca', ca_cert_name])          self.cli_commit()          # Verify the CA key is removed -        trusted_user_ca_key_config = get_config_value('TrustedUserCAKeys') -        self.assertNotIn(trusted_user_ca_key, trusted_user_ca_key_config) +        trusted_user_ca_config = get_config_value('TrustedUserCAKeys') +        self.assertNotIn(trusted_user_ca, trusted_user_ca_config) +        self.assertFalse(os.path.exists(trusted_user_ca)) +        authorize_principals_file_config = get_config_value('AuthorizedPrincipalsFile') +        self.assertNotIn('none', authorize_principals_file_config) +        self.assertFalse(os.path.exists(f'/home/{test_user}/.ssh/authorized_principals'))  if __name__ == '__main__':      unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_service_stunnel.py b/smoketest/scripts/cli/test_service_stunnel.py index 3aeffd09e..4bae79865 100755 --- a/smoketest/scripts/cli/test_service_stunnel.py +++ b/smoketest/scripts/cli/test_service_stunnel.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_service_tftp-server.py b/smoketest/scripts/cli/test_service_tftp-server.py index d60794980..e3f1e25e4 100755 --- a/smoketest/scripts/cli/test_service_tftp-server.py +++ b/smoketest/scripts/cli/test_service_tftp-server.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2019-2023 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_service_webproxy.py b/smoketest/scripts/cli/test_service_webproxy.py index ab4707a61..431f1c885 100755 --- a/smoketest/scripts/cli/test_service_webproxy.py +++ b/smoketest/scripts/cli/test_service_webproxy.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_system_acceleration_qat.py b/smoketest/scripts/cli/test_system_acceleration_qat.py index 9e60bb211..9b8ecef7f 100755 --- a/smoketest/scripts/cli/test_system_acceleration_qat.py +++ b/smoketest/scripts/cli/test_system_acceleration_qat.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2021 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_system_conntrack.py b/smoketest/scripts/cli/test_system_conntrack.py index 72deb7525..75fabdf7a 100755 --- a/smoketest/scripts/cli/test_system_conntrack.py +++ b/smoketest/scripts/cli/test_system_conntrack.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -20,7 +20,10 @@ import unittest  from base_vyostest_shim import VyOSUnitTestSHIM  from vyos.firewall import find_nftables_rule -from vyos.utils.file import read_file, read_json +from vyos.utils.file import read_file +from vyos.utils.file import read_json +from vyos.utils.system import sysctl_read +from vyos.xml_ref import default_value  base_path = ['system', 'conntrack'] @@ -168,8 +171,8 @@ class TestSystemConntrack(VyOSUnitTestSHIM.TestCase):                      self.assertTrue(find_nftables_rule('ip vyos_conntrack', 'VYOS_CT_HELPER', [rule]) == None)      def test_conntrack_hash_size(self): -        hash_size = '65536' -        hash_size_default = '32768' +        hash_size = '8192' +        hash_size_default = default_value(base_path + ['hash-size'])          self.cli_set(base_path + ['hash-size', hash_size]) @@ -178,7 +181,7 @@ class TestSystemConntrack(VyOSUnitTestSHIM.TestCase):          # verify new configuration - only effective after reboot, but          # a valid config file is sufficient -        tmp = read_file('/etc/modprobe.d/vyatta_nf_conntrack.conf') +        tmp = sysctl_read('net.netfilter.nf_conntrack_buckets')          self.assertIn(hash_size, tmp)          # Test default value by deleting the configuration @@ -189,12 +192,14 @@ class TestSystemConntrack(VyOSUnitTestSHIM.TestCase):          # verify new configuration - only effective after reboot, but          # a valid config file is sufficient -        tmp = read_file('/etc/modprobe.d/vyatta_nf_conntrack.conf') +        tmp = sysctl_read('net.netfilter.nf_conntrack_buckets')          self.assertIn(hash_size_default, tmp)      def test_conntrack_ignore(self):          address_group = 'conntracktest'          address_group_member = '192.168.0.1' +        port_single = '53' +        ports_multi = '500,4500'          ipv6_address_group = 'conntracktest6'          ipv6_address_group_member = 'dead:beef::1' @@ -211,6 +216,14 @@ class TestSystemConntrack(VyOSUnitTestSHIM.TestCase):          self.cli_set(base_path + ['ignore', 'ipv4', 'rule', '2', 'destination', 'group', 'address-group', address_group])          self.cli_set(base_path + ['ignore', 'ipv4', 'rule', '2', 'protocol', 'all']) +        self.cli_set(base_path + ['ignore', 'ipv4', 'rule', '3', 'source', 'address', '192.0.2.1']) +        self.cli_set(base_path + ['ignore', 'ipv4', 'rule', '3', 'destination', 'port', ports_multi]) +        self.cli_set(base_path + ['ignore', 'ipv4', 'rule', '3', 'protocol', 'udp']) + +        self.cli_set(base_path + ['ignore', 'ipv4', 'rule', '4', 'source', 'address', '192.0.2.1']) +        self.cli_set(base_path + ['ignore', 'ipv4', 'rule', '4', 'destination', 'port', port_single]) +        self.cli_set(base_path + ['ignore', 'ipv4', 'rule', '4', 'protocol', 'udp']) +          self.cli_set(base_path + ['ignore', 'ipv6', 'rule', '11', 'source', 'address', 'fe80::1'])          self.cli_set(base_path + ['ignore', 'ipv6', 'rule', '11', 'destination', 'address', 'fe80::2'])          self.cli_set(base_path + ['ignore', 'ipv6', 'rule', '11', 'destination', 'port', '22']) @@ -226,7 +239,9 @@ class TestSystemConntrack(VyOSUnitTestSHIM.TestCase):          nftables_search = [              ['ip saddr 192.0.2.1', 'ip daddr 192.0.2.2', 'tcp dport 22', 'tcp flags & syn == syn', 'notrack'], -            ['ip saddr 192.0.2.1', 'ip daddr @A_conntracktest', 'notrack'] +            ['ip saddr 192.0.2.1', 'ip daddr @A_conntracktest', 'notrack'], +            ['ip saddr 192.0.2.1', 'udp dport { 500, 4500 }', 'notrack'], +            ['ip saddr 192.0.2.1', 'udp dport 53', 'notrack']          ]          nftables6_search = [ diff --git a/smoketest/scripts/cli/test_system_flow-accounting.py b/smoketest/scripts/cli/test_system_flow-accounting.py index 9d7942789..7778c393f 100755 --- a/smoketest/scripts/cli/test_system_flow-accounting.py +++ b/smoketest/scripts/cli/test_system_flow-accounting.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_system_frr.py b/smoketest/scripts/cli/test_system_frr.py index a2ce58bf6..98baca1d3 100755 --- a/smoketest/scripts/cli/test_system_frr.py +++ b/smoketest/scripts/cli/test_system_frr.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2023 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_system_ip.py b/smoketest/scripts/cli/test_system_ip.py index 5b6ef2046..764cd9192 100755 --- a/smoketest/scripts/cli/test_system_ip.py +++ b/smoketest/scripts/cli/test_system_ip.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -128,5 +128,26 @@ class TestSystemIP(VyOSUnitTestSHIM.TestCase):          frrconfig = self.getFRRconfig('', end='')          self.assertNotIn(f'no ip nht resolve-via-default', frrconfig) +    def test_system_ip_import_table(self): +        table_num = '100' +        distance = '200' +        route_map_in = 'foo-map-in' +        self.cli_set(['policy', 'route-map', route_map_in, 'rule', '10', 'action', 'permit']) +        self.cli_set(base_path + ['import-table', table_num, 'distance', distance]) +        self.cli_set(base_path + ['import-table', table_num, 'route-map', route_map_in]) + +        self.cli_commit() +        # Verify CLI config applied to FRR +        frrconfig = self.getFRRconfig('', end='') +        self.assertIn(f'ip import-table {table_num} distance {distance} route-map {route_map_in}', frrconfig) + +        self.cli_delete(['policy', 'route-map', route_map_in]) + +        self.cli_delete(base_path + ['import-table']) +        self.cli_commit() +        # Verify CLI config removed to FRR +        frrconfig = self.getFRRconfig('', end='') +        self.assertNotIn(f'ip import-table {table_num} distance {distance}', frrconfig) +  if __name__ == '__main__':      unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_system_ipv6.py b/smoketest/scripts/cli/test_system_ipv6.py index 26f281bb4..2b4a86a4d 100755 --- a/smoketest/scripts/cli/test_system_ipv6.py +++ b/smoketest/scripts/cli/test_system_ipv6.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_system_login.py b/smoketest/scripts/cli/test_system_login.py index 71dec68d8..9a07505d0 100755 --- a/smoketest/scripts/cli/test_system_login.py +++ b/smoketest/scripts/cli/test_system_login.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2019-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -548,5 +548,34 @@ class TestSystemLogin(VyOSUnitTestSHIM.TestCase):              self.cli_commit()          self.cli_discard() +    def test_pam_nologin(self): +        # Testcase for T7443, test if we can login with a non-privileged user +        # when there are only 5 minutes left until the system reboots +        username = users[0] +        password = f'{username}-pSWd-t3st' + +        self.cli_set(base_path + ['user', username, 'authentication', 'plaintext-password', password]) +        self.cli_commit() + +        # Login with proper credentials +        out, err = self.ssh_send_cmd(ssh_test_command, username, password) +        # verify login +        self.assertFalse(err) +        self.assertEqual(out, self.ssh_test_command_result) + +        # Request system reboot in 5 minutes - this will activate pam_nologin.so +        # and prevent any login - but we have this disabled, so we must be able +        # to login to the router +        self.op_mode(['reboot', 'in', '4']) + +        # verify login +        # Login with proper credentials - after reboot is pending +        out, err = self.ssh_send_cmd(ssh_test_command, username, password) +        self.assertFalse(err) +        self.assertEqual(out, self.ssh_test_command_result) + +        # Cancel pending reboot - we do wan't to preceed with the remaining tests +        self.op_mode(['reboot', 'cancel']) +  if __name__ == '__main__':      unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_system_logs.py b/smoketest/scripts/cli/test_system_logs.py index 17cce5ca1..d951ce43d 100755 --- a/smoketest/scripts/cli/test_system_logs.py +++ b/smoketest/scripts/cli/test_system_logs.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_system_option.py b/smoketest/scripts/cli/test_system_option.py index f3112cf0b..69f053a7f 100755 --- a/smoketest/scripts/cli/test_system_option.py +++ b/smoketest/scripts/cli/test_system_option.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -16,14 +16,18 @@  import os  import unittest +  from base_vyostest_shim import VyOSUnitTestSHIM + +from vyos.configsession import ConfigSessionError +from vyos.utils.cpu import get_cpus  from vyos.utils.file import read_file  from vyos.utils.process import is_systemd_service_active  from vyos.utils.system import sysctl_read +from vyos.system import image  base_path = ['system', 'option'] -  class TestSystemOption(VyOSUnitTestSHIM.TestCase):      def tearDown(self):          self.cli_delete(base_path) @@ -96,6 +100,60 @@ class TestSystemOption(VyOSUnitTestSHIM.TestCase):          self.cli_commit()          self.assertFalse(os.path.exists(ssh_client_opt_file)) +    def test_kernel_options(self): +        amd_pstate_mode = 'active' +        isolate_cpus = '1,2,3' +        nohz_full = '2' +        rcu_no_cbs = '1,2,4-5' +        default_hp_size = '2M' +        hp_size_1g = '1G' +        hp_size_2m = '2M' +        hp_count_1g = '2' +        hp_count_2m = '512' + +        self.cli_set(['system', 'option', 'kernel', 'cpu', 'disable-nmi-watchdog']) +        self.cli_set(['system', 'option', 'kernel', 'cpu', 'isolate-cpus', isolate_cpus]) +        self.cli_set(['system', 'option', 'kernel', 'cpu', 'nohz-full', nohz_full]) +        self.cli_set(['system', 'option', 'kernel', 'cpu', 'rcu-no-cbs', rcu_no_cbs]) +        self.cli_set(['system', 'option', 'kernel', 'disable-hpet']) +        self.cli_set(['system', 'option', 'kernel', 'disable-mce']) +        self.cli_set(['system', 'option', 'kernel', 'disable-mitigations']) +        self.cli_set(['system', 'option', 'kernel', 'disable-power-saving']) +        self.cli_set(['system', 'option', 'kernel', 'disable-softlockup']) +        self.cli_set(['system', 'option', 'kernel', 'memory', 'disable-numa-balancing']) +        self.cli_set(['system', 'option', 'kernel', 'memory', 'default-hugepage-size', default_hp_size]) +        self.cli_set(['system', 'option', 'kernel', 'memory', 'hugepage-size', hp_size_1g, 'hugepage-count', hp_count_1g]) +        self.cli_set(['system', 'option', 'kernel', 'memory', 'hugepage-size', hp_size_2m, 'hugepage-count', hp_count_2m]) +        self.cli_set(['system', 'option', 'kernel', 'quiet']) + +        self.cli_set(['system', 'option', 'kernel', 'amd-pstate-driver', amd_pstate_mode]) +        cpu_vendor = get_cpus()[0]['vendor_id'] +        if cpu_vendor != 'AuthenticAMD': +            with self.assertRaises(ConfigSessionError): +                self.cli_commit() +            self.cli_delete(['system', 'option', 'kernel', 'amd-pstate-driver']) + +        self.cli_commit() + +        # Read GRUB config file for current running image +        tmp = read_file(f'{image.grub.GRUB_DIR_VYOS_VERS}/{image.get_running_image()}.cfg') +        self.assertIn(' mitigations=off', tmp) +        self.assertIn(' intel_idle.max_cstate=0 processor.max_cstate=1', tmp) +        self.assertIn(' quiet', tmp) +        self.assertIn(' nmi_watchdog=0', tmp) +        self.assertIn(' hpet=disable', tmp) +        self.assertIn(' mce=off', tmp) +        self.assertIn(' nosoftlockup', tmp) +        self.assertIn(f' isolcpus={isolate_cpus}', tmp) +        self.assertIn(f' nohz_full={nohz_full}', tmp) +        self.assertIn(f' rcu_nocbs={rcu_no_cbs}', tmp) +        self.assertIn(f' default_hugepagesz={default_hp_size}', tmp) +        self.assertIn(f' hugepagesz={hp_size_1g} hugepages={hp_count_1g}', tmp) +        self.assertIn(f' hugepagesz={hp_size_2m} hugepages={hp_count_2m}', tmp) +        self.assertIn(' numa_balancing=disable', tmp) + +        if cpu_vendor == 'AuthenticAMD': +            self.assertIn(f' initcall_blacklist=acpi_cpufreq_init amd_pstate={amd_pstate_mode}', tmp)  if __name__ == '__main__':      unittest.main(verbosity=2) diff --git a/smoketest/scripts/cli/test_system_resolvconf.py b/smoketest/scripts/cli/test_system_resolvconf.py index d8726a301..d91e29230 100755 --- a/smoketest/scripts/cli/test_system_resolvconf.py +++ b/smoketest/scripts/cli/test_system_resolvconf.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2019-2023 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_system_sflow.py b/smoketest/scripts/cli/test_system_sflow.py index 700253e2b..69b35d1f0 100755 --- a/smoketest/scripts/cli/test_system_sflow.py +++ b/smoketest/scripts/cli/test_system_sflow.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2023-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_system_syslog.py b/smoketest/scripts/cli/test_system_syslog.py index 6eae3f19d..c4e043a7c 100755 --- a/smoketest/scripts/cli/test_system_syslog.py +++ b/smoketest/scripts/cli/test_system_syslog.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2019-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -14,6 +14,7 @@  # You should have received a copy of the GNU General Public License  # along with this program.  If not, see <http://www.gnu.org/licenses/>. +import os  import unittest  from base_vyostest_shim import VyOSUnitTestSHIM @@ -59,6 +60,11 @@ class TestRSYSLOGService(VyOSUnitTestSHIM.TestCase):          self.cli_delete(base_path)          self.cli_commit() +        # The default syslog implementation should make syslog.service a +        # symlink to itself +        self.assertEqual(os.readlink('/etc/systemd/system/syslog.service'), +                         '/lib/systemd/system/rsyslog.service') +          # Check for running process          self.assertFalse(process_named_running(PROCESS_NAME)) diff --git a/smoketest/scripts/cli/test_vpn_ipsec.py b/smoketest/scripts/cli/test_vpn_ipsec.py index 91a76e6f6..a0bf30953 100755 --- a/smoketest/scripts/cli/test_vpn_ipsec.py +++ b/smoketest/scripts/cli/test_vpn_ipsec.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -352,6 +352,94 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):          self.tearDownPKI() +    def test_site_to_site_vti_ts_afi(self): +        local_address = '192.0.2.10' +        vti = 'vti10' +        # IKE +        self.cli_set(base_path + ['ike-group', ike_group, 'key-exchange', 'ikev2']) +        self.cli_set(base_path + ['ike-group', ike_group, 'disable-mobike']) +        # ESP +        self.cli_set(base_path + ['esp-group', esp_group, 'compression']) +        # VTI interface +        self.cli_set(vti_path + [vti, 'address', '10.1.1.1/24']) + +        # vpn ipsec auth psk <tag> id <x.x.x.x> +        self.cli_set(base_path + ['authentication', 'psk', connection_name, 'id', local_id]) +        self.cli_set(base_path + ['authentication', 'psk', connection_name, 'id', remote_id]) +        self.cli_set(base_path + ['authentication', 'psk', connection_name, 'id', peer_ip]) +        self.cli_set(base_path + ['authentication', 'psk', connection_name, 'secret', secret]) + +        # Site to site +        peer_base_path = base_path + ['site-to-site', 'peer', connection_name] +        self.cli_set(peer_base_path + ['authentication', 'mode', 'pre-shared-secret']) +        self.cli_set(peer_base_path + ['connection-type', 'none']) +        self.cli_set(peer_base_path + ['force-udp-encapsulation']) +        self.cli_set(peer_base_path + ['ike-group', ike_group]) +        self.cli_set(peer_base_path + ['default-esp-group', esp_group]) +        self.cli_set(peer_base_path + ['local-address', local_address]) +        self.cli_set(peer_base_path + ['remote-address', peer_ip]) +        self.cli_set(peer_base_path + ['vti', 'bind', vti]) +        self.cli_set(peer_base_path + ['vti', 'esp-group', esp_group]) +        self.cli_set(peer_base_path + ['vti', 'traffic-selector', 'local', 'prefix', '0.0.0.0/0']) +        self.cli_set(peer_base_path + ['vti', 'traffic-selector', 'remote', 'prefix', '192.0.2.1/32']) +        self.cli_set(peer_base_path + ['vti', 'traffic-selector', 'remote', 'prefix', '192.0.2.3/32']) + +        self.cli_commit() + +        swanctl_conf = read_file(swanctl_file) +        if_id = vti.lstrip('vti') +        # The key defaults to 0 and will match any policies which similarly do +        # not have a lookup key configuration - thus we shift the key by one +        # to also support a vti0 interface +        if_id = str(int(if_id) +1) +        swanctl_conf_lines = [ +            f'version = 2', +            f'auth = psk', +            f'proposals = aes128-sha1-modp1024', +            f'esp_proposals = aes128-sha1-modp1024', +            f'local_addrs = {local_address} # dhcp:no', +            f'mobike = no', +            f'remote_addrs = {peer_ip}', +            f'mode = tunnel', +            f'local_ts = 0.0.0.0/0', +            f'remote_ts = 192.0.2.1/32,192.0.2.3/32', +            f'ipcomp = yes', +            f'start_action = none', +            f'replay_window = 32', +            f'if_id_in = {if_id}', # will be 11 for vti10 - shifted by one +            f'if_id_out = {if_id}', +            f'updown = "/etc/ipsec.d/vti-up-down {vti}"' +        ] +        for line in swanctl_conf_lines: +            self.assertIn(line, swanctl_conf) + +        # Check IPv6 TS +        self.cli_delete(peer_base_path + ['vti', 'traffic-selector']) +        self.cli_set(peer_base_path + ['vti', 'traffic-selector', 'local', 'prefix', '::/0']) +        self.cli_set(peer_base_path + ['vti', 'traffic-selector', 'remote', 'prefix', '::/0']) +        self.cli_commit() +        swanctl_conf = read_file(swanctl_file) +        swanctl_conf_lines = [ +            f'local_ts = ::/0', +            f'remote_ts = ::/0', +            f'updown = "/etc/ipsec.d/vti-up-down {vti}"' +        ] +        for line in swanctl_conf_lines: +            self.assertIn(line, swanctl_conf) + +        # Check both TS (IPv4 + IPv6) +        self.cli_delete(peer_base_path + ['vti', 'traffic-selector']) +        self.cli_commit() +        swanctl_conf = read_file(swanctl_file) +        swanctl_conf_lines = [ +            f'local_ts = 0.0.0.0/0,::/0', +            f'remote_ts = 0.0.0.0/0,::/0', +            f'updown = "/etc/ipsec.d/vti-up-down {vti}"' +        ] +        for line in swanctl_conf_lines: +            self.assertIn(line, swanctl_conf) + +      def test_dmvpn(self):          ike_lifetime = '3600'          esp_lifetime = '1800' diff --git a/smoketest/scripts/cli/test_vpn_l2tp.py b/smoketest/scripts/cli/test_vpn_l2tp.py index 07a7e2906..581ebd35d 100755 --- a/smoketest/scripts/cli/test_vpn_l2tp.py +++ b/smoketest/scripts/cli/test_vpn_l2tp.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2023-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_vpn_openconnect.py b/smoketest/scripts/cli/test_vpn_openconnect.py index dcce229e2..77f37b74d 100755 --- a/smoketest/scripts/cli/test_vpn_openconnect.py +++ b/smoketest/scripts/cli/test_vpn_openconnect.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_vpn_pptp.py b/smoketest/scripts/cli/test_vpn_pptp.py index 25d9a4760..f2e9d9868 100755 --- a/smoketest/scripts/cli/test_vpn_pptp.py +++ b/smoketest/scripts/cli/test_vpn_pptp.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2023-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_vpn_sstp.py b/smoketest/scripts/cli/test_vpn_sstp.py index 1a3e1df6e..d1e197246 100755 --- a/smoketest/scripts/cli/test_vpn_sstp.py +++ b/smoketest/scripts/cli/test_vpn_sstp.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2023 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/cli/test_vrf.py b/smoketest/scripts/cli/test_vrf.py index 30980f9ec..42c95dd71 100755 --- a/smoketest/scripts/cli/test_vrf.py +++ b/smoketest/scripts/cli/test_vrf.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2025 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/system/test_config_mount.py b/smoketest/scripts/system/test_config_mount.py index 657158c39..09a6327e5 100755 --- a/smoketest/scripts/system/test_config_mount.py +++ b/smoketest/scripts/system/test_config_mount.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/system/test_iproute2.py b/smoketest/scripts/system/test_iproute2.py index f4fa0f3ba..c720b78b1 100755 --- a/smoketest/scripts/system/test_iproute2.py +++ b/smoketest/scripts/system/test_iproute2.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2021 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as diff --git a/smoketest/scripts/system/test_kernel_options.py b/smoketest/scripts/system/test_kernel_options.py index b51b0be1d..b418ae172 100755 --- a/smoketest/scripts/system/test_kernel_options.py +++ b/smoketest/scripts/system/test_kernel_options.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2020-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as @@ -134,5 +134,32 @@ class TestKernelModules(unittest.TestCase):              tmp = re.findall(f'{option}=y', self._config_data)              self.assertTrue(tmp) +    def test_amd_pstate(self): +        # AMD pstate driver required as we have "set system option kernel amd-pstate-driver" +        for option in ['CONFIG_X86_AMD_PSTATE']: +            tmp = re.findall(f'{option}=y', self._config_data) +            self.assertTrue(tmp) +        for option in ['CONFIG_X86_AMD_PSTATE_DEFAULT_MODE']: +            tmp = re.findall(f'{option}=3', self._config_data) +            self.assertTrue(tmp) + +    def test_inotify_stackfs(self): +        for option in ['CONFIG_INOTIFY_USER', 'CONFIG_INOTIFY_STACKFS']: +            tmp = re.findall(f'{option}=y', self._config_data) +            self.assertTrue(tmp) + +    def test_wwan(self): +        for option in ['CONFIG_USB_NET_DRIVERS', 'CONFIG_USB_USBNET', +                       'CONFIG_USB_NET_CDCETHER', 'CONFIG_USB_NET_HUAWEI_CDC_NCM', +                       'CONFIG_USB_NET_CDC_MBIM', 'CONFIG_USB_NET_QMI_WWAN', +                       'CONFIG_USB_SIERRA_NET', 'CONFIG_WWAN', +                       'CONFIG_USB_SERIAL', 'CONFIG_USB_SERIAL_WWAN']: +            tmp = re.findall(f'{option}=y', self._config_data) +            self.assertTrue(tmp) + +        for option in ['CONFIG_WWAN_HWSIM', 'CONFIG_IOSM', 'CONFIG_MTK_T7XX']: +            tmp = re.findall(f'{option}=m', self._config_data) +            self.assertTrue(tmp) +  if __name__ == '__main__':      unittest.main(verbosity=2) diff --git a/smoketest/scripts/system/test_module_load.py b/smoketest/scripts/system/test_module_load.py index fc60c7220..29fbb407d 100755 --- a/smoketest/scripts/system/test_module_load.py +++ b/smoketest/scripts/system/test_module_load.py @@ -1,6 +1,6 @@  #!/usr/bin/env python3  # -# Copyright (C) 2019-2024 VyOS maintainers and contributors +# Copyright VyOS maintainers and contributors <maintainers@vyos.io>  #  # This program is free software; you can redistribute it and/or modify  # it under the terms of the GNU General Public License version 2 or later as | 
