mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-21 08:02:38 +00:00
Putting it inside `custom_instance_pg_databases` was the wrong call, and it cost two ways. The catalog serializes a generated Postgres password per role, and that row is the operator-facing instance config, so the passwords reached `get_instance_config` and its YAML editor — a live cluster credential in a response body, a UI field and any log of either. Worse in the other direction: `to_settings_map` strips the catalog, so a full-row upsert of that key writes the row back without it and the catalog is gone, while the cluster keeps every login it described. `custom_instance_replication_pwd` is the precedent and says exactly why — a generated secret, written only by the server, never operator-authored, hidden so the config machinery cannot read, rewrite or drop it. The catalog is the same thing, so it now has the same shape: `datatable_roles`, in `HIDDEN_SETTINGS`, `PROTECTED_SETTINGS` and the agent-worker denylist. No redaction to keep in step with three code paths, and no way for a neighbouring write to take it out. Two races on the same shared documents. `edit_datatable_config` read the stored data tables outside its transaction and then wrote the whole `datatable` document, so a permissions save committing in between was silently rolled back; it now reads under `FOR UPDATE`. And `set_datatable_permissions` validated role ids against the catalog before opening its transaction, so a deletion in between let it write a deleted role back — including as the default, which every later job then fails on; it now holds the catalog lock and the settings row across validation and write. Completes the authorization contracts the previous commit claimed but did not finish: `read_datatable_entry` (which it named and missed), `resolve_governing_datatable`, whose whole job is to answer for a workspace the caller may not belong to, and `converge_connect_grants_with`, which had not inherited its wrapper's. Also the generic Python SDK reference: `_format_py_params` learned the bare `*` last time, but `extract_py_functions` is a second formatter and still rendered `datatable(name, role)`, so code written from that page passed a keyword-only argument positionally. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ti5HyeTikPMYyW8YSdiHR
45 lines
2.1 KiB
SQL
45 lines
2.1 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.
|
|
|
|
INSERT INTO global_settings (name, value) VALUES
|
|
('custom_instance_pg_databases', '{"user_pwd": "pw", "databases": {"dt_main": {}}}'::jsonb),
|
|
-- The role catalog has its own row: it holds generated credentials and must stay out of the
|
|
-- operator-facing config the neighbouring row belongs to.
|
|
('datatable_roles', '{"role1": {"name": "analytics", "enabled": true, "pwd": "pw"}}'::jsonb)
|
|
ON CONFLICT (name) DO UPDATE SET value = EXCLUDED.value;
|
|
|
|
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);
|