Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions nexus/external-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3033,6 +3033,11 @@ pub trait NexusExternalApi {
) -> Result<HttpResponseFound, HttpError>;

// Console API: Pages
//
// Dropshot does not have route match ranking and does not allow overlapping
// route definitions, so we cannot use a catchall `/*` route for console pages
// because it would overlap with the API routes definitions. So instead we have
// to manually define more specific routes.

#[endpoint {
method = GET,
Expand Down
104 changes: 104 additions & 0 deletions nexus/src/app/login.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use dropshot::{http_response_found, HttpError, HttpResponseFound};
use nexus_auth::context::OpContext;
use nexus_db_model::{ConsoleSession, Name};
use nexus_db_queries::authn::silos::IdentityProviderType;
use nexus_db_queries::db::identity::Asset;
use nexus_types::external_api::{params::RelativeUri, shared::RelayState};
use omicron_common::api::external::Error;

impl super::Nexus {
pub(crate) async fn login_saml_redirect(
&self,
opctx: &OpContext,
silo_name: &Name,
provider_name: &Name,
redirect_uri: Option<RelativeUri>,
) -> Result<HttpResponseFound, HttpError> {
let (.., identity_provider) = self
.datastore()
.identity_provider_lookup(&opctx, silo_name, provider_name)
.await?;

match identity_provider {
IdentityProviderType::Saml(saml_identity_provider) => {
// Relay state is sent to the IDP, to be sent back to the SP
// after a successful login.
let relay_state =
RelayState { redirect_uri }.to_encoded().map_err(|e| {
HttpError::for_internal_error(format!(
"encoding relay state failed: {}",
e
))
})?;

let sign_in_url = saml_identity_provider
.sign_in_url(Some(relay_state))
.map_err(|e| {
HttpError::for_internal_error(e.to_string())
})?;

http_response_found(sign_in_url)
}
}
}

pub(crate) async fn login_saml(
&self,
opctx: &OpContext,
body_bytes: dropshot::UntypedBody,
silo_name: &Name,
provider_name: &Name,
) -> Result<(ConsoleSession, String), HttpError> {
let (authz_silo, db_silo, identity_provider) = self
.datastore()
.identity_provider_lookup(&opctx, silo_name, provider_name)
.await?;
let (authenticated_subject, relay_state_string) =
match identity_provider {
IdentityProviderType::Saml(saml_identity_provider) => {
let body_bytes = dbg!(body_bytes.as_str())?;
saml_identity_provider.authenticated_subject(
&body_bytes,
self.samael_max_issue_delay(),
)?
}
};
let relay_state =
relay_state_string.and_then(|v| RelayState::from_encoded(v).ok());
let user = self
.silo_user_from_authenticated_subject(
&opctx,
&authz_silo,
&db_silo,
&authenticated_subject,
)
.await?;
let session = self.create_session(opctx, user).await?;
let next_url = relay_state
.and_then(|r| r.redirect_uri)
.map(|u| u.to_string())
.unwrap_or_else(|| "/".to_string());
Ok((session, next_url))
}

// TODO: move this logic, it's weird
pub(crate) async fn create_session(
&self,
opctx: &OpContext,
user: Option<nexus_db_queries::db::model::SiloUser>,
) -> Result<ConsoleSession, Error> {
let session = match user {
Some(user) => self.session_create(&opctx, user.id()).await?,
None => Err(Error::Unauthenticated {
internal_message: String::from(
"no matching user found or credentials were not valid",
),
})?,
};
Ok(session)
}
}
1 change: 1 addition & 0 deletions nexus/src/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ mod instance;
mod instance_network;
mod internet_gateway;
mod ip_pool;
mod login;
mod metrics;
mod network_interface;
pub(crate) mod oximeter;
Expand Down
24 changes: 5 additions & 19 deletions nexus/src/app/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,26 +46,12 @@ impl super::Nexus {
.await;

match fetch_result {
Err(e) => {
match e {
Error::ObjectNotFound { type_name: _, lookup_type: _ } => {
// if the silo user was deleted, they're not allowed to
// log in :)
return Ok(false);
}

_ => {
return Err(e);
}
}
}

Ok(_) => {
// they're allowed
}
// if the silo user was deleted, they're not allowed to log in :)
Err(Error::ObjectNotFound { .. }) => Ok(false),
Err(e) => Err(e),
// they're allowed
Ok(_) => Ok(true),
}

Ok(true)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still don't like this method, but at least it's a few lines shorter now

}

pub(crate) async fn session_create(
Expand Down
Loading
Loading