tests: run sudo tests in namespace rather than under sudo with cleanup
There is a test suite where we manipulate with network stack and we
check that velia correctly captures such changes and propagates them to
sysrepo. However, to manipulate with network stack one must have
privileges for that and also such manipulations *may* destroy some
network settings on the host computer. That's why these tests were not
automatically run but they had to be explicitly enabled in
configuration.
jkt proposed a better way: Run this in a network namespace using
unshare[1]. This way we can run these tests always and not worry about
destroying any network settings. Also, this method doesn't require any
extra privileges, like the ability to run `sudo` in the first place.
There is one caveat though. When sysrepo is compiled with
`-DSYSREPO_GROUP=<group>` then the files it creates are owned by
<user>:<group>. But `unshare --map-root-user` only maps the <user> to
root and not the <group> (unless it is your main group).
Hence we explicitly call unshare with `--map-group=<group>` when we
detect that sysrepo was indeed compiled with `-DSYSREPO_GROUP`. This way
we ensure to have correct permissions inside the namespace to open
sysrepo files which were created before the namespace.
The code uses sysfs for checking whether the interface is a bridge
because libnl support for detecting bridges is just horribly broken
(see commit f910893aff599cde36fb841f633854c248ed59ee for details).
Unfortunately (and contrary to what the docs [2] say), sysfs' mount
namespace is determined by those of the mounting process and then
fixed, no matter what mount NS the caller lives in [3]. That's why
we need to create a custom mount NS and remount sysfs under /sys.
[1] https://www.man7.org/linux/man-pages/man1/unshare.1.html
[2] https://man7.org/linux/man-pages/man7/network_namespaces.7.html
[3] https://unix.stackexchange.com/questions/457025/switching-into-a-network-namespace-does-not-change-sys-class-net
Change-Id: Ifb19c1b49335a3ae2580cb5c8c34aeda8f8b7b52
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b177e06..d8d913a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -310,8 +310,6 @@
find_package(trompeloeil 33 REQUIRED)
find_package(doctest 2.3.1 REQUIRED)
- option(TEST_NETWORK_WITH_SUDO "Include ietf-routing and ietf-interfaces tests that require root privileges" "OFF")
-
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tests/configure.cmake.h.in ${CMAKE_CURRENT_BINARY_DIR}/tests/configure.cmake.h)
add_library(DoctestIntegration STATIC
@@ -359,7 +357,6 @@
find_program(SYSREPOCTL sysrepoctl)
find_program(SYSREPOCFG sysrepocfg)
find_program(IPROUTE2_EXECUTABLE ip REQUIRED)
- find_program(SUDO_EXECUTABLE sudo REQUIRED)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tests/test_vars.h.in ${CMAKE_CURRENT_BINARY_DIR}/test_vars.h @ONLY)
function(velia_test)
@@ -448,14 +445,15 @@
YANG ${CMAKE_CURRENT_SOURCE_DIR}/yang/czechlight-network@2021-02-22.yang)
velia_test(NAME sysrepo_system-ietfinterfaces LIBRARIES velia-system FIXTURE fixture_sysrepo-czechlight-network)
- if(TEST_NETWORK_WITH_SUDO)
- velia_test(NAME sysrepo_system-ietfinterfaces-sudo LIBRARIES velia-system FIXTURE fixture_sysrepo-czechlight-network)
- add_test(NAME network-czechlight0-prepare COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/tests/sysrepo_system-ietfinterfaces-sudo.sh ${SUDO_EXECUTABLE})
- add_test(NAME network-czechlight0-cleanup COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/tests/sysrepo_system-ietfinterfaces-sudo.sh ${SUDO_EXECUTABLE})
- set_tests_properties(network-czechlight0-prepare PROPERTIES FIXTURES_SETUP network-czechlight0)
- set_tests_properties(network-czechlight0-cleanup PROPERTIES FIXTURES_CLEANUP network-czechlight0)
+ find_program(UNSHARE_EXECUTABLE unshare REQUIRED)
+ pkg_get_variable(SR_GROUP sysrepo SR_GROUP)
+ if (SR_GROUP)
+ set(UNSHARE_MAP_GROUP_ARG "--map-group=${SR_GROUP}")
+ else()
+ set(UNSHARE_MAP_GROUP_ARG "")
endif()
-
+ velia_test(NAME sysrepo_system-ietfinterfaces-sudo LIBRARIES velia-system FIXTURE fixture_sysrepo-czechlight-network
+ COMMAND ${UNSHARE_EXECUTABLE} --net --mount --map-root-user ${UNSHARE_MAP_GROUP_ARG} sh -c "mount -t sysfs none /sys $<SEMICOLON> ./test-sysrepo_system-ietfinterfaces-sudo")
set(fixture_sysrepo-ietf-hardware YANG ${CMAKE_CURRENT_SOURCE_DIR}/yang/iana-hardware@2018-03-13.yang YANG ${CMAKE_CURRENT_SOURCE_DIR}/yang/ietf-hardware@2018-03-13.yang FEATURE hardware-sensor)
velia_test(NAME hardware_ietf-hardware LIBRARIES velia-ietf-hardware velia-ietf-hardware-sysrepo FsTestUtils FIXTURE fixture_sysrepo-ietf-hardware)