grima

grima - whispering into alma's ear with APIs

This project is maintained by zemkat

Deploying grima on the cloud

Grima is designed to be deployed in a cloud environment. Sample configurations are given for docker-compose, docker swarm, and kubernetes.

Pre-requisites

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.

Configuration

The main container docker.io/zemkat/grima-cloud allows quite a bit of configuration through environment variables.

No authentication mode

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.

API Key is authentication mode

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.

User database

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).

Port configuration

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.