mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-19 16:02:14 +00:00
fix: SAML redirect uses SAMLRequest in URL (#3168)
* fix: SAML redirect uses SAMLRequest in URL * revert samael fork and fix ce edition * simplify enterprise ff * logging to debug * rename unused variable
This commit is contained in:
committed by
GitHub
parent
75e210bfc7
commit
812516bb06
Generated
+12
-12
@@ -934,9 +934,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.14.1"
|
||||
version = "1.14.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed2490600f404f2b94c167e31d3ed1d5f3c225a0f3b80230053b3e0b7b962bd9"
|
||||
checksum = "ea31d69bda4949c1c1562c1e6f042a1caefac98cdc8a298260a2ff41c1e2d42b"
|
||||
dependencies = [
|
||||
"bytemuck_derive",
|
||||
]
|
||||
@@ -1505,9 +1505,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "curve25519-dalek"
|
||||
version = "4.1.1"
|
||||
version = "4.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c"
|
||||
checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
@@ -2077,9 +2077,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ed25519-dalek"
|
||||
version = "2.1.0"
|
||||
version = "2.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0"
|
||||
checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871"
|
||||
dependencies = [
|
||||
"curve25519-dalek",
|
||||
"ed25519",
|
||||
@@ -4162,9 +4162,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
|
||||
checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"num-traits",
|
||||
@@ -8669,9 +8669,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.10.1"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
|
||||
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
@@ -9635,9 +9635,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.5.37"
|
||||
version = "0.5.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7cad8365489051ae9f054164e459304af2e7e9bb407c958076c8bf4aef52da5"
|
||||
checksum = "5389a154b01683d28c77f8f68f49dea75f0a4da32557a58f68ee51ebba472d29"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
+1
-1
@@ -198,7 +198,7 @@ tokio-postgres = {version = "^0.7", features = ["array-impls", "with-serde_json-
|
||||
mysql_async = { version = "*", default-features = false, features = ["minimal", "default", "native-tls-tls"]}
|
||||
postgres-native-tls = "^0"
|
||||
native-tls = "^0"
|
||||
samael = { version = "0.0.14", features = ["xmlsec"] }
|
||||
samael = { version="0.0.14", features = ["xmlsec"] }
|
||||
gcp_auth = "0.9.0"
|
||||
rust_decimal = { version = "^1", features = ["db-postgres"]}
|
||||
jsonwebtoken = "8.3.0"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
use crate::db::ApiAuthed;
|
||||
use crate::embeddings::load_embeddings_db;
|
||||
use crate::oauth2::AllClients;
|
||||
use crate::saml::{SamlSsoLogin, ServiceProviderExt};
|
||||
use crate::saml::ServiceProviderExt;
|
||||
use crate::scim::has_scim_token;
|
||||
use crate::tracing_init::MyOnFailure;
|
||||
use crate::{
|
||||
@@ -164,13 +164,15 @@ pub async fn run_server(
|
||||
.allow_origin(Any);
|
||||
|
||||
#[cfg(feature = "enterprise_saml")]
|
||||
let sp_extension: (ServiceProviderExt, SamlSsoLogin) = match get_license_plan().await {
|
||||
let sp_extension: ServiceProviderExt = match get_license_plan().await {
|
||||
LicensePlan::Enterprise => saml::build_sp_extension().await?,
|
||||
LicensePlan::Pro => (ServiceProviderExt(None), SamlSsoLogin(None)),
|
||||
LicensePlan::Pro => ServiceProviderExt(None),
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "enterprise_saml"))]
|
||||
let sp_extension = (ServiceProviderExt(), SamlSsoLogin(None));
|
||||
let sp_extension = ServiceProviderExt();
|
||||
|
||||
let sp_extension_arc = Arc::new(sp_extension);
|
||||
|
||||
let embeddings_db = if server_mode {
|
||||
Some(load_embeddings_db(&db))
|
||||
@@ -242,7 +244,7 @@ pub async fn run_server(
|
||||
.nest("/oidc", oidc::global_service())
|
||||
.nest(
|
||||
"/saml",
|
||||
saml::global_service().layer(Extension(Arc::new(sp_extension.0))),
|
||||
saml::global_service().layer(Extension(Arc::clone(&sp_extension_arc))),
|
||||
)
|
||||
.nest(
|
||||
"/scim",
|
||||
@@ -274,7 +276,7 @@ pub async fn run_server(
|
||||
)
|
||||
.nest(
|
||||
"/oauth",
|
||||
oauth2::global_service().layer(Extension(Arc::new(sp_extension.1))),
|
||||
oauth2::global_service().layer(Extension(Arc::clone(&sp_extension_arc))),
|
||||
)
|
||||
.route("/version", get(git_v))
|
||||
.route("/uptodate", get(is_up_to_date))
|
||||
|
||||
@@ -41,7 +41,7 @@ use windmill_common::utils::{not_found_if_none, now_from_db};
|
||||
use windmill_common::variables::build_crypt;
|
||||
|
||||
use crate::db::ApiAuthed;
|
||||
use crate::saml::SamlSsoLogin;
|
||||
use crate::saml::{generate_redirect_url, ServiceProviderExt};
|
||||
use crate::users::{login_externally, LoginUserInfo};
|
||||
use crate::webhook_util::{InstanceEvent, WebhookShared};
|
||||
use crate::{db::DB, variables::encrypt, workspaces::WorkspaceSettings};
|
||||
@@ -446,7 +446,12 @@ struct Logins {
|
||||
oauth: Vec<String>,
|
||||
saml: Option<String>,
|
||||
}
|
||||
async fn list_logins(Extension(sso): Extension<Arc<SamlSsoLogin>>) -> error::JsonResult<Logins> {
|
||||
async fn list_logins(
|
||||
Extension(sso): Extension<Arc<ServiceProviderExt>>,
|
||||
) -> error::JsonResult<Logins> {
|
||||
let saml_redirect_opt = generate_redirect_url(sso)
|
||||
.await
|
||||
.map_err(|e| Error::InternalErr(e.to_string()))?;
|
||||
Ok(Json(Logins {
|
||||
oauth: OAUTH_CLIENTS
|
||||
.read()
|
||||
@@ -455,7 +460,7 @@ async fn list_logins(Extension(sso): Extension<Arc<SamlSsoLogin>>) -> error::Jso
|
||||
.keys()
|
||||
.map(|x| x.to_owned())
|
||||
.collect::<Vec<String>>(),
|
||||
saml: sso.0.clone(),
|
||||
saml: saml_redirect_opt,
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ use axum::response::Redirect;
|
||||
use axum::{routing::post, Router};
|
||||
#[cfg(feature = "enterprise_saml")]
|
||||
use axum::{Extension, Form};
|
||||
#[cfg(feature = "enterprise_saml")]
|
||||
use std::sync::Arc;
|
||||
|
||||
#[cfg(feature = "enterprise_saml")]
|
||||
@@ -43,10 +42,8 @@ pub struct ServiceProviderExt();
|
||||
#[cfg(feature = "enterprise_saml")]
|
||||
use windmill_common::ee::{get_license_plan, LicensePlan};
|
||||
|
||||
pub struct SamlSsoLogin(pub Option<String>);
|
||||
|
||||
#[cfg(feature = "enterprise_saml")]
|
||||
pub async fn build_sp_extension() -> anyhow::Result<(ServiceProviderExt, SamlSsoLogin)> {
|
||||
pub async fn build_sp_extension() -> anyhow::Result<ServiceProviderExt> {
|
||||
if let Some(url_metadata) = std::env::var("SAML_METADATA").ok() {
|
||||
//todo restrict for non ee
|
||||
|
||||
@@ -56,13 +53,7 @@ pub async fn build_sp_extension() -> anyhow::Result<(ServiceProviderExt, SamlSso
|
||||
// let pub_key = openssl::x509::X509::from_pem("")?;
|
||||
// let private_key = openssl::rsa::Rsa::private_key_from_pem("")?;
|
||||
|
||||
let url = idp_metadata
|
||||
.idp_sso_descriptors
|
||||
.clone()
|
||||
.unwrap_or_default()
|
||||
.get(0)
|
||||
.and_then(|x| x.single_sign_on_services.get(0).map(|x| x.location.clone()));
|
||||
|
||||
let acs_url = format!("{}/api/saml/acs", BASE_URL.read().await.clone());
|
||||
let sp = ServiceProviderBuilder::default()
|
||||
.entity_id("windmill".to_string())
|
||||
// .key(private_key)
|
||||
@@ -74,13 +65,51 @@ pub async fn build_sp_extension() -> anyhow::Result<(ServiceProviderExt, SamlSso
|
||||
..ContactPerson::default()
|
||||
})
|
||||
.idp_metadata(idp_metadata)
|
||||
.acs_url(format!("{}/api/saml/acs", BASE_URL.read().await.clone()))
|
||||
.acs_url(acs_url)
|
||||
.build()?;
|
||||
|
||||
tracing::info!("SAML Configured, sso login link at: {:?}", url);
|
||||
Ok((ServiceProviderExt(Some(sp)), SamlSsoLogin(url)))
|
||||
tracing::info!("SAML Configured - ACS url is {}", acs_url);
|
||||
Ok(ServiceProviderExt(Some(sp)))
|
||||
} else {
|
||||
Ok((ServiceProviderExt(None), SamlSsoLogin(None)))
|
||||
Ok(ServiceProviderExt(None))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "enterprise_saml"))]
|
||||
pub async fn generate_redirect_url(
|
||||
_service_provider: Arc<ServiceProviderExt>,
|
||||
) -> anyhow::Result<Option<String>> {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
#[cfg(feature = "enterprise_saml")]
|
||||
pub async fn generate_redirect_url(
|
||||
service_provider: Arc<ServiceProviderExt>,
|
||||
) -> anyhow::Result<Option<String>> {
|
||||
if let Some(sp) = &service_provider.0 {
|
||||
let url = sp
|
||||
.idp_metadata
|
||||
.idp_sso_descriptors
|
||||
.clone()
|
||||
.unwrap_or_default()
|
||||
.get(0)
|
||||
.and_then(|x| x.single_sign_on_services.get(0).map(|x| x.location.clone()));
|
||||
|
||||
let authn_req = sp
|
||||
.make_authentication_request(url.unwrap_or_default().as_str())
|
||||
.map_err(|e| anyhow::anyhow!(e.to_string()))?;
|
||||
let redirect_url = authn_req
|
||||
.redirect(BASE_URL.read().await.clone().as_str())
|
||||
.map_err(|e| anyhow::anyhow!(e.to_string()))?
|
||||
.map(|u| u.to_string());
|
||||
|
||||
tracing::debug!(
|
||||
"SAML Configured, sso login link at: {:?}",
|
||||
redirect_url.clone()
|
||||
);
|
||||
Ok(redirect_url)
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user