From 247acb69cd5b10f2433f2103ca426f4a829b3ea4 Mon Sep 17 00:00:00 2001 From: HugoCasa Date: Thu, 12 Jun 2025 21:37:50 +0200 Subject: [PATCH] fix: audit logs for token refresh + consider refresh for active users (#5930) * fix: audit logs for token refresh + consider refresh for active users * tmp repo ref --- ...e6733943278998d3df62a9486607827e59ec.json} | 4 +- ...ca43f00456a27fda32583846497116f92f96c.json | 38 +++++++++++++++++++ ...679366bb07bc6a100727721a787160ac6910c.json | 38 ------------------- backend/ee-repo-ref.txt | 2 +- backend/windmill-api/src/users.rs | 19 +++++++++- 5 files changed, 58 insertions(+), 43 deletions(-) rename backend/.sqlx/{query-3895cee539a24b4c6ea89fa7a835fc62bc93b0530efba09fc3c32a8f93eaabb1.json => query-5430f7728c1e9b539cc8aad29ca9e6733943278998d3df62a9486607827e59ec.json} (68%) create mode 100644 backend/.sqlx/query-cb3862634f18160207ee2621ddfca43f00456a27fda32583846497116f92f96c.json delete mode 100644 backend/.sqlx/query-cce991f582bc9d2ba28a5b2b41c679366bb07bc6a100727721a787160ac6910c.json diff --git a/backend/.sqlx/query-3895cee539a24b4c6ea89fa7a835fc62bc93b0530efba09fc3c32a8f93eaabb1.json b/backend/.sqlx/query-5430f7728c1e9b539cc8aad29ca9e6733943278998d3df62a9486607827e59ec.json similarity index 68% rename from backend/.sqlx/query-3895cee539a24b4c6ea89fa7a835fc62bc93b0530efba09fc3c32a8f93eaabb1.json rename to backend/.sqlx/query-5430f7728c1e9b539cc8aad29ca9e6733943278998d3df62a9486607827e59ec.json index 66431239db..f3961847f4 100644 --- a/backend/.sqlx/query-3895cee539a24b4c6ea89fa7a835fc62bc93b0530efba09fc3c32a8f93eaabb1.json +++ b/backend/.sqlx/query-5430f7728c1e9b539cc8aad29ca9e6733943278998d3df62a9486607827e59ec.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "WITH active_users AS (SELECT distinct username as email FROM audit WHERE timestamp > NOW() - INTERVAL '1 month' AND (operation = 'users.login' OR operation = 'oauth.login')),\n authors as (SELECT distinct email FROM usr WHERE usr.operator IS false)\n SELECT email, email NOT IN (SELECT email FROM authors) as operator_only, login_type::text, verified, super_admin, devops, name, company, username\n FROM password\n WHERE email IN (SELECT email FROM active_users)\n ORDER BY super_admin DESC, devops DESC\n LIMIT $1 OFFSET $2", + "query": "WITH active_users AS (SELECT distinct username as email FROM audit WHERE timestamp > NOW() - INTERVAL '1 month' AND (operation = 'users.login' OR operation = 'oauth.login' OR operation = 'users.token.refresh')),\n authors as (SELECT distinct email FROM usr WHERE usr.operator IS false)\n SELECT email, email NOT IN (SELECT email FROM authors) as operator_only, login_type::text, verified, super_admin, devops, name, company, username\n FROM password\n WHERE email IN (SELECT email FROM active_users)\n ORDER BY super_admin DESC, devops DESC\n LIMIT $1 OFFSET $2", "describe": { "columns": [ { @@ -67,5 +67,5 @@ true ] }, - "hash": "3895cee539a24b4c6ea89fa7a835fc62bc93b0530efba09fc3c32a8f93eaabb1" + "hash": "5430f7728c1e9b539cc8aad29ca9e6733943278998d3df62a9486607827e59ec" } diff --git a/backend/.sqlx/query-cb3862634f18160207ee2621ddfca43f00456a27fda32583846497116f92f96c.json b/backend/.sqlx/query-cb3862634f18160207ee2621ddfca43f00456a27fda32583846497116f92f96c.json new file mode 100644 index 0000000000..8ccf623719 --- /dev/null +++ b/backend/.sqlx/query-cb3862634f18160207ee2621ddfca43f00456a27fda32583846497116f92f96c.json @@ -0,0 +1,38 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH active_users as (SELECT distinct username as email FROM audit WHERE timestamp > NOW() - INTERVAL '1 month' AND (operation = 'users.login' OR operation = 'oauth.login' OR operation = 'users.token.refresh')),\n active_authors as (SELECT distinct email FROM usr WHERE usr.operator IS false AND email IN (SELECT email FROM active_users)),\n active_authors_agg as (SELECT array_agg(email) as authors FROM active_authors),\n active_ops_agg as (SELECT array_agg(email) as operators from active_users WHERE email NOT IN (SELECT email FROM active_authors))\n SELECT active_authors_agg.authors, active_ops_agg.operators, array_length(active_authors_agg.authors, 1) as author_count, array_length(active_ops_agg.operators, 1) as operator_count FROM active_authors_agg, active_ops_agg", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "authors", + "type_info": "VarcharArray" + }, + { + "ordinal": 1, + "name": "operators", + "type_info": "VarcharArray" + }, + { + "ordinal": 2, + "name": "author_count", + "type_info": "Int4" + }, + { + "ordinal": 3, + "name": "operator_count", + "type_info": "Int4" + } + ], + "parameters": { + "Left": [] + }, + "nullable": [ + null, + null, + null, + null + ] + }, + "hash": "cb3862634f18160207ee2621ddfca43f00456a27fda32583846497116f92f96c" +} diff --git a/backend/.sqlx/query-cce991f582bc9d2ba28a5b2b41c679366bb07bc6a100727721a787160ac6910c.json b/backend/.sqlx/query-cce991f582bc9d2ba28a5b2b41c679366bb07bc6a100727721a787160ac6910c.json deleted file mode 100644 index f5d905a157..0000000000 --- a/backend/.sqlx/query-cce991f582bc9d2ba28a5b2b41c679366bb07bc6a100727721a787160ac6910c.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "WITH active_users as (SELECT distinct username as email FROM audit WHERE timestamp > NOW() - INTERVAL '1 month' AND (operation = 'users.login' OR operation = 'oauth.login')),\n active_authors as (SELECT distinct email FROM usr WHERE usr.operator IS false AND email IN (SELECT email FROM active_users)),\n active_authors_agg as (SELECT array_agg(email) as authors FROM active_authors),\n active_ops_agg as (SELECT array_agg(email) as operators from active_users WHERE email NOT IN (SELECT email FROM active_authors))\n SELECT active_authors_agg.authors, active_ops_agg.operators, array_length(active_authors_agg.authors, 1) as author_count, array_length(active_ops_agg.operators, 1) as operator_count FROM active_authors_agg, active_ops_agg", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "authors", - "type_info": "VarcharArray" - }, - { - "ordinal": 1, - "name": "operators", - "type_info": "VarcharArray" - }, - { - "ordinal": 2, - "name": "author_count", - "type_info": "Int4" - }, - { - "ordinal": 3, - "name": "operator_count", - "type_info": "Int4" - } - ], - "parameters": { - "Left": [] - }, - "nullable": [ - null, - null, - null, - null - ] - }, - "hash": "cce991f582bc9d2ba28a5b2b41c679366bb07bc6a100727721a787160ac6910c" -} diff --git a/backend/ee-repo-ref.txt b/backend/ee-repo-ref.txt index fe8033ab6e..18e55e2434 100644 --- a/backend/ee-repo-ref.txt +++ b/backend/ee-repo-ref.txt @@ -1 +1 @@ -ab4f856708a056973faea19f10eda5efff546176 +c39fec179a5a54d7b0629a568166c1d5dd6d9f33 diff --git a/backend/windmill-api/src/users.rs b/backend/windmill-api/src/users.rs index da77337703..58e9d2d849 100644 --- a/backend/windmill-api/src/users.rs +++ b/backend/windmill-api/src/users.rs @@ -542,7 +542,7 @@ async fn list_users_as_super_admin( let rows = if active_only.is_some_and(|x| x) { sqlx::query_as!( GlobalUserInfo, - "WITH active_users AS (SELECT distinct username as email FROM audit WHERE timestamp > NOW() - INTERVAL '1 month' AND (operation = 'users.login' OR operation = 'oauth.login')), + "WITH active_users AS (SELECT distinct username as email FROM audit WHERE timestamp > NOW() - INTERVAL '1 month' AND (operation = 'users.login' OR operation = 'oauth.login' OR operation = 'users.token.refresh')), authors as (SELECT distinct email FROM usr WHERE usr.operator IS false) SELECT email, email NOT IN (SELECT email FROM authors) as operator_only, login_type::text, verified, super_admin, devops, name, company, username FROM password @@ -1750,7 +1750,22 @@ async fn refresh_token( .await? .unwrap_or(false); - let _ = create_session_token(&authed.email, super_admin, &mut tx, cookies).await?; + let new_token = create_session_token(&authed.email, super_admin, &mut tx, cookies).await?; + + audit_log( + &mut *tx, + &AuditAuthor { + email: authed.email.to_string(), + username: authed.email.to_string(), + username_override: None, + }, + "users.token.refresh", + ActionKind::Create, + &"global", + Some(&truncate_token(&new_token)), + None, + ) + .await?; tx.commit().await?; Ok("token refreshed".to_string())