mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-18 16:02:10 +00:00
3716a71fd7
* fix: credit the token owner instead of the token label in the audit trail Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: address review findings on token-owner audit attribution Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: carry token-label provenance explicitly instead of inferring it Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * chore: point ee-repo-ref at the companion branch Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: trust only non-forgeable token labels to name the acting entity Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: reject reserved system-token labels at token creation Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: narrow the token-label guard to server-minted namespaces Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: add the provenance field to the remaining ApiAuthed literals Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * fix: stop trusting the email- label, which no mint produces Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
71 lines
2.3 KiB
Rust
71 lines
2.3 KiB
Rust
//! Postgres-trigger ancillary handlers (slot / publication / version management)
|
|
//! must reject a path-mismatched scoped token before opening any connection —
|
|
//! the route-level middleware only checks the scope domain, so per-path
|
|
//! enforcement lives in the handlers. Rejecting pre-connection is why these tests
|
|
//! need no real Postgres resource.
|
|
|
|
use axum::{extract::Path, Extension, Json};
|
|
use sqlx::{Pool, Postgres};
|
|
use windmill_api_auth::ApiAuthed;
|
|
use windmill_common::{db::UserDB, error::Error};
|
|
use windmill_trigger_postgres::{handler, Slot};
|
|
|
|
fn scoped_authed(scopes: Vec<&str>) -> ApiAuthed {
|
|
ApiAuthed {
|
|
email: "alice@windmill.dev".to_string(),
|
|
username: "alice".to_string(),
|
|
is_admin: false,
|
|
is_operator: false,
|
|
groups: vec![],
|
|
folders: vec![],
|
|
scopes: Some(scopes.into_iter().map(str::to_string).collect()),
|
|
username_override: None,
|
|
username_override_is_token_label: false,
|
|
token_prefix: None,
|
|
read_only: false,
|
|
}
|
|
}
|
|
|
|
// A token scoped to `u/alice/db` must not reach a read handler for `u/bob/db`.
|
|
#[sqlx::test]
|
|
async fn read_handler_rejects_path_mismatched_scope(db: Pool<Postgres>) -> anyhow::Result<()> {
|
|
let authed = scoped_authed(vec!["postgres_triggers:read:u/alice/db"]);
|
|
let user_db = UserDB::new(db.clone());
|
|
|
|
let res = handler::get_postgres_version(
|
|
authed,
|
|
Extension(db),
|
|
Extension(user_db),
|
|
Path(("test-workspace".to_string(), "u/bob/db".to_string())),
|
|
)
|
|
.await;
|
|
|
|
assert!(
|
|
matches!(res, Err(Error::PermissionDenied(_))),
|
|
"expected PermissionDenied, got {res:?}"
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
// The destructive slot-drop handler must reject a write token scoped to another path.
|
|
#[sqlx::test]
|
|
async fn drop_slot_rejects_path_mismatched_scope(db: Pool<Postgres>) -> anyhow::Result<()> {
|
|
let authed = scoped_authed(vec!["postgres_triggers:write:u/alice/db"]);
|
|
let user_db = UserDB::new(db.clone());
|
|
|
|
let res = handler::drop_slot_name(
|
|
authed,
|
|
Extension(user_db),
|
|
Extension(db),
|
|
Path(("test-workspace".to_string(), "u/bob/db".to_string())),
|
|
Json(Slot { name: "some_slot".to_string() }),
|
|
)
|
|
.await;
|
|
|
|
assert!(
|
|
matches!(res, Err(Error::PermissionDenied(_))),
|
|
"expected PermissionDenied, got {res:?}"
|
|
);
|
|
Ok(())
|
|
}
|