mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-03 16:02:12 +00:00
* feat: restricted job tokens (job_token_scopes on scripts and flows) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: admit flow-run reads, skip dedicated workers, gate on worker version Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: keep restricted jobs off flow runners, preserve scopes on rename and promotion Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: keep restricted jobs off every dedicated handoff, confine progress flow id Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: exclude restricted runnables from dedicated worker startup Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: gate restrictions on the release after 1.821.0 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * fix: store per-job scopes on job_perms instead of v2_job, pin inline runs to the checked version Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * feat: step-level job_token_scopes for flow steps and agent tools Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * fix: fail closed on perms read errors, refuse restricted queue imports, gate step scopes in previews Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * fix: carry a job's scopes on its completion so a re-run keeps the caller's cap Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * fix: carry a zombie job's scopes into its completion Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * fix: leave a zombie for the next sweep when its scopes cannot be read Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * docs: correct the QueuedJobV2 completion comment Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * fix: validate step scopes in batch flows, fail closed on unvalidated step scopes Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * fix: refuse flows with step or tool restrictions at push while an older worker is live Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * fix: apply the step-scope worker gate to flow restarts Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * fix: list the job token toggle with the other step and flow settings Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * chore: pin the EE companion merged with EE main Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * perf: skip scope lookups for unrestricted jobs; list job token setting last Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * style: rustfmt scopes tests Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * fix: confine restricted job tokens to their own run lineage; drop remaining extra lookups Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FHGE3ynoAu6yrgeg4kLwL * chore: update ee-repo-ref to 259ad3bfeef5285ba80eedc86309b11dca001220 This commit updates the EE repository reference after PR #843 was merged in windmill-ee-private. Previous ee-repo-ref: 2b77c0225dca441235daf7bf0a06ba968df0c927 New ee-repo-ref: 259ad3bfeef5285ba80eedc86309b11dca001220 Automated by sync-ee-ref workflow. --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Co-authored-by: windmill-internal-app[bot] <windmill-internal-app[bot]@users.noreply.github.com>
113 lines
3.6 KiB
Rust
113 lines
3.6 KiB
Rust
//! A caller's `_MODULES` never reaches a job: the worker builds that arg in as module code,
|
|
//! so on a deployed runnable it would run caller code as the runnable (and its
|
|
//! `on_behalf_of`). `push` drops it from `args` and `extra` alike and only sets it from a
|
|
//! preview's own `RawCode::modules`.
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use serde_json::{json, value::RawValue};
|
|
use sqlx::{Pool, Postgres};
|
|
use windmill_common::{
|
|
jobs::{JobPayload, RawCode},
|
|
runnable_settings::{ConcurrencySettings, DebouncingSettings},
|
|
scripts::{ScriptHash, ScriptLang, ScriptModule},
|
|
};
|
|
use windmill_queue::{PushArgs, PushIsolationLevel};
|
|
|
|
fn modules(v: &str) -> serde_json::Value {
|
|
json!({ "helper.ts": { "content": format!("export const v = \"{v}\""), "language": "bun" } })
|
|
}
|
|
|
|
/// Pushes `payload` with a caller `_MODULES` both in `args` and in `extra` (where webhook
|
|
/// query and headers land), and returns the stored `_MODULES`.
|
|
async fn stored_modules(db: &Pool<Postgres>, payload: JobPayload) -> Option<serde_json::Value> {
|
|
let caller: Box<RawValue> = serde_json::value::to_raw_value(&modules("caller")).unwrap();
|
|
let args = HashMap::from([("_MODULES".to_string(), caller.clone())]);
|
|
let extra = HashMap::from([("_MODULES".to_string(), caller)]);
|
|
let (id, tx) = windmill_queue::push(
|
|
db,
|
|
PushIsolationLevel::IsolatedRoot(db.clone()),
|
|
"test-workspace",
|
|
payload,
|
|
PushArgs { args: &args, extra: Some(extra) },
|
|
"test-user",
|
|
"test@windmill.dev",
|
|
"u/test-user".to_string(),
|
|
None,
|
|
None,
|
|
None,
|
|
None,
|
|
None,
|
|
None,
|
|
None,
|
|
None,
|
|
false,
|
|
false,
|
|
None,
|
|
true,
|
|
None,
|
|
None,
|
|
None,
|
|
None,
|
|
None,
|
|
false,
|
|
None,
|
|
None,
|
|
None,
|
|
None,
|
|
)
|
|
.await
|
|
.expect("push must succeed");
|
|
tx.commit().await.unwrap();
|
|
sqlx::query_scalar::<_, Option<serde_json::Value>>(
|
|
"SELECT args->'_MODULES' FROM v2_job WHERE id = $1",
|
|
)
|
|
.bind(id)
|
|
.fetch_one(db)
|
|
.await
|
|
.unwrap()
|
|
}
|
|
|
|
#[sqlx::test(fixtures("base"))]
|
|
async fn caller_modules_never_reach_a_job(db: Pool<Postgres>) {
|
|
let deployed = JobPayload::ScriptHash {
|
|
hash: ScriptHash(123412),
|
|
path: "f/system/hello".to_string(),
|
|
cache_ttl: None,
|
|
cache_ignore_s3_path: None,
|
|
dedicated_worker: None,
|
|
language: ScriptLang::Bun,
|
|
priority: None,
|
|
apply_preprocessor: false,
|
|
concurrency_settings: ConcurrencySettings::default(),
|
|
debouncing_settings: DebouncingSettings::default(),
|
|
labels: None,
|
|
job_token_scopes: None,
|
|
};
|
|
assert_eq!(stored_modules(&db, deployed).await, None);
|
|
|
|
let preview = |modules: Option<HashMap<String, ScriptModule>>| {
|
|
JobPayload::Code(RawCode {
|
|
hash: None,
|
|
content: "import { v } from \"./helper\"; export function main() { return v }"
|
|
.to_string(),
|
|
path: None,
|
|
language: ScriptLang::Bun,
|
|
lock: None,
|
|
concurrency_settings: ConcurrencySettings::default().into(),
|
|
debouncing_settings: DebouncingSettings::default(),
|
|
cache_ttl: None,
|
|
cache_ignore_s3_path: None,
|
|
dedicated_worker: None,
|
|
modules,
|
|
tag: None,
|
|
})
|
|
};
|
|
assert_eq!(stored_modules(&db, preview(None)).await, None);
|
|
let own = serde_json::from_value(modules("preview")).unwrap();
|
|
assert_eq!(
|
|
stored_modules(&db, preview(Some(own))).await,
|
|
Some(modules("preview"))
|
|
);
|
|
}
|