Unit Testing in Isolation with the unshare / firejail Commands

Author

Andres Monge

Published

October 15, 2023

The unshare command in Linux allows you to run programs in isolated namespaces, making it ideal for unit testing in a controlled environment. Namespaces isolate resources like the network, file system, or processes, ensuring tests don’t affect the host system.

Key Use Case: Disconnected Unit Testing

A common use case is running unit tests in a disconnected environment. For example, you can isolate network operations to avoid affecting the host’s network.

Example: Isolating Network Namespace

To test a network-related function without sending actual packets, use:

unshare -n -- poe test

This command runs poe test in a new network namespace (-n flag). Any network operations inside this namespace are isolated from the host. For instance, you can bring up a loopback interface without impacting the host:

ip link set lo up

This ensures your tests run in a controlled, isolated environment.

Running unshare Without sudo

By default, the unshare command requires elevated privileges (e.g., sudo) to create new namespaces.

However, you can configure your system to allow non-root users to run unshare without sudo. Here’s how:

1. Add the User to the sudo Group (if not already)

If your user is not already in the sudo group, you can add them:

sudo usermod -aG sudo $USER

After running this command, log out and log back in for the changes to take effect.

2. Grant Specific Capabilities to the User

To avoid using sudo altogether, you can grant specific capabilities to the unshare binary.

For example, granting the CAP_SYS_ADMIN capability allows non-root users to create namespaces:

sudo setcap cap_sys_admin+ep /usr/bin/unshare

After this, you can run unshare without sudo:

unshare -n -- $(poe test)

3. Revert Changes (Optional)

If you want to revert the changes and remove the capabilities:

sudo setcap -r /usr/bin/unshare

4. Alternative: Configure sudoers

If you frequently need to run unshare without a password, you can configure sudoers to allow passwordless execution for specific commands.

Add the following line to /etc/sudoers:

username ALL=(ALL) NOPASSWD: /usr/bin/unshare -n -- $(poe test-only -f tests/
research_operation_workflows/test_duplicate_research_operation_workflows.py)

Replace username with your actual username.

Important Notes

  • Security Implications: Granting capabilities like CAP_SYS_ADMIN or configuring sudoers can have security implications. Ensure you understand the risks before proceeding.

  • System-Specific: The exact steps may vary depending on your Linux distribution and system configuration.

Comparison: unshare vs. firejail

Both unshare and firejail are tools for isolating processes, but they serve different purposes and have distinct features. Here’s a comparison:

Feature unshare firejail
Purpose Low-level namespace isolation High-level sandboxing
Ease of Use Manual configuration Pre-configured profiles
Namespaces All Linux namespaces Network, FS, user namesp.
Security Features Limited (capabilities) Advanced (AppArmor, etc.)
Network Isolation Yes (-n flag) Yes (--net=none, etc.)
Filesystem Isol. Manual (mount commands) Auto (--private, etc.)
User Namespace Yes (-U flag) Yes (--noroot)
Custom Profiles No Yes (--profile=file)
D-Bus Isolation No Yes (--nodbus)
X11 Sandboxing No Yes (--x11)
Resource Limits No Yes (--rlimit-*)
Debugging Tools No Yes (--debug, --trace)

Example: Using firejail for Network Isolation

To achieve similar network isolation as unshare -n, you can use firejail:

firejail --net=none -- poe test

This command runs poe test in a sandbox with no network access, similar to unshare -n.

Example: Using firejail for Filesystem Isolation

To isolate the filesystem and create a temporary home directory:

firejail --private -- poe test

This creates a new, empty home directory for the process, ensuring no access to the host’s files.

Conclusion

The unshare command is a powerful tool for unit testing. By isolating namespaces, you can ensure tests are reproducible and don’t interfere with the host system. Use unshare -n for network isolation or combine flags for more comprehensive control. With proper configuration, you can run unshare without sudo, making it easier to integrate into automated workflows.

For more advanced sandboxing and security features, firejail is an excellent alternative. It provides pre-configured profiles, resource limits, and additional isolation mechanisms, making it ideal for running untrusted applications securely.

References

  • unshare Documentation: Run man unshare for detailed usage.

  • Linux Namespaces: Learn more about namespaces in the Linux kernel docs.

  • Capabilities in Linux: Refer to man capabilities for details on Linux capabilities.

  • firejail Documentation: Visit Firejail’s homepage for more information.