006
Combined tombstoning of uid and login
Lukas Juhrich, Jakob Müller
2023-01-15
Postulated
In the light of data economy, we should not store the login of a User
–
which implicitly is a (partial) property of the UnixAccount
–
more than necessary.
The only reason to keep the login is to avoid assigning the same mail address to multiple people across time; otherwise, mails might be send to the wrong addressee.
Thus it has been decided (external from the development team) to store the login in form of a hash whenever it stops being required for providing services to a user.
The implementation has to ensure
absence of the login
whenever it is not needed (legal requirement)
that no login is doubly assigned (legal / business requirement)
Consequently, we need to track the login
hash in some kind of “tombstone”,
such that
it is referenced by a User
or a UnixAccount
it exists in all scenarios and is never deleted
Since the login
and the uid
have the same lifecycle, and both
require tombstoning –
albeit the uid
needs to be kept only for technical reasons,
not for legal ones –
it makes sense to let such a tombstone
maintain both pieces of data.
In the current model, the relevant entities are related as follows:
User
: has a login
(nullable) and a unix_account_id
(nullable).
UnixAccount
: Has the columns uid
, gid
, home
, and login_shell
,
but no login
.
An ldap account (Derived entity):
If a User
has a UnixAccount
and the correct permissions,
this causes an LDAP account to be exported by the ldap syncer.
Since user.unix_account
is a foreign key constraint,
we have the following possible states (U
: User, UA
: UnixAccount):
# |
∃U? |
∃U.login? |
∃U.unix_account_id? |
∃UA? |
---|---|---|---|---|
1 |
✓ |
✗ |
✗ |
✗ |
2 |
✓ |
✗ |
✓ |
✓ |
3 |
✓ |
✓ |
✗ |
✗ |
4 |
✓ |
✓ |
✓ |
✓ |
5 |
✗ |
✗ |
✗ |
✓ |
6 |
✗ |
✗ |
✗ |
✗ |
With regards to tombstoning, the states imply the following requirements:
No requirements.
This is currently allowed, but issues a warning in the ldap syncer. Indeed, without the login the unix account cannot be exported. With tombstones however, we require
\((T_u)\) there shall exist a tombstone with the same uid as the account
\((T_l)\) there shall exist a tombstone with the implied login hash
\((T_u)\) there shall exist a tombstone with the same uid as the account
\((T_l)\) there shall exist a tombstone with the implied login hash
\((E_{ul})\) both tombstones in question should be equal
\((T_u)\) there shall exist a tombstone with the same uid as the account
Nothing exists
There shall be
A new entity unix_tombstone(uid int, login_hash text)
satisfying
uid
is unique
login_hash
is unique
Either column may be null
, but not both
uid
and login_hash
form the primary key
A generated column login_hash
on the user
relation
(see sqlalchemy.schema.Computed
)
\((T_l)\): A foreign key constraint User.login_hash → UnixTombstone.login_hash
\((T_l)\): A foreign key constraint UnixAccount.uid → UnixTombstone.uid
\((E_{ul})\): A constraint checking consistency for users with login and unix account:
In this case, the tombstone induced by the account.uid
should agree
with the tombstone induced by the user.login_hash
That the login_hash
is optional allows for
unix_accounts
which don’t have a unix_login
associated to them
to have valid tombstones as well.
However, this implies that were one to couple these accounts to users again,
the tombstone has to be modified to reflect the user’s login
(if it exists).
using a combined entity instead of an entity for the login
and uid
,
respectively, has the advantage that one can identify login
tombstones
which never had a respective unix_account
.
Database administrators can then decide on whether to keep these entries or not,
since technically these logins have not been used anywhere.
This might not serve any particular purpose but the
In the most frequent use case of creating a user with login and unix account, A tombstone has to be created as well. This is slightly more effort than the current implementation. To avoid this, triggers may be created that take care of this automatically.
Note
This ADR does not take a stance on whether or not to add triggers as it is mainly concerned with ensuring the critical legal and business requirements.
Tests have to be written to ensure that with any state change of the user
or unix_account
relations,
the information contained in the tombstone
tables is monotonous,
i.e that neither does a tombstone get deleted via a cascade
nor is a field set to null
when it has been non-null before.