mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-21 00:02:30 +00:00
fix: let the hub_sync job read the uid and hub_base_url settings (#11106)
Claude-Session: https://claude.ai/code/session_01Q6triDksvGJ4YK2gA1acEc Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
62d4632fad
commit
45102c8265
@@ -318,19 +318,35 @@ async fn test_wm_token_is_confined_to_its_workspace(db: Pool<Postgres>) -> anyho
|
||||
resp.text().await?
|
||||
);
|
||||
}
|
||||
// ...and the one `settings/global` key on the allowlist, which the CLI reads before
|
||||
// creating a user on a git-sync push. `ws_base_url` is the control: the handler leaves
|
||||
// it as ungated as `automate_username_creation`, so only the allowlist stops it.
|
||||
// ...and the `settings/global` keys on the allowlist, which the CLI reads from a job: on a
|
||||
// git-sync push, and in `u/admin/hub_sync`. `ws_base_url` is the control: the handler
|
||||
// leaves it as ungated as these, so only the allowlist stops it.
|
||||
for key in ["automate_username_creation", "uid", "hub_base_url"] {
|
||||
let resp = authed(
|
||||
client().get(format!("{api}/settings/global/{key}")),
|
||||
&user_wm,
|
||||
)
|
||||
.send()
|
||||
.await?;
|
||||
assert_eq!(
|
||||
resp.status(),
|
||||
200,
|
||||
"WM_TOKEN must still read {key}: {}",
|
||||
resp.text().await?
|
||||
);
|
||||
}
|
||||
// The same hub pull reads `hub_api_secret` for a private Hub, but a secret stays out of
|
||||
// a job's reach even when the token borrows a superadmin.
|
||||
let resp = authed(
|
||||
client().get(format!("{api}/settings/global/automate_username_creation")),
|
||||
&user_wm,
|
||||
client().get(format!("{api}/settings/global/hub_api_secret")),
|
||||
&sa_wm,
|
||||
)
|
||||
.send()
|
||||
.await?;
|
||||
assert_eq!(
|
||||
resp.status(),
|
||||
200,
|
||||
"WM_TOKEN must still read automate_username_creation: {}",
|
||||
let status = resp.status().as_u16();
|
||||
assert!(
|
||||
status == 401 || status == 403,
|
||||
"superadmin WM_TOKEN must not read hub_api_secret ({status}): {}",
|
||||
resp.text().await?
|
||||
);
|
||||
let resp = authed(
|
||||
|
||||
@@ -1073,12 +1073,15 @@ fn scope_grants_access(
|
||||
/// the caller's own row; `email` and `allowed_domain_auto_invite` are derived from the
|
||||
/// token itself and touch no table.
|
||||
///
|
||||
/// `settings/global/automate_username_creation` is the one instance setting on the list.
|
||||
/// `get_global_setting` exempts a handful of keys from its own super-admin gate, that one
|
||||
/// among them, so the boolean is already readable by every authenticated user; it is here
|
||||
/// because the CLI reads it before creating a user during a git-sync push, which runs as a
|
||||
/// job. The other ungated keys have no such caller, so they stay confined — being ungated
|
||||
/// earns a key nothing on its own.
|
||||
/// Three instance settings are on the list. `get_global_setting` exempts a handful of keys
|
||||
/// from its own super-admin gate, these among them, so each is already readable by every
|
||||
/// authenticated user; each is here because the CLI reads it from a job:
|
||||
/// `automate_username_creation` before creating a user during a git-sync push, `uid` and
|
||||
/// `hub_base_url` when `u/admin/hub_sync` pulls resource types from the Hub. The other
|
||||
/// ungated keys have no such caller, so they stay confined — being ungated earns a key
|
||||
/// nothing on its own. Listing a gated key earns it nothing either: `require_super_admin`
|
||||
/// refuses every job token, so `hub_api_secret`, which that pull reads for a private Hub,
|
||||
/// stays out of a job's reach whatever this list says.
|
||||
///
|
||||
/// Deliberately absent, as each crosses that line: `users/list_invites` (returns the
|
||||
/// workspace ids the identity was invited to), `users/tokens/list` (credential metadata
|
||||
@@ -1096,6 +1099,8 @@ fn is_global_read_open_to_job_token(route_path: &str) -> bool {
|
||||
| "/api/users/tutorial_progress"
|
||||
| "/api/workspaces/allowed_domain_auto_invite"
|
||||
| "/api/settings/global/automate_username_creation"
|
||||
| "/api/settings/global/uid"
|
||||
| "/api/settings/global/hub_base_url"
|
||||
| "/api/docs/search"
|
||||
| "/api/docs/page"
|
||||
| "/api/integrations/hub/list"
|
||||
|
||||
@@ -61,7 +61,7 @@ use windmill_common::{
|
||||
GITHUB_APP_WEBHOOK_BASE_URL_SETTING, HTTP_ROUTE_WORKSPACED_ROUTE_SETTING,
|
||||
HUB_ACCESSIBLE_URL_SETTING, HUB_BASE_URL_SETTING, INSTANCE_BANNER_SETTING,
|
||||
MAX_RETENTION_OVERRIDE_WORKSPACES, RETENTION_PERIOD_SECS_OVERRIDES_SETTING,
|
||||
RUFF_CONFIG_SETTING, WORKSPACE_FAIRNESS_DURATION_SECS_SETTING,
|
||||
RUFF_CONFIG_SETTING, UNIQUE_ID_SETTING, WORKSPACE_FAIRNESS_DURATION_SECS_SETTING,
|
||||
WORKSPACE_FAIRNESS_ENABLED_SETTING, WORKSPACE_FAIRNESS_MAX_PERCENT_SETTING,
|
||||
WORKSPACE_FAIRNESS_MIN_TOTAL_SETTING, WS_BASE_URL_SETTING,
|
||||
},
|
||||
@@ -1321,6 +1321,9 @@ pub async fn get_global_setting(
|
||||
&& key != AUTOMATE_USERNAME_CREATION_SETTING
|
||||
&& key != DEFAULT_TAGS_WORKSPACES_SETTING
|
||||
&& key != HUB_BASE_URL_SETTING
|
||||
// `wmill hub pull` reads it from a job, and no job token clears the gate. It binds an
|
||||
// offline license only together with `license_key`, which stays gated.
|
||||
&& key != UNIQUE_ID_SETTING
|
||||
&& key != HUB_ACCESSIBLE_URL_SETTING
|
||||
&& key != DISABLE_HUB_SETTING
|
||||
&& key != EMAIL_DOMAIN_SETTING
|
||||
|
||||
Reference in New Issue
Block a user