Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
187 changes: 50 additions & 137 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ serde_bytes = { version = "0.11" }
serde_json = { version = "1.0" }
thiserror = { version = "2.0" }
tokio = { version = "1.45", features = ["fs", "macros", "signal", "rt-multi-thread"] }
tokio-util = "0.7.15"
tower = { version = "0.5" }
tower-http = { version = "0.6", features = ["compression-full", "request-id", "sensitive-headers", "trace", "util"] }
tracing = { version = "0.1" }
Expand Down
6 changes: 4 additions & 2 deletions migration/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions migration/src/m20250414_000001_idp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ impl MigrationTrait for Migration {
.col(string_len(FederatedAuthState::Nonce, 64))
.col(string_len(FederatedAuthState::RedirectUri, 256))
.col(string_len(FederatedAuthState::PkceVerifier, 64))
.col(date_time(FederatedAuthState::StartedAt))
.col(date_time(FederatedAuthState::ExpiresAt))
.col(json_null(FederatedAuthState::RequestedScope))
.foreign_key(
ForeignKey::create()
Expand Down Expand Up @@ -234,7 +234,7 @@ enum FederatedAuthState {
Nonce,
RedirectUri,
PkceVerifier,
StartedAt,
ExpiresAt,
RequestedScope,
}

Expand Down
50 changes: 48 additions & 2 deletions src/api/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ use thiserror::Error;
use tracing::error;

use crate::api::v3::federation::error::OidcError;

use crate::assignment::error::AssignmentProviderError;
use crate::auth::AuthenticationError;
use crate::catalog::error::CatalogProviderError;
use crate::federation::error::FederationProviderError;
use crate::identity::error::IdentityProviderError;
Expand All @@ -43,6 +43,9 @@ pub enum KeystoneApiError {
identifier: String,
},

#[error("Attempted to authenticate with an unsupported method.")]
AuthMethodNotSupported,

#[error("The request you have made requires authentication.")]
Unauthorized,

Expand Down Expand Up @@ -73,6 +76,12 @@ pub enum KeystoneApiError {
source: AssignmentProviderError,
},

#[error(transparent)]
AuthenticationInfo {
//#[from]
source: crate::auth::AuthenticationError,
},

#[error(transparent)]
CatalogError {
#[from]
Expand Down Expand Up @@ -163,11 +172,37 @@ impl IntoResponse for KeystoneApiError {
Json(json!({"error": {"code": StatusCode::UNAUTHORIZED.as_u16(), "message": self.to_string()}})),
).into_response()
}
KeystoneApiError::InternalError(_) | KeystoneApiError::IdentityError { .. } | KeystoneApiError::ResourceError { .. } | KeystoneApiError::AssignmentError { .. } | KeystoneApiError::TokenError{..} | KeystoneApiError::Federation {..} | KeystoneApiError::Oidc{..} | KeystoneApiError::Other(..) => {
KeystoneApiError::AuthenticationInfo{ .. } => {
(StatusCode::UNAUTHORIZED,
Json(json!({"error": {"code": StatusCode::UNAUTHORIZED.as_u16(), "message": self.to_string()}})),
).into_response()
}
KeystoneApiError::Forbidden => {
(StatusCode::FORBIDDEN,
Json(json!({"error": {"code": StatusCode::FORBIDDEN.as_u16(), "message": self.to_string()}})),
).into_response()
}
KeystoneApiError::InternalError(_) | KeystoneApiError::IdentityError { .. } | KeystoneApiError::ResourceError { .. } | KeystoneApiError::AssignmentError { .. } | KeystoneApiError::TokenError{..} | KeystoneApiError::Federation{..} | KeystoneApiError::Other(..) => {
(StatusCode::INTERNAL_SERVER_ERROR,
Json(json!({"error": {"code": StatusCode::INTERNAL_SERVER_ERROR.as_u16(), "message": self.to_string()}})),
).into_response()
}
KeystoneApiError::Oidc{ source: ref err } => {
match err {
OidcError::OpenIdConnectReqwest{..} | OidcError::OpenIdConnectConfiguration{..} => {
(
StatusCode::INTERNAL_SERVER_ERROR,
Json(json!({"error": {"code": StatusCode::INTERNAL_SERVER_ERROR.as_u16(), "message": self.to_string()}})),
).into_response()
}
_ => {
(
StatusCode::BAD_REQUEST,
Json(json!({"error": {"code": StatusCode::BAD_REQUEST.as_u16(), "message": self.to_string()}})),
).into_response()
}
}
}
_ => {
// KeystoneApiError::SubjectTokenMissing | KeystoneApiError::InvalidHeader | KeystoneApiError::InvalidToken | KeystoneApiError::Token{..} | KeystoneApiError::WebAuthN{..} | KeystoneApiError::Uuid {..} | KeystoneApiError::Serde {..} | KeystoneApiError::DomainIdOrName | KeystoneApiError::ProjectIdOrName | KeystoneApiError::ProjectDomain =>
(StatusCode::BAD_REQUEST,
Expand Down Expand Up @@ -281,3 +316,14 @@ impl IntoResponse for WebauthnError {
(StatusCode::INTERNAL_SERVER_ERROR, body).into_response()
}
}

impl From<AuthenticationError> for KeystoneApiError {
fn from(value: AuthenticationError) -> Self {
match value {
AuthenticationError::AuthenticatedInfoBuilder { source } => {
KeystoneApiError::InternalError(source.to_string())
}
other => KeystoneApiError::AuthenticationInfo { source: other },
}
}
}
14 changes: 12 additions & 2 deletions src/api/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,13 +165,14 @@ impl From<Vec<(Service, Vec<ProviderEndpoint>)>> for Catalog {
/// order to uniquely identify the project by name. A domain scope may be specified by either the
/// domain’s ID or name with equivalent results.
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, ToSchema)]
#[serde(rename_all = "lowercase")]
pub enum Scope {
/// Project scope
#[serde(rename = "project")]
Project(ProjectScope),
/// Domain scope
#[serde(rename = "domain")]
Domain(Domain),
/// System scope
System(System),
}

/// Project scope information
Expand Down Expand Up @@ -208,6 +209,15 @@ pub struct Project {
pub domain: Domain,
}

/// System scope
#[derive(Builder, Clone, Debug, Default, Deserialize, PartialEq, Serialize, ToSchema)]
#[builder(setter(into))]
pub struct System {
/// system scope
#[builder(default)]
pub all: Option<bool>,
}

impl From<resource_provider_types::Domain> for Domain {
fn from(value: resource_provider_types::Domain) -> Self {
Self {
Expand Down
Loading
Loading