Open ethanjli opened 3 years ago
Rather than loading the authtoken.secret file every time the program starts, should we instead only load it once and then somehow store it persistently in the Rust side of the app? This way our program could run without root privileges, which seems like a big security win. The only issue would be how to guarantee that there's no way to leak the secret through the app - e.g. if we could have a separate/isolated frontend which runs once as root for copying the secret to a secure store (perhaps secrets or coccoon?), and then only Rust is allowed to read the secret or use the secret. This would make it easier to completely isolate the main frontend (which talks to the internet) from the secret.
The approach described in https://github.com/zerotier/ZeroTierOne/blob/master/doc/zerotier-cli.1.md is to copy the authtoken to the user's home directory; "this gives the user the power to connect or disconnect the system to or from any virtual network, which is a significant permission." For the first iteration of this functionality, we could do the same thing (including using a script or a separate program to accomplish this) - this would be fine for computers used only by a single person. For multi-user desktops, would we need to create a backend which acts as a wrapper around ZeroTier One but with an auth layer, and then run that as a background service with more fine-grained controls over read/write permissions?
One strategy could be for the Rust layer of the app to check for authtoken.secret in the user's config directory and attempt to contact the ZeroTier API; if the authtoken.secret file is missing or the API is rejecting the authtoken, it should attempt to read the authtoken.secret from the Zerotier directory (attempting to acquire the necessary permissions), and then pass it to the frontend. If it failed, the frontend will display the (currently verbose) instructions for manually copying the authtoken.secret file; if it succeed, the frontend should provide an opt-out setting on the home screen to only make it usable with admin access; opting out will trigger the Rust layer to write the authtoken to the user's config directory, while opting back in will trigger the Rust layer to delete the authtoken.secret file from the user's config directory.
All of this might be simpler and more secure if all calls to the ZeroTier API are done through Rust, so that the frontend can't leak the authtoken and doesn't need to make fetch calls to the ZeroTier API.
For usability, we'll need the app to be able to automatically load ZeroTier One's authtoken.secret file so that we can issue requests to the ZeroTier One service (which runs on
localhost:9993
). This will require the app to have filesystem access, and the app will need to open the authtoken.secret file (whose location depends on the target OS) usingpkexec
on Linux or UAC elevation request on Windows which may require adding a manifest using cargo somehow. I'm not sure whether or how we can require the app to ask for administrator privileges. If the app is unable to open the file, we'll certainly need to display an error message to the user.In the meantime, we can add a text field to paste in the authtoken, so that we can provide that in HTTP requests to the ZeroTier One service.