Skip to content

Commit

Permalink
Credential policies
Browse files Browse the repository at this point in the history
  • Loading branch information
Eugeny committed Jul 5, 2022
1 parent 93a1259 commit 890c5d8
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 16 deletions.
10 changes: 9 additions & 1 deletion warpgate-common/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,12 +127,20 @@ pub enum UserAuthCredential {
},
}

#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct UserRequireCredentialsPolicy {
#[serde(skip_serializing_if = "Option::is_none")]
pub http: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ssh: Option<Vec<String>>,
}

#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct User {
pub username: String,
pub credentials: Vec<UserAuthCredential>,
#[serde(skip_serializing_if = "Option::is_none")]
pub require: Option<Vec<String>>,
pub require: Option<UserRequireCredentialsPolicy>,
pub roles: Vec<String>,
}

Expand Down
31 changes: 21 additions & 10 deletions warpgate-common/src/config_providers/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use super::ConfigProvider;
use crate::helpers::hash::verify_password_hash;
use crate::helpers::otp::verify_totp;
use crate::{
AuthCredential, AuthResult, Target, User, UserAuthCredential, UserSnapshot, WarpgateConfig,
AuthCredential, AuthResult, ProtocolName, Target, User, UserAuthCredential, UserSnapshot,
WarpgateConfig,
};
use anyhow::Result;
use async_trait::async_trait;
Expand Down Expand Up @@ -71,6 +72,7 @@ impl ConfigProvider for FileConfigProvider {
&mut self,
username: &str,
credentials: &[AuthCredential],
protocol: ProtocolName,
) -> Result<AuthResult> {
if credentials.is_empty() {
return Ok(AuthResult::Rejected);
Expand Down Expand Up @@ -159,8 +161,16 @@ impl ConfigProvider for FileConfigProvider {
);
}

match user.require {
Some(ref required_kinds) => {
if let Some(ref policy) = user.require {
let required_kinds = match protocol {
"SSH" => &policy.ssh,
"HTTP" => &policy.http,
_ => {
error!(%protocol, "Unkown protocol");
return Ok(AuthResult::Rejected);
}
};
if let Some(required_kinds) = required_kinds {
let mut remaining_required_kinds = HashSet::new();
remaining_required_kinds.extend(required_kinds);
for kind in required_kinds {
Expand All @@ -181,14 +191,15 @@ impl ConfigProvider for FileConfigProvider {
return Ok(AuthResult::Rejected);
}
}
None => Ok(if !valid_credentials.is_empty() {
AuthResult::Accepted {
username: user.username.clone(),
}
} else {
AuthResult::Rejected
}),
}

Ok(if !valid_credentials.is_empty() {
AuthResult::Accepted {
username: user.username.clone(),
}
} else {
AuthResult::Rejected
})
}

async fn authorize_target(&mut self, username: &str, target_name: &str) -> Result<bool> {
Expand Down
3 changes: 2 additions & 1 deletion warpgate-common/src/config_providers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
mod file;
use crate::{Secret, Target, UserSnapshot};
use crate::{ProtocolName, Secret, Target, UserSnapshot};
use anyhow::Result;
use async_trait::async_trait;
use bytes::Bytes;
Expand Down Expand Up @@ -36,6 +36,7 @@ pub trait ConfigProvider {
&mut self,
username: &str,
credentials: &[AuthCredential],
protocol: ProtocolName,
) -> Result<AuthResult>;

async fn authorize_target(&mut self, username: &str, target: &str) -> Result<bool>;
Expand Down
2 changes: 1 addition & 1 deletion warpgate-protocol-http/src/api/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ impl Api {
let result = {
let mut config_provider = services.config_provider.lock().await;
config_provider
.authorize(&body.username, &credentials)
.authorize(&body.username, &credentials, crate::common::PROTOCOL_NAME)
.await
.map_err(|e| e.context("Failed to authorize user"))?
};
Expand Down
2 changes: 1 addition & 1 deletion warpgate-protocol-ssh/src/server/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -952,7 +952,7 @@ impl ServerSession {
.config_provider
.lock()
.await
.authorize(username, &self.credentials)
.authorize(username, &self.credentials, crate::PROTOCOL_NAME)
.await?
};

Expand Down
45 changes: 43 additions & 2 deletions warpgate/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,18 @@ pub fn load_config(path: &Path, secure: bool) -> Result<WarpgateConfig> {
secure_file(path).context("Could not secure config")?;
}

let store: WarpgateConfigStore = Config::builder()
let mut store: serde_yaml::Value = Config::builder()
.add_source(File::from(path))
.add_source(Environment::with_prefix("WARPGATE"))
.build()
.context("Could not load config")?
.try_deserialize()
.context("Could not parse config")?;
.context("Could not parse YAML")?;

check_and_migrate_config(&mut store);

let store: WarpgateConfigStore =
serde_yaml::from_value(store).context("Could not load config")?;

let config = WarpgateConfig {
store,
Expand All @@ -35,6 +40,42 @@ pub fn load_config(path: &Path, secure: bool) -> Result<WarpgateConfig> {
Ok(config)
}

fn check_and_migrate_config(store: &mut serde_yaml::Value) {
use serde_yaml::Value;
if let Some(map) = store.as_mapping_mut() {
if let Some(web_admin) = map.remove(&Value::String("web_admin".into())) {
warn!("The `web_admin` config section is deprecated. Rename it to `http`.");
map.insert(Value::String("http".into()), web_admin);
}

if let Some(Value::Sequence(ref mut users)) = map.get_mut(&Value::String("users".into())) {
for user in users {
if let Value::Mapping(ref mut user) = user {
if let Some(new_require) = match user.get(&Value::String("require".into())) {
Some(Value::Sequence(ref old_requires)) => Some(Value::Mapping(
vec![
(
Value::String("ssh".into()),
Value::Sequence(old_requires.clone()),
),
(
Value::String("http".into()),
Value::Sequence(old_requires.clone()),
),
]
.into_iter()
.collect(),
)),
x => x.cloned(),
} {
user.insert(Value::String("require".into()), new_require);
}
}
}
}
}
}

pub async fn watch_config<P: AsRef<Path>>(
path: P,
config: Arc<Mutex<WarpgateConfig>>,
Expand Down

0 comments on commit 890c5d8

Please sign in to comment.