test driven fixes

This commit is contained in:
Eugene Pankov 2022-08-06 00:55:30 +02:00
parent 5a74efeae1
commit 1271dee26d
No known key found for this signature in database
GPG key ID: 5896FCBBDD1CF4F4
8 changed files with 47 additions and 25 deletions

View file

@ -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
}
}

View file

@ -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 {

View file

@ -16,6 +16,7 @@ use crate::{Secret, Target, UserSnapshot, WarpgateError};
pub enum AuthResult {
Accepted { username: String },
Need(CredentialKind),
NeedMoreCredentials,
Rejected,
}

View file

@ -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,
}
}

View file

@ -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 } => {

View file

@ -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();

View file

@ -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}

View file

@ -338,7 +338,6 @@
"enum": [
"Google",
"Apple",
"Microsoft",
"Azure",
"Custom"
]