Security uses RBAC with authz and authn provided by Keycloak server, and heavily relies on row-level security (RLS) in the database.
There should be two DB users (roles); dbadmin
who has full access to the database, and appuser
with limited access.
dbadmin
should set up DB structure - tables with RLS policies and grant RW access to all tables to appuser
.
When the application performs a database query, impersonating the authenticated user, it invokes SET horreum.userroles = '...'
to declare all roles the user has based on information from Keycloak. RLS policies makes sure that the user cannot read or modify
anything that does not belong to this user or is made available to him.
We define 3 levels of access to each row:
- public: available even to non-authenticated users (for reading)
- protected: available to all authenticated users that have
viewer
role (see below) - private: available only to users who 'own' this data.
In addition to these 3 levels, each row defines a random 'token': everyone who knows this token can read the record.
This token should be reset any time the restriction level changes. On database level the token is set using SET horreum.token = ...
and the table policies allow read access when the token matches.
It is assumed that the repo will host data for multiple teams; each user is a member of one or more teams. There are few generic roles that mostly help the UI and serve as an early line of defense by annotating API methods:
- viewer: general permission to view non-public runs
- uploader: permission to upload new runs, useful for bot accounts (CI)
- tester: common user that can define tests, modify or delete data.
- admin: permission both see and change application-wide configuration such as global actions
Each team should have a role with -team
suffix that will be the owner of the tests/runs, e.g. engineers-team
.
Uploaders for team's data have engineers-uploader
which is a composite role, including engineers-team
and uploader
.
Bot accounts that only upload data do not need read access that is represented by the viewer
role; if the account
needs to update a run it needs this role, though (this role is not sufficient to delete anything, though; that requires the tester
role).
Similar to that testers should get a engineers-tester
role which is a composite role, including engineers-team
, tester
and viewer
.
You can set a certificate in runtime for HorreumClient
HorreumClient.Builder builder = ..
builder.sslContext(certFilePath);
or create a custom SSLContext
SSLContext ctx = ...
HorreumClient.Builder builder = ..
builder.sslContext(ctx);