Fix behavior when run as non-root. #141
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Before this patch, if you run the install script without root/sudo on Ubuntu/Debian, then you can get into a broken situation that could be hard for some users to fix. This breakage would prevent any updates to the OS until resolved.
There's one main fix here: removing two instances of lines like:
And replacing each with this fix:
The issue here is that in order to access a privileged location like
/etc/apt/trusted.gpg.d/zerotier-debian-package-key.gpg
, it is not enough to use sudo and a shell redirect because the shell will actually open the file, not sudo. The fix is to use sudo with the tee command, which can use its elevated privileges to open the file and accept input from GPG.Note that this use case, running the script as non-root, is not covered by the test cases in CI. Nevertheless, it is actually recommended as "foil hat mode" in the readme. It's also a perfectly sensible and convenient way to use the script.
The way this issue can block OS updates is as follows: if a user on Ubuntu or Debian runs the script as non-root, then writing the ZeroTier package key to /usr/share/keyrings will fail, but the subsequent operation that adds a source list depending on this key will succeed. This leads to a situation where
apt-get update
fails with a GPG error, blocking any updates.The above fix is sufficient to resolve this issue with the script, but I've also added
set -Eeuo pipefail
to the script to defend against this type of issue in the future. This enables Bash "sane mode", which would have prevented this issue by failing the script on the first command failure, leading to a consistent APT configuration even though the install would still fail.Adopting sane mode does require consideration of the existing code in the script. I had to disable errexit temporarily in one code block to support the way that code handles error status explicitly. Note that this code block is not exercised by tests. I reviewed all code in the script for any similar issues with sane mode.
I ran the new version of the script through ShellCheck on "style" mode (all messages, warnings, etc enabled) and reviewed all its output. Incidentally I removed all trailing white space from the script. GPG removes this whitespace when it de-armors the script.
Finally, I wanted to ensure that CI passed in my fork before opening a PR. I removed "debian:10" (Buster) from the test matrix as its repos have been moved to the archive now that it is end-of-life. It might be possible to keep Debian Buster in the test matrix by adding some conditional logic in ci.yml to update the repo lists to point to the archive repos. I also removed the unnecessary apt step and enabled Bash's "x" flag so print debug info.
I'm open to any feedback. Please let me know if you'd like me to split these changes into separate PRs.