mirror of
https://github.com/warp-tech/warpgate.git
synced 2024-09-20 06:46:17 +08:00
test driven fixes
This commit is contained in:
parent
5a74efeae1
commit
1271dee26d
|
@ -5,6 +5,7 @@ use crate::UserRequireCredentialsPolicy;
|
|||
|
||||
pub enum CredentialPolicyResponse {
|
||||
Ok,
|
||||
NeedMoreCredentials,
|
||||
Need(CredentialKind),
|
||||
}
|
||||
|
||||
|
@ -38,9 +39,16 @@ impl CredentialPolicy for UserRequireCredentialsPolicy {
|
|||
}
|
||||
|
||||
if let Some(kind) = remaining_required_kinds.into_iter().next() {
|
||||
return CredentialPolicyResponse::Need(kind);
|
||||
CredentialPolicyResponse::Need(kind)
|
||||
} else {
|
||||
CredentialPolicyResponse::Ok
|
||||
}
|
||||
} else {
|
||||
if valid_credentials.is_empty() {
|
||||
CredentialPolicyResponse::NeedMoreCredentials
|
||||
} else {
|
||||
CredentialPolicyResponse::Ok
|
||||
}
|
||||
}
|
||||
CredentialPolicyResponse::Ok
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::time::{Duration, Instant};
|
||||
|
||||
use once_cell::sync::Lazy;
|
||||
use tracing::*;
|
||||
use tracing::warn;
|
||||
|
||||
use super::{AuthCredential, CredentialPolicy, CredentialPolicyResponse};
|
||||
use crate::AuthResult;
|
||||
|
@ -59,6 +59,9 @@ impl AuthState {
|
|||
CredentialPolicyResponse::Need(kind) => {
|
||||
return AuthResult::Need(kind);
|
||||
}
|
||||
CredentialPolicyResponse::NeedMoreCredentials => {
|
||||
return AuthResult::Rejected;
|
||||
}
|
||||
}
|
||||
}
|
||||
AuthResult::Accepted {
|
||||
|
|
|
@ -16,6 +16,7 @@ use crate::{Secret, Target, UserSnapshot, WarpgateError};
|
|||
pub enum AuthResult {
|
||||
Accepted { username: String },
|
||||
Need(CredentialKind),
|
||||
NeedMoreCredentials,
|
||||
Rejected,
|
||||
}
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@ impl From<AuthResult> for ApiAuthState {
|
|||
AuthResult::Need(CredentialKind::Otp) => ApiAuthState::OtpNeeded,
|
||||
AuthResult::Need(CredentialKind::Sso) => ApiAuthState::SsoNeeded,
|
||||
AuthResult::Need(CredentialKind::PublicKey) => ApiAuthState::Failed,
|
||||
AuthResult::NeedMoreCredentials => ApiAuthState::Failed,
|
||||
AuthResult::Accepted { .. } => ApiAuthState::Success,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -216,7 +216,9 @@ impl MySqlSession {
|
|||
}
|
||||
self.run_authorized(handshake, username, target_name).await
|
||||
}
|
||||
AuthResult::Rejected | AuthResult::Need(_) => fail(&mut self).await, // TODO SSO
|
||||
AuthResult::Rejected
|
||||
| AuthResult::Need(_)
|
||||
| AuthResult::NeedMoreCredentials => fail(&mut self).await, // TODO SSO
|
||||
}
|
||||
}
|
||||
AuthSelector::Ticket { secret } => {
|
||||
|
|
|
@ -930,16 +930,18 @@ impl ServerSession {
|
|||
match self
|
||||
.try_auth(
|
||||
&selector,
|
||||
AuthCredential::PublicKey {
|
||||
Some(AuthCredential::PublicKey {
|
||||
kind: key.name().to_string(),
|
||||
public_key_bytes: Bytes::from(key.public_key_bytes()),
|
||||
},
|
||||
}),
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(AuthResult::Accepted { .. }) => russh::server::Auth::Accept,
|
||||
Ok(AuthResult::Rejected) => russh::server::Auth::Reject,
|
||||
Ok(AuthResult::Need(_)) => russh::server::Auth::Reject,
|
||||
Ok(AuthResult::Need(_) | AuthResult::NeedMoreCredentials) => {
|
||||
russh::server::Auth::Reject
|
||||
}
|
||||
Err(error) => {
|
||||
error!(?error, "Failed to verify credentials");
|
||||
russh::server::Auth::Reject
|
||||
|
@ -956,12 +958,14 @@ impl ServerSession {
|
|||
info!("Password key auth as {:?}", selector);
|
||||
|
||||
match self
|
||||
.try_auth(&selector, AuthCredential::Password(password))
|
||||
.try_auth(&selector, Some(AuthCredential::Password(password)))
|
||||
.await
|
||||
{
|
||||
Ok(AuthResult::Accepted { .. }) => russh::server::Auth::Accept,
|
||||
Ok(AuthResult::Rejected) => russh::server::Auth::Reject,
|
||||
Ok(AuthResult::Need(_)) => russh::server::Auth::Reject,
|
||||
Ok(AuthResult::Need(_) | AuthResult::NeedMoreCredentials) => {
|
||||
russh::server::Auth::Reject
|
||||
}
|
||||
Err(error) => {
|
||||
error!(?error, "Failed to verify credentials");
|
||||
russh::server::Auth::Reject
|
||||
|
@ -977,14 +981,15 @@ impl ServerSession {
|
|||
let selector: AuthSelector = ssh_username.expose_secret().into();
|
||||
info!("Keyboard-interactive auth as {:?}", selector);
|
||||
|
||||
let Some(otp) = response else {
|
||||
return russh::server::Auth::Reject
|
||||
};
|
||||
let cred = response.map(|otp| AuthCredential::Otp(otp));
|
||||
|
||||
match self.try_auth(&selector, AuthCredential::Otp(otp)).await {
|
||||
match self.try_auth(&selector, cred).await {
|
||||
Ok(AuthResult::Accepted { .. }) => russh::server::Auth::Accept,
|
||||
Ok(AuthResult::Rejected) => russh::server::Auth::Reject,
|
||||
Ok(AuthResult::Need(CredentialKind::Otp)) => russh::server::Auth::Partial {
|
||||
Ok(
|
||||
AuthResult::Rejected
|
||||
| AuthResult::NeedMoreCredentials
|
||||
| AuthResult::Need(CredentialKind::Otp),
|
||||
) => russh::server::Auth::Partial {
|
||||
name: Cow::Borrowed("Two-factor authentication"),
|
||||
instructions: Cow::Borrowed(""),
|
||||
prompts: Cow::Owned(vec![(Cow::Borrowed("One-time password: "), true)]),
|
||||
|
@ -1000,7 +1005,7 @@ impl ServerSession {
|
|||
async fn try_auth(
|
||||
&mut self,
|
||||
selector: &AuthSelector,
|
||||
credential: AuthCredential,
|
||||
credential: Option<AuthCredential>,
|
||||
) -> Result<AuthResult> {
|
||||
match selector {
|
||||
AuthSelector::User {
|
||||
|
@ -1009,13 +1014,16 @@ impl ServerSession {
|
|||
} => {
|
||||
let cp = self.services.config_provider.clone();
|
||||
let state = self.get_auth_state(username).await?;
|
||||
if cp
|
||||
.lock()
|
||||
.await
|
||||
.validate_credential(username, &credential)
|
||||
.await?
|
||||
{
|
||||
state.add_valid_credential(credential);
|
||||
|
||||
if let Some(credential) = credential {
|
||||
if cp
|
||||
.lock()
|
||||
.await
|
||||
.validate_credential(username, &credential)
|
||||
.await?
|
||||
{
|
||||
state.add_valid_credential(credential);
|
||||
}
|
||||
}
|
||||
|
||||
let user_auth_result = state.verify();
|
||||
|
|
|
@ -187,7 +187,7 @@ async function startSSO (provider: SsoProviderDescription) {
|
|||
{#if ssoProvider.kind === SsoProviderKind.Google}
|
||||
<Fa fw class="me-2" icon={faGoogle} />
|
||||
{/if}
|
||||
{#if ssoProvider.kind === SsoProviderKind.Microsoft || ssoProvider.kind === SsoProviderKind.Azure}
|
||||
{#if ssoProvider.kind === SsoProviderKind.Azure}
|
||||
<Fa fw class="me-2" icon={faMicrosoft} />
|
||||
{/if}
|
||||
{#if ssoProvider.kind === SsoProviderKind.Apple}
|
||||
|
|
|
@ -338,7 +338,6 @@
|
|||
"enum": [
|
||||
"Google",
|
||||
"Apple",
|
||||
"Microsoft",
|
||||
"Azure",
|
||||
"Custom"
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue