Add a README
This commit is contained in:
95
README.md
Normal file
95
README.md
Normal file
@@ -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
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user