Service Accounts
System principals versus ordinary service users.
Situation. Two non-human accounts at Valmont. lab-importer files
lab results every night and must never be blocked by a policy mistake. The
patient-portal backend reads prescriptions on behalf of patients and should
be governed like any other account.
They need different treatment.
The rule of thumb
| System principal | Ordinary service user | |
|---|---|---|
Registered in system_principals | yes | no |
| Prohibitions apply | never | yes |
| Config editable at runtime | no (trigger-locked) | yes |
| Use for | infrastructure jobs that must not be lockable | anything acting for users |
Registering a principal is a deployment-time decision, made in SQL by the database owner. Make it only when being blocked would break the platform.
The system principal
INSERT INTO morbac.system_principals (user_id, description)
VALUES ('aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa', 'Nightly lab-results importer')
ON CONFLICT (user_id) DO NOTHING;It still needs a permission; being a principal only removes prohibitions:
INSERT INTO morbac.global_rules (user_id, activity, view, context_id, modality)
VALUES ('aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa', 'create', 'lab-results',
(SELECT id FROM morbac.contexts WHERE name = 'always'), 'permission')
ON CONFLICT DO NOTHING;Proof that a prohibition cannot touch it:
INSERT INTO morbac.global_rules (user_id, activity, view, context_id, modality, priority)
VALUES (NULL, 'create', 'lab-results',
(SELECT id FROM morbac.contexts WHERE name = 'always'), 'prohibition', 500)
ON CONFLICT DO NOTHING; -- bans everybody
SELECT morbac.is_allowed('aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa',
(SELECT id FROM morbac.orgs WHERE name = 'Clinique Valmont Nord'),
'create', 'lab-results'); -- true, still runs
SELECT morbac.is_allowed('11111111-1111-4111-8111-111111111111',
(SELECT id FROM morbac.orgs WHERE name = 'Clinique Valmont Nord'),
'create', 'lab-results'); -- false, bannedClean up the demo ban:
DELETE FROM morbac.global_rules
WHERE user_id IS NULL AND view = 'lab-results' AND modality = 'prohibition';The ordinary service user
patient-portal gets a normal role and normal rules, so it can be
suspended, scoped and audited like a human account:
INSERT INTO morbac.roles (org_id, name)
SELECT id, 'portal-service' FROM morbac.orgs WHERE name = 'Clinique Valmont Nord'
ON CONFLICT (org_id, name) DO NOTHING;
INSERT INTO morbac.user_roles (user_id, role_id, org_id)
SELECT 'bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb', r.id, r.org_id
FROM morbac.roles r JOIN morbac.orgs o ON o.id = r.org_id
WHERE o.name = 'Clinique Valmont Nord' AND r.name = 'portal-service'
ON CONFLICT DO NOTHING;What the trigger lock prevents
Once registered, attempts to assign roles to the principal, delegate to or
from it, write user rules for it, or target it with a global prohibition all
raise an exception. Removing the lock means removing the row from
system_principals, which only the database owner can do.