mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-21 00:02:30 +00:00
A data table backed by the instance database resolved to exactly one Postgres connection, `custom_instance_user`, for everyone who could reach it at all. There was no way to say this job reads, that one writes, this one never sees the salaries table. A data table role is now a real Postgres login on the cluster, defined once for the instance by a superadmin and named exactly as they named it. A script that declares `-- role analytics` connects as `analytics`, and Postgres decides what it may touch — grants are ordinary SQL. Windmill answers only "may this caller ask for this role", from the tenant lists on the data table entry: `u/alice`, `g/analysts`, `f/finance` or `*`. A data table with no `permissions` block behaves exactly as before. Everything that opens a connection on someone's behalf goes through one chokepoint, `get_datatable_resource_from_db`, which takes the identity explicitly and fails closed when there is none. The role logs in as itself — never `SET ROLE`, which a script could `RESET ROLE` its way out of. A fork's data table entry becomes a pointer at the workspace that governs it rather than a copy of it. The settings clone used to hand a fork a byte-identical entry naming the parent's database, which a fork admin could edit to grant themselves `admin` there; a pointer has nothing local to edit, and its tenants are evaluated as a member of the governing workspace, by email. `permissions` is stripped from the workspace export and ignored on import: tenants name principals of one workspace, and a settings push is not where an access decision should be made. Operations that see the whole database whatever the roles grant stay with the governing workspace's admins: editing the roles, a migration that declares none, and opening a replication stream for a Postgres trigger or capture. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR
47 lines
2.2 KiB
SQL
47 lines
2.2 KiB
SQL
-- A data table under roles in `test-workspace`, and a fork whose entry points at it rather than
|
|
-- carrying a copy. `test-user-2` is a non-admin of the parent and an admin of the fork: the shape
|
|
-- the pointer exists for.
|
|
|
|
UPDATE global_settings SET value = jsonb_set(value, '{roles}',
|
|
'{"role1": {"name": "analytics", "enabled": true, "pwd": "pw"}}'::jsonb)
|
|
WHERE name = 'custom_instance_pg_databases';
|
|
INSERT INTO global_settings (name, value)
|
|
SELECT 'custom_instance_pg_databases',
|
|
'{"user_pwd": "pw", "databases": {"dt_main": {}},
|
|
"roles": {"role1": {"name": "analytics", "enabled": true, "pwd": "pw"}}}'::jsonb
|
|
WHERE NOT EXISTS (SELECT 1 FROM global_settings WHERE name = 'custom_instance_pg_databases');
|
|
|
|
UPDATE workspace_settings SET datatable = '{
|
|
"datatables": {
|
|
"main": {
|
|
"database": {"resource_type": "instance", "resource_path": "dt_main"},
|
|
"permissions": {
|
|
"default_role": "role1",
|
|
"roles": {
|
|
"admin": {"tenants": []},
|
|
"role1": {"tenants": ["u/test-user-2", "g/analysts", "f/finance"]}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}'::jsonb WHERE workspace_id = 'test-workspace';
|
|
|
|
INSERT INTO group_ (workspace_id, name, summary, extra_perms) VALUES
|
|
('test-workspace', 'analysts', 'Analysts', '{}');
|
|
INSERT INTO folder (workspace_id, name, display_name, owners, extra_perms) VALUES
|
|
('test-workspace', 'finance', 'finance', '{}', '{}');
|
|
|
|
INSERT INTO workspace (id, name, owner, parent_workspace_id) VALUES
|
|
('wm-fork-dt', 'fork of test-workspace', 'test2@windmill.dev', 'test-workspace');
|
|
INSERT INTO workspace_key (workspace_id, kind, key) VALUES ('wm-fork-dt', 'cloud', 'test-key');
|
|
INSERT INTO group_ (workspace_id, name, summary, extra_perms) VALUES
|
|
('wm-fork-dt', 'all', 'All users', '{}');
|
|
INSERT INTO usr (workspace_id, email, username, is_admin, role) VALUES
|
|
('wm-fork-dt', 'test2@windmill.dev', 'test-user-2', true, 'Admin');
|
|
|
|
INSERT INTO workspace_settings (workspace_id, datatable) VALUES ('wm-fork-dt', '{
|
|
"datatables": {
|
|
"main": {"reference": {"workspace_id": "test-workspace", "datatable": "main"}}
|
|
}
|
|
}'::jsonb);
|