Store Entities Neatly, Kept Encrypted
Senke (/ˈzɛŋkə/) is a transparently encrypted cache accessible via a simple HTTP API. By default, all data is encrypted at rest, and access is controlled through simple, policy-based access control lists.
There are a few words repeatedly used:
- entity: a single data item stored in the cache. It exists under a
(domain, resource)
namespace. - resource: an identifier representing a logical or historical collection of related
entities
. - domain: a grouping of
resources
— essentially a namespace or scope. - action: what a user can do to entities within a domain. One of:
create
,read
,delete
. - policy: a permission tuple:
(domain, user, action)
. Policies define who can perform what action on which domain. - user: an authenticated actor granted one or more policies. Multiple users can have overlapping access.
Build it first. See below how.
Create a .env
file like seen in example.env
.
The file senke uses can be overriden by setting the
environment variable ENV_FILE
to the path with your
config file (e.g. ENV_FILE=/path/to/my-config.env
).
This assumes you used the example.env
as configuration.
mkdir -p local-db
# display help, every subcommand has this
senke -h
# create a domain
senke domain add ab.example.com # can be any string
# create users
senke user add alice # enter password for alice (e.g. secret1)
senke user add bob # enter password for bob (e.g. secret2)
senke user add candace # enter password for candace (e.g. secret3)
# use the PASSWORD env variable to skip the prompt
# add policies to allow users access to actions at the domain
senke policy add ab.example.com alice create
senke policy add ab.example.com bob read
senke policy add ab.example.com candace delete
# or create users and domains together with the policy
# the PASSWORD env variable works here too
PASSWORD=secret1 senke policy add --create ab.example.com alice create
PASSWORD=secret2 senke policy add --create ab.example.com bob read
PASSWORD=secret3 senke policy add --create ab.example.com candace delete
# start the server
senke serve
Using the HTTP API of the cache with curl would go like this:
# generate some random data
dd if=/dev/urandom bs=64 count=2 | base64 > /tmp/random-data.txt;
# upload data
curl --request PUT --header 'content-type: application/octet-stream' --user alice:secret1 --data-binary '@/tmp/random-data.txt' 'http://localhost:8080/api/domains/ab.example.com/my-custom-resource' --verbose
# retrieve data
curl --request GET --user bob:secret2 'http://localhost:8080/api/domains/ab.example.com/my-custom-resource' --verbose
# look at the content-location header to get the URL for deleting this entity
# delete data
curl --request DELETE --user candace:secret3 'http://localhost:8080/api/domains/ab.example.com/my-custom-resource/archive/2b539ce91c1c34656a5ae19e2c46113eecfc0b1a8b561e7c9b18a6f55ed6a9ac'
The three actions create
, read
and delete
map to the HTTP methods (PUT
or POST
), GET
and DELETE
.
alice
cannot read
nor delete
on ab.example.com
.
bob
cannot create
nor delete
on ab.example.com
.
candace
cannot create
nor read
on ab.example.com
.
Either build it statically with docker, with the nix package manager or by hand on your local system.
Use the just command runner.
just docker
ls -lah target/senke
nix build
ls -lah result/bin
- cargo
- libsodium
- sqlite
- clang
- mold (because mold is cool)
- make
- musl (only for static linking against musl libc)
Archlinux:
pacman -Sy --noconfirm make clang rustup cargo libsodium sqlite mold musl
Alpine:
apk add build-base clang make mold musl-dev libsodium-dev sqlite-dev
cargo build --release --target x86_64-unknown-linux-gnu
cargo build --release --target x86_64-unknown-linux-musl
Caution
This project has not been audited and may contain security vulnerabilities.
Use this software at your own risk.
It is provided "as is", without any warranty or guarantee of fitness for any particular purpose.
The author(s) accept no responsibility or liability for any damages, losses, or issues resulting from the use of this code.
Big thanks go to libsodium for providing such an awesome cryptographic library and alkali for making it so easy to use it with rust!
This is just a small project of mine to easily automate sharing arbitrary data or even secrets across hosts.
I had lots of fun with this project and learned many new things.
Maybe it will be useful to you too :D
Cheers