grima - whispering into alma's ear with APIs
This project is maintained by zemkat
Grima is designed to be deployed in a cloud environment. Sample configurations
are given for docker-compose
, docker swarm
, and kubernetes
.
Grima is fairly lightweight. Its source code is around 300K, with another 10 to 15 MB of documentation. It runs in PHP and requires a web-server.
For institutions where grima-users should not all have access to Alma API keys,
grima can use an external database for authentication (PHP PDO
is the driver,
and support for mysql
and postgresql
are builtin).
Sessions can be stored in redis
(support builtin to the container), but the
new feature is to store the session in a cookie (to prevent replay attacks by
eavesdroppers, this requires HTTPS which is not built-in).
So the three main parts are: web-server, database, and sessions.
The main container docker.io/zemkat/grima-cloud
allows quite a bit of configuration
through environment variables.
By passing apikey
and server
values through environment variables, or by
passing apikey_file
pointing at a docker secret (or plain file) you can setup
grima to run without any authentication. This is suitable for private networks
where anyone who can connect has the authority to work with the catalog.
SESSION_MODULE=none
is recommended to avoid any cookies being set.
SESSION_KEY
, SESSION_NAME
, SESSION_PATH
are unused in this case.
DATABASE_URL
, DATABASE_USER
, DATABASE_PASS
are unused.
No session store or database is used. The Grima-cloud
container can be
replicated as much as desired. Each container will use as many cores as you
allow it.
Realistically, a single container on a single core with 512MB ram should serve a staff of 20 librarians.
Require each user to login using an API Key. This requires sessions, but no database.
apikey
, apikey_file
, should be unset. One probably leaves server
,
server_file
unset, as they are chosen from an easy to read drop-down menu.
SESSION_MODULE
can either be redis
or encrypted_cookie
(recommended
if you have HTTPS or an otherwise secure network).
With redis: you’ll need to run a redis container. These can have master nodes
and replica nodes, etc. However, a single redis instance per data center should
be plenty. SESSION_NAME
is the name of the redis key, SESSION_PATH
should be
something like tcp://redis-server.example.com
. SESSION_KEY
is unused.
Simpler: use encrypted_cookie
sessions. A cookie is set that contains the API
key encrypted. However, anyone with the cookie can ask your copy of grima
whatever they want, so make sure the web-server is behind HTTPS. Most
load-balancers include “SSL termination” and this document is mostly geared
towards “enterprise” deployments.
SESSION_NAME
is the name of the cookie. SESSION_PATH
is unused. SESSION_KEY
can be left unset (a default value is used), but if it is set, is must be the
same at every grima web-server behind your load-balancer (so that a cookie from one
replica can be used at another).
Again, since one replica should be enough, this is likely simple to setup.
There is no database in this setup. DATABASE_URL
, DATABASE_USER
, and DATABASE_PASS
are unset.
If you have multiple users sharing API Keys, and multiple API keys, etc. then you’ll probably need a user database. The database is only consulted at login, so it does not need to be performant. Each user is about 100 bytes of data. Kathryn’s institution uses SQLite for its database.
However, the cloud configs have you choose between mysql
and postgres
.
Likely you already have a favorite, but if not, they are basically equivalent
for this usage. The containers suggested set themselves up.
Leave apikey
, apikey_file
, server
, server_file
unset.
Choose SESSION_MODULE=redis
(SESSION_PATH=tcp://redis-service-url
) or
SESSION_MODULE=encrypted_cookie
(SESSION_KEY_FILE=/run/secrets/SESSION_KEY
).
DATABASE_URL
should be as in the examples (mysql
or postgres).
DATABASE_USER
and DATABASE_PASS
are only used for the mysql driver.
Password security is perhaps a bit paranoid, but the goal was to ensure that this password database is a low value target. The grima admin and the grima user are not allowed to set or use passwords that are on haveibeenpwned.com. The browser runs PBKDF for half a second or so to increase a brute force cost of someone who has breached your grima-cloud server. The grima-cloud server itself runs another KDF (Argon) for a tenth of a second or so to further increase the cost if the user database is breached. Since the passwords are uncommon, and have been securely (slowly) hashed, attacking the user database is not a feasible method of getting the passwords.
That said, the only computers that need to access your session store or user
database are the grima-cloud servers (not the employees using the
grima-server), so feel free to have them only accessible from the internal
docker network. (kompose
appeared to expose the redis and database ports to
the world during some brief testing).
The grima-cloud container can run without any special privileges if you set
APACHE_PORT
to a non-privileged port, such as 19290
.
APACHE_PORT=80
might make some orchestrators happier, as it runs the web-server
on the default port.