/sue

As small and swift as su-exec, but as featureful and robust as gosu!

Primary LanguageNimGNU General Public License v3.0GPL-3.0

nimble

Source Language

Last Commit

GitHub Liberapay patrons

What

Executes a program as a user different from the user running sue. The target program is exec'ed which means, that it replaces the sue process you are using to run the target program. This simulates native tools like su and sudo and uses the same low-level POSIX tools to achieve that, but eliminates common issues that usually arise, when using those native tools.

Why

As small and swift as su-exec, but as featureful and robust as gosu!

This and its alternatives all exist for pretty much the same core reason:

This is a simple tool grown out of the simple fact that su and sudo have very strange and often annoying TTY and signal-forwarding behavior. They're also somewhat complex to setup and use (especially in the case of sudo), which allows for a great deal of expressivity, but falls flat if all you need is "run this specific application as this specific user and get out of the pipeline".

Source

Why use sue instead of su-exec, gosu or other alternatives?

An opinionated comparison!

Better than gosu in these ways:

gosu is written in Go, which is comparatively slow and bloated compared to other systems programming languages. sue is written in Nim, which is comparable to C in terms of performance and size, while being actually maintainable & readable.

Better than su-exec in these ways:

su-exec is supposed to be a far more lightweight alternative to gosu. As an example, the official Debian-based postgres images use gosu while the Alpine-based images use su-exec. The latter is written in C, meaning that the level of maintainability is kept pretty low. It also is focused entirely on size and less on providing every feature of gosu in a more compact fashion. gosu has a stricter and much more robust behaviour, than su-exec.

sue is on the other hand covering all gosu test cases, meaning that it provides precisely the same feature set as gosu while being only half the size and most likely being also more performant overall.

Better than chroot in these ways:

chroot is a bit clunky and not as straight-forward to use. For the use-case of the specific privilege management in Docker environments, this tool is not well suited, as it has originally a different overall purpose.

Better than setpriv in these ways:

Similar to chroot, setpriv feels very clunky and you have to provide so much information explicitly, when it could be so much more straight-forward and easy to use, as is gosu, su-exec or sue.

How

First, make sure you are running sue as the root user, to avoid permission issues.

Get the project and prepare it:

git clone https://github.com/theAkito/sue.git
cd sue
nimble configure

To build the project use one of the predefined tasks:

nimble fbuild

for the release build or

nimble dbuild

for the debug/development build.

You can also make a quick test if sue works, as it should:

nimble test

Run the fully fledged test suite, covering a large amount of edge cases and possible flukes:

nimble xtest

This test suite covers all original gosu test cases. Since all are passed successfully, we achieve full compatability with gosu's behaviour.


The first argument passed to sue is the user-spec with either the username or its id. Appending a group to the user-spec is optional.

The following examples assume a user named dunwall, belonging to a group of the same name and id.

Example 1:

./sue dunwall src/test

Example 2:

./sue dunwall:dunwall src/test

Example 3:

./sue 1000:dunwall src/test

Where

This tool is meant to be used in a Docker environment, as a way to execute a program while temporarily switching the user just for running that process, as some need to be run as a specific user or need a designated user for taking over a user role in that program.

Real world example

The following example is taken from the official postgres:13-alpine Docker image's docker-entrypoint.sh script, where su-exec is used to execute this startup script as the postgres user, since PostgreSQL should be operated by the postgres user.

	if [ "$1" = 'postgres' ] && ! _pg_want_help "$@"; then
		docker_setup_env
		# setup data directories and permissions (when run as root)
		docker_create_db_directories
		if [ "$(id -u)" = '0' ]; then
			# then restart script as postgres user
			exec su-exec postgres "$BASH_SOURCE" "$@"
		fi

Source

Note that use-cases like this one are the primary target of sue. Using this program outside of a Docker container usually means that this tool is misused, as it is specifically designed for the type of purpose shown in the example above.

Goals

  • Performance
  • Size
  • Maintainability

Project Status

All gosu test cases are covered, achieving full compatability with gosu's behaviour. Therefore, this alternative is just as stable as the widely popular gosu.

TODO

  • Implement test suite
  • Include gosu test cases
  • Better error handling
  • Add base Docker image
  • Add CI
  • Separate inlined script from Dockerfile
  • Optimize

License

Copyright © 2020-2022 Akito the@akito.ooo

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.