A small and ultrasecure LessPass database server written in Rust.
Simply download latest release from releases page. You can use systemd unit from Arch Linux package to run it.
tar xf rockpass-X.X.X-ARCH.tar.xz sudo install -m755 rockpass-X.X.X-ARCH/rockpass /usr/bin/rockpass sudo install -m644 rockpass-X.X.X-ARCH/rockpass/rockpass.toml.example \ /etc/rockpass.toml sudo vim /etc/rockpass.toml # Configure Rockpass as you like sudo curl 'https://aur.archlinux.org/cgit/aur.git/plain/rockpass.service?h=rockpass' \ -o /etc/systemd/system/rockpass.service sudo systemctl start rockpass sudo systemctl enable rockpassWarning: The only binaries provided are for linux-amd64 and linux-arm64, if you need to run Rockpass on another architecture (like a Raspberry Pi 32bit) you must compile it, see how to do it in the from source section.
Note that the systemd unit uses a dynamic user that has a persistent directory in /var/lib/rockpass/ so it is recommended that the SQLite DB be stored in this directory (see production sample section in rockpass.toml.example).
If everything worked correctly you should have a new clean database in /var/lib/rockpass/rockpass.sqlite. Go to the usage section to learn how to create your first user.
You can download a Rockpass Docker image from here, from Docker Hub or from Quay (only linux-amd64).
To run it, simply exec.
docker run -t -d \ --name=rockpass \ -p 8000:8000 \ ogarcia/rockpass This start Rockpass and publish the port to host.
Warning: this is a basic run, all data will be destroyed after container stop and rm.
Rockpass Docker image uses a volume /var/lib/rockpass to store sqlite database. You can exec the following to mount it in your host as persistent storage.
docker run -t -d \ --name=rockpass \ -p 8000:8000 \ -v /my/rockpass:/var/lib/rockpass \ ogarcia/rockpass Take note that you must create before the directory /my/rockpass and set ownership to UID/GID 100.
mkdir -p /my/rockpass chown -R 100:100 /my/rockpass | Variable | Used for | Default value |
|---|---|---|
ROCKPASS_DATABASES | Database location | {rockpass={url="/var/lib/rockpass/rockpass.sqlite"}} |
ROCKPASS_ADDRESS | Listen address | 0.0.0.0 |
ROCKPASS_PORT | Listen port | 8000 |
ROCKPASS_REGISTRATION_ENABLED | Enable or disable the ability to register new users | true |
ROCKPASS_ACCESS_TOKEN_LIFETIME | Time, in seconds, that the access token is valid | 3600 (1 hour) |
ROCKPASS_REFRESH_TOKEN_LIFETIME | Time, in seconds, that the refresh token is valid | 2592000 (30 days) |
ROCKPASS_LOG_LEVEL | Log level | critical |
Rockpass build has been tested with current Rust stable release version. You can install Rust from your distribution package or use rustup.
rustup default stable If you prefer, you can use the stable version only for install Rockpass (you must clone the repository first).
rustup override set stable Apart from Rust, to build rockpass you will need sqlite3 (usually the -dev package) and the compiler tools. For example in Debian.
apt install build-essential libsqlite3-devDepending on the Linux distribution you use these packages may vary, consult the manual of yours for more information.
To build Rockpass binary simply execute the following commands.
git clone https://gitlab.com/ogarcia/rockpass.git cd rockpass cargo build --releaseAfter build the binary is located in target/release/rockpass.
How Rockpass uses Rocket certain configuration parameters are compatible with each other. You can look at the Rocket configuration documentation to see what the basic parameters are. In any case, a fully commented rockpass.toml.example is provided and the most important parameters are detailed below.
| Setting | Use | Default value |
|---|---|---|
address | Listen address | 127.0.0.1 |
port | Listen port | 8000 |
registration_enabled | Enable or disable the ability to register new users | true |
access_token_lifetime | Time, in seconds, that the access token is valid | 3600 (1 hour) |
refresh_token_lifetime | Time, in seconds, that the refresh token is valid | 2592000 (30 days) |
databases | SQLite database location (see below) | {rockpass={url=":memory:"}} |
The database configuration can be detailed in three options.
Option One.
databases = { rockpass = { url = "/location/of/rockpass.sqlite" } }Option Two.
[release.databases] rockpass = { url = "/location/of/rockpass.sqlite" }Option Three.
[release.databases.rockpass] url = "/location/of/rockpass.sqlite"If you don't want use a config file you can use environment variables. For example to disable registration and listen in 8080.
export ROCKPASS_PORT=8080 export ROCKPASS_REGISTRATION_ENABLED=false export ROCKPASS_DATABASES='{ rockpass = { url = "/location/of/rockpass.sqlite" } }' rockpassYou can run Rockpass without any configuration. By default it creates an in-memory DB that is deleted once the process stops, this is useful for testing purposes.
rockpass The latter is exactly the same as running Rockpass by setting the url key to :memory:.
ROCKPASS_DATABASES='{rockpass = { url = ":memory:" }}' rockpass You can use Rockpass directly on a local network, but if you want to expose it to the Internet it is best to set up some kind of http server in front of it (remember to configure it to listen only to localhost).
server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name rockpass.example.com; access_log /var/log/nginx/rockpass.access.log; error_log /var/log/nginx/rockpass.error.log; ssl_certificate /etc/letsencrypt/live/rockpass.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/rockpass.example.com/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/rockpass.example.com/chain.pem; ssl_session_timeout 1d; ssl_session_cache shared:MozSSL:10m; ssl_session_tickets off; ssl_protocols TLSv1.3; ssl_prefer_server_ciphers off; ssl_stapling on; ssl_stapling_verify on; root /srv/http/pass/htdocs; # Only exposes Rockpass on the endpoints it can handle location ~ (/auth/|/passwords/) { proxy_set_header Host $http_host; proxy_max_temp_file_size 0; proxy_read_timeout 1800s; proxy_send_timeout 1800s; proxy_pass http://127.0.0.1:8000; proxy_redirect http:// https://; } }You must create an empty index.html file in /srv/http/pass/htdocs so that when someone accesses rockpass.example.com they simply get a blank page.
If you want to increase security you can introduce some kind of random string in the exposed endpoints as detailed in the following example.
# Expose Rockpass under very difficult URL location ~ (/somerandomstring/auth/|/somerandomstring/passwords/) { rewrite ^/somerandomstring/(.*) /$1 break; proxy_set_header Host $http_host; proxy_max_temp_file_size 0; proxy_read_timeout 1800s; proxy_send_timeout 1800s; proxy_pass http://127.0.0.1:8000; proxy_redirect http:// https://; }Now in the clients you must configure the server address as https://rockpass.example.com/somerandomstring/. This way it will be very difficult for an external attacker to locate where you have Rockpass listening.
$HTTP["url"] =~ "^/rockpass" { proxy.server = ( "" => ( ( "host" => "127.0.0.1", "port" => "8000" ))) proxy.header = ( "map-urlpath" => ( "/rockpass" => "")) } In this case Rockpass will be listening at https://rockpass.example.com/rockpass/. If you change rockpass to some kind of random string you will increase the security.
Rockpass is an API server for LessPass so it does not expose any interface. You can use any of the existing LessPass applications (plugins, mobile...) to connect against the server or my own lesspass-client command line client implementation.
Let's see an example of use with lesspass-client. First we start rockpass without options or configuration to work directly in memory (it is an example). When we feel comfortable we can start Rockpass with its final configuration.
rockpass The first thing we need to be able to connect is to create a user. For this user to be compatible with the official LessPass applications we must encrypt their password as LessPass does. We can do this with the lesspass-client itself as follows.
$ lesspass-client -m Login_Password password build lesspass.com login@mail.com |O}'bU/sW*7Dfw->What we have done is encrypt a password Login_Password for the user login@mail.com, this has resulted in the encrypted password |O}'bU/sW*7Dfw-> which is the one we must use to create the user.
We now create the user as follows.
$ lesspass-client \ -s http://127.0.0.1:8000 \ user create "login@mail.com" "|O}'bU/sW*7Dfw->" New user created successfullyFrom here we can connect against the API either with the client applications or with the lesspass-client itself. If we do it with any of the client applications (for example the Firefox plugin), we will use as username login@mail.com and password Login_Password since the client application itself will be responsible for encrypting it. If, on the other hand, we do it with lesspass-client, the username will be the same but we must use the encrypted password as detailed below.
# Add a new password profile $ lesspass-client \ -s http://127.0.0.1:8000 \ -u "login@mail.com" \ -p "|O}'bU/sW*7Dfw->" \ password add example.com login@mail.com New password created successfully # List profiles stored on the server $ lesspass-client \ -s http://127.0.0.1:8000 \ -u "login@mail.com" \ -p "|O}'bU/sW*7Dfw->" \ password list example.com # Show a profile $ lesspass-client \ -s http://127.0.0.1:8000 \ -u "login@mail.com" \ -p "|O}'bU/sW*7Dfw->" \ password show example.com ID: 1 Site: example.com Login: login@mail.com Lowercase: true Uppercase: true Symbols: true Digits: true Length: 16 Couter: 1 # Encrypt a new password using a master password and the created profile # Option One (Master password as environment variable) $ export LESSPASS_MASTERPASS="very difficult master password" $ lesspass-client \ -s http://127.0.0.1:8000 \ -u "login@mail.com" \ -p "|O}'bU/sW*7Dfw->" \ password show -p example.com X?%x0O=yn&n4cWGU # Option Two (Master password as argument) $ lesspass-client \ -s http://127.0.0.1:8000 \ -u "login@mail.com" \ -p "|O}'bU/sW*7Dfw->" \ -m "very difficult master password as argument" \ password show -p example.com :~xd`ZtYvS1/8I2+ # The passwords are different in each example because we have changed the # master password.All of the above is just an example, lesspass-client is a complete client so it is possible to perform multiple operations on the LessPass API. See the command help for more information.
If you want to migrate an account from any LessPass server to Rockpass you can use lesspass-client. You will need to encrypt the passwords to be able to export and import the data, see the example above to know how to do it.
First we export the profiles to profiles.json.
$ lesspass-client -s https://api.lesspass.example.com \ -u LOGIN_EMAIL \ -p ENCRYPTED_LOGIN_PASSWORD \ password export profiles.jsonThen we import them.
$ lesspass-client -s http://127.0.0.1:8000 \ -u LOGIN_EMAIL \ -p ENCRYPTED_LOGIN_PASSWORD \ password import profiles.jsonYou can do this operation in memory without using a file as follows.
$ lesspass-client -s https://api.lesspass.example.com \ -u LOGIN_EMAIL \ -p ENCRYPTED_LOGIN_PASSWORD \ password export - | \ lesspass-client -s http://127.0.0.1:8000 \ -u LOGIN_EMAIL \ -p ENCRYPTED_LOGIN_PASSWORD \ password import - Note that when importing data it is not overwritten so if you import the same JSON twice you will have repeated entries.
With the premise in mind of keeping the code simple (remember that it is for personal use so KISS), Rockpass has not implemented any password reset API. However, if any user does not remember their password, you can reset it by following the procedure below.
LessPass encrypts the passwords in the client before sending them, so we must perform the same procedure since for each user the encrypted password is different. My advice is to use a temporary easy password (in my examples I will use 123456) and then the user will change it to something more secure.
To encrypt the password we can use LessPass itself or my lesspass-client. The parameters to use are the following.
- Site:
lesspass.com - Login: The email address you use to authenticate. I will use
rockpass@example.comin this example. - Master password: The new password you want to use. In my case as I said before
123456. - Options: Default. This means all options checked, size 16 and counter 1.
If we want to encrypt the password with lesspass-client the command would be.
$ lesspass-client -m 123456 password build lesspass.com rockpass@example.com -!?}5Nx9E\%svt07Regardless of how we encrypt the password the result is that our encrypted password is -!?}5Nx9E\%svt07. Obviously this is only valid if the user name is rockpass@example.com, if you use another user name it will generate a different encrypted password.
Even if the password is encrypted by the client, Rockpass encrypts it again with Bcrypt hash, this is because in the client options you can select that the password is not encrypted and to increase security.
To encrypt the password with Bcrypt the easiest way is to use a web application that does it, for example Bcrypt-Generator or Bcrypt-Online. When encrypting with Bcrypt you have to set a cost factor, Rockpass uses a factor of 10, but it is OK to use a different factor.
Note that each time you encrypt with Bcrypt a new string is generated, this is normal since Bcrypt generates a different salt each time. In my case the password generated from -!?}5Nx9E\%svt07 is $2y$10$EYeEDnNN/dIQOkJtU9VQAe2fGXhncHbsdZnTdmrs6JMaceKqLg.X6.
- Connect to database.
sqlite3 /location/of/rockpass.sqlite
- Update password to the value
123456for the userrockpass@example.com.UPDATE users SET password='$2y$10$EYeEDnNN/dIQOkJtU9VQAe2fGXhncHbsdZnTdmrs6JMaceKqLg.X6' WHERE email = 'rockpass@example.com';
Now it would be possible to authenticate with the user rockpass@example.com with the password 123456 and modify it with the application. Don't forget to do it!
Users can delete their own accounts using any of the mobile or lesspass-client applications (browser extensions do not have this option). You can still delete any user with the sqlite command. For example to delete user user@example.com and all of his/her passwords settings.
- Connect to database.
sqlite3 /location/of/rockpass.sqlite
- Delete user.
PRAGMA foreign_keys = ON; DELETE FROM users WHERE email = 'user@example.com';