diff --git a/README.md b/README.md new file mode 100644 index 0000000..fd45015 --- /dev/null +++ b/README.md @@ -0,0 +1,95 @@ +# `web-pinentry`: decrypt server keys from your phone + +`web-pinentry` is a [pinentry](https://github.com/gpg/pinentry) program for +Linux servers, allowing you to decrypt keys on your server remotely via your +phone. It relies on HTTP and the Matrix protocol. This is a modern approach to +tasks often faced during server boot up, when things like SQL passwords and API +tokens need to be ascertained before services can begin. + +Sensitive server credentials are historically stored in environment variable +files. Though this legacy approach eases automated server startup, it carries a +huge cost in terms of security. If the server becomes compromised, passwords +and other sensitive information within environment variables and plaintext +config files poses a security threat. Server admins may ultimately +feel compelled to reject server access to engineers or technicians lest they +gain knowledge of crucial passwords in config files. + +To solve this headache, passwords can be encrypted with a GPG wrapper tool such +as `pass`. Rather than pulling passwords from a file, they are obtained through +subprocess calls, e.g. + +`pass sql-root-password` +`pass github-token` + +This is standard practice on desktops, but not yet on servers. + +`web-pinentry` attempts to make this workflow more feasible on servers. Programs +typically pause for user authentication when executing GPG or `pass` commands. On desktop, +a user may types a password or inserts a Yubi key before things can resume. `web-pinentry` +does not assume the user has physical access to the computer, taking a radically +different yet somewhat simple approach. + +## How `web-pinentry` works + +`web-pinentry` is designed to override the builtin GPG `pinentry` program: +Rather than waiting for a password to be typed in the same terminal as the +current process, `web-pinentry` awaits a user password over the network +via a temporary login link. Here is an example of this altered workflow: + +- An engineer reboots a server. +- The init system (systemd or otherwise) starts up the various services. +- Among these is a Scala REST API that attempts to reach a remote DB. +- In the Scala code, a subprocess is used to configure the SQL password: + - I.e. `pass sql-root-password` is executed as the REST API spins up. +- Under the hood, GNU `pass` attempts to decrypt a master-password-protected + file containing the SQL login details. +- This triggers a pinentry program which seeks the master password. + +Usually this is the point at which most naively configured systems would +hang or timeout. However, with `web-pinentry` as your default pinentry program, +the workflow continues unininterupted: + +- GPG communicates with `web-pinentry`, and the latter spins up a temporary + HTTP server. +- On this HTTP server, there is exactly one randomly generated path. +- This path is sent as a URL to a Matrix channel, where the system admin + can then enter the GPG master password. +- Passwords and API keys are then momentarily available for the server's + startup procedure. + +## Security Details + +- Login paths only live for two GET requests, and the pinentry program must + therefore try again with a new link if you type your password wrong. +- `web-pinentry`'s HTTP server only responds to requests made via docker + network IPs or localhost. + - It's imperative to run web-pinentry behind a HTTPS proxy (recommendation: `caddy`). +- All paths that are not the login path are restricted. +- The login link is sent to Matrix via `matrix-commander-rs`, which needs to be + configured in advance. +- The login link is randomly generated anew on each invocation. +- Once a password is entered correctly, the HTTP server is torn down. + +**WARNING**: It is highly recommended to use a GPG master password that is randomly generated +and stored within a password manager. This protects you from phishing attacks +and can further automate the pinentry workflow. Without this protection, a bad +actor could create a visually similar website to the `web-pinentry` default +login, and attempt to prompt you for your password. + +## Requirements + +- [`matrix-commander-rs`](https://github.com/8go/matrix-commander-rs) +- [Matrix](https://matrix.org/) + - Your Matrix user + - A Matrix bot user (just a normal user with a noticeable username like `notification-bot`) + - A private Matrix channel between you and the bot (preferably encrypted). +- A proxy server with HTTPS support (E.g. [`caddy`](https://caddyserver.com/)) +- A DNS subdomain/domain you control. +For development contributors only: +- [`rust`](https://rust-lang.org/) + +## Installation instructions + +```{sh} +cargo build +``` \ No newline at end of file