api: rustfmt

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
Thomas Lamprecht
2022-04-14 13:33:01 +02:00
parent 35f151e010
commit dc7a5b3491
53 changed files with 2703 additions and 1864 deletions

View File

@ -3,13 +3,12 @@
use anyhow::{bail, Error};
use hex::FromHex;
use proxmox_router::{Router, RpcEnvironment, Permission};
use proxmox_router::{Permission, Router, RpcEnvironment};
use proxmox_schema::api;
use pbs_api_types::{
Authid, AclListItem, Role,
ACL_PATH_SCHEMA, PROXMOX_CONFIG_DIGEST_SCHEMA, PROXMOX_GROUP_ID_SCHEMA,
ACL_PROPAGATE_SCHEMA, PRIV_SYS_AUDIT, PRIV_PERMISSIONS_MODIFY,
AclListItem, Authid, Role, ACL_PATH_SCHEMA, ACL_PROPAGATE_SCHEMA, PRIV_PERMISSIONS_MODIFY,
PRIV_SYS_AUDIT, PROXMOX_CONFIG_DIGEST_SCHEMA, PROXMOX_GROUP_ID_SCHEMA,
};
use pbs_config::acl::AclTreeNode;
@ -32,15 +31,18 @@ fn extract_acl_node_data(
for (user, roles) in &node.users {
if let Some(auth_id_filter) = auth_id_filter {
if !user.is_token()
|| user.user() != auth_id_filter.user() {
continue;
if !user.is_token() || user.user() != auth_id_filter.user() {
continue;
}
}
for (role, propagate) in roles {
list.push(AclListItem {
path: if path.is_empty() { String::from("/") } else { path.to_string() },
path: if path.is_empty() {
String::from("/")
} else {
path.to_string()
},
propagate: *propagate,
ugid_type: String::from("user"),
ugid: user.to_string(),
@ -55,7 +57,11 @@ fn extract_acl_node_data(
for (role, propagate) in roles {
list.push(AclListItem {
path: if path.is_empty() { String::from("/") } else { path.to_string() },
path: if path.is_empty() {
String::from("/")
} else {
path.to_string()
},
propagate: *propagate,
ugid_type: String::from("group"),
ugid: group.to_string(),
@ -201,8 +207,10 @@ pub fn update_acl(
} else if auth_id.user() != current_auth_id.user() {
bail!("Unprivileged users can only set ACL items for their own API tokens.");
}
},
None => { bail!("Unprivileged user needs to provide auth_id to update ACL item."); },
}
None => {
bail!("Unprivileged user needs to provide auth_id to update ACL item.");
}
};
}
@ -222,18 +230,26 @@ pub fn update_acl(
if let Some(ref _group) = group {
bail!("parameter 'group' - groups are currently not supported.");
} else if let Some(ref auth_id) = auth_id {
if !delete { // Note: we allow to delete non-existent users
if !delete {
// Note: we allow to delete non-existent users
let user_cfg = pbs_config::user::cached_config()?;
if user_cfg.sections.get(&auth_id.to_string()).is_none() {
bail!(format!("no such {}.",
if auth_id.is_token() { "API token" } else { "user" }));
bail!(format!(
"no such {}.",
if auth_id.is_token() {
"API token"
} else {
"user"
}
));
}
}
} else {
bail!("missing 'userid' or 'group' parameter.");
}
if !delete { // Note: we allow to delete entries with invalid path
if !delete {
// Note: we allow to delete entries with invalid path
pbs_config::acl::check_acl_path(&path)?;
}

View File

@ -1,9 +1,9 @@
//! List Authentication domains/realms
use anyhow::{Error};
use anyhow::Error;
use serde_json::{json, Value};
use proxmox_router::{Router, RpcEnvironment, Permission};
use proxmox_router::{Permission, Router, RpcEnvironment};
use proxmox_schema::api;
use pbs_api_types::BasicRealmInfo;
@ -50,5 +50,4 @@ fn list_domains(mut rpcenv: &mut dyn RpcEnvironment) -> Result<Vec<BasicRealmInf
Ok(list)
}
pub const ROUTER: Router = Router::new()
.get(&API_METHOD_LIST_DOMAINS);
pub const ROUTER: Router = Router::new().get(&API_METHOD_LIST_DOMAINS);

View File

@ -6,19 +6,19 @@ use serde_json::{json, Value};
use std::collections::HashMap;
use std::collections::HashSet;
use proxmox_sys::sortable;
use proxmox_router::{
http_err, list_subdirs_api_method, Router, RpcEnvironment, SubdirMap, Permission,
http_err, list_subdirs_api_method, Permission, Router, RpcEnvironment, SubdirMap,
};
use proxmox_schema::api;
use proxmox_sys::sortable;
use pbs_api_types::{
Userid, Authid, PASSWORD_SCHEMA, ACL_PATH_SCHEMA,
PRIVILEGES, PRIV_PERMISSIONS_MODIFY, PRIV_SYS_AUDIT,
Authid, Userid, ACL_PATH_SCHEMA, PASSWORD_SCHEMA, PRIVILEGES, PRIV_PERMISSIONS_MODIFY,
PRIV_SYS_AUDIT,
};
use pbs_tools::ticket::{self, Empty, Ticket};
use pbs_config::acl::AclTreeNode;
use pbs_config::CachedUserInfo;
use pbs_tools::ticket::{self, Empty, Ticket};
use crate::auth_helpers::*;
use crate::config::tfa::TfaChallenge;
@ -193,10 +193,11 @@ pub fn create_ticket(
tfa_challenge: Option<String>,
rpcenv: &mut dyn RpcEnvironment,
) -> Result<Value, Error> {
use proxmox_rest_server::RestEnvironment;
let env: &RestEnvironment = rpcenv.as_any().downcast_ref::<RestEnvironment>()
let env: &RestEnvironment = rpcenv
.as_any()
.downcast_ref::<RestEnvironment>()
.ok_or_else(|| format_err!("detected worng RpcEnvironment type"))?;
match authenticate_user(&username, &password, path, privs, port, tfa_challenge) {
@ -340,7 +341,7 @@ pub fn list_permissions(
} else {
bail!("not allowed to list permissions of {}", auth_id);
}
},
}
None => current_auth_id,
};

View File

@ -4,31 +4,35 @@ use std::convert::TryFrom;
use anyhow::{bail, format_err, Error};
use serde_json::{json, Value};
use proxmox_sys::sortable;
use proxmox_router::{
http_err, list_subdirs_api_method, Router, RpcEnvironment, SubdirMap, Permission,
http_err, list_subdirs_api_method, Permission, Router, RpcEnvironment, SubdirMap,
};
use proxmox_schema::api;
use proxmox_sys::sortable;
use proxmox_openid::{OpenIdAuthenticator, OpenIdConfig};
use pbs_api_types::{
OpenIdRealmConfig, User, Userid,
EMAIL_SCHEMA, FIRST_NAME_SCHEMA, LAST_NAME_SCHEMA, OPENID_DEFAILT_SCOPE_LIST,
REALM_ID_SCHEMA,
OpenIdRealmConfig, User, Userid, EMAIL_SCHEMA, FIRST_NAME_SCHEMA, LAST_NAME_SCHEMA,
OPENID_DEFAILT_SCOPE_LIST, REALM_ID_SCHEMA,
};
use pbs_buildcfg::PROXMOX_BACKUP_RUN_DIR_M;
use pbs_tools::ticket::Ticket;
use pbs_config::CachedUserInfo;
use pbs_config::open_backup_lockfile;
use pbs_config::CachedUserInfo;
use crate::auth_helpers::*;
use crate::server::ticket::ApiTicket;
fn openid_authenticator(realm_config: &OpenIdRealmConfig, redirect_url: &str) -> Result<OpenIdAuthenticator, Error> {
let scopes: Vec<String> = realm_config.scopes.as_deref().unwrap_or(OPENID_DEFAILT_SCOPE_LIST)
fn openid_authenticator(
realm_config: &OpenIdRealmConfig,
redirect_url: &str,
) -> Result<OpenIdAuthenticator, Error> {
let scopes: Vec<String> = realm_config
.scopes
.as_deref()
.unwrap_or(OPENID_DEFAILT_SCOPE_LIST)
.split(|c: char| c == ',' || c == ';' || char::is_ascii_whitespace(&c))
.filter(|s| !s.is_empty())
.map(String::from)
@ -37,11 +41,10 @@ fn openid_authenticator(realm_config: &OpenIdRealmConfig, redirect_url: &str) ->
let mut acr_values = None;
if let Some(ref list) = realm_config.acr_values {
acr_values = Some(
list
.split(|c: char| c == ',' || c == ';' || char::is_ascii_whitespace(&c))
list.split(|c: char| c == ',' || c == ';' || char::is_ascii_whitespace(&c))
.filter(|s| !s.is_empty())
.map(String::from)
.collect()
.collect(),
);
}
@ -105,7 +108,9 @@ pub fn openid_login(
) -> Result<Value, Error> {
use proxmox_rest_server::RestEnvironment;
let env: &RestEnvironment = rpcenv.as_any().downcast_ref::<RestEnvironment>()
let env: &RestEnvironment = rpcenv
.as_any()
.downcast_ref::<RestEnvironment>()
.ok_or_else(|| format_err!("detected worng RpcEnvironment type"))?;
let user_info = CachedUserInfo::new()?;
@ -113,7 +118,6 @@ pub fn openid_login(
let mut tested_username = None;
let result = proxmox_lang::try_block!({
let (realm, private_auth_state) =
OpenIdAuthenticator::verify_public_auth_state(PROXMOX_BACKUP_RUN_DIR_M!(), &state)?;
@ -157,13 +161,19 @@ pub fn openid_login(
use pbs_config::user;
let _lock = open_backup_lockfile(user::USER_CFG_LOCKFILE, None, true)?;
let firstname = info["given_name"].as_str().map(|n| n.to_string())
let firstname = info["given_name"]
.as_str()
.map(|n| n.to_string())
.filter(|n| FIRST_NAME_SCHEMA.parse_simple_value(n).is_ok());
let lastname = info["family_name"].as_str().map(|n| n.to_string())
let lastname = info["family_name"]
.as_str()
.map(|n| n.to_string())
.filter(|n| LAST_NAME_SCHEMA.parse_simple_value(n).is_ok());
let email = info["email"].as_str().map(|n| n.to_string())
let email = info["email"]
.as_str()
.map(|n| n.to_string())
.filter(|n| EMAIL_SCHEMA.parse_simple_value(n).is_ok());
let user = User {
@ -206,7 +216,7 @@ pub fn openid_login(
if let Err(ref err) = result {
let msg = err.to_string();
env.log_failed_auth(tested_username, &msg);
return Err(http_err!(UNAUTHORIZED, "{}", msg))
return Err(http_err!(UNAUTHORIZED, "{}", msg));
}
result
@ -240,7 +250,6 @@ fn openid_auth_url(
redirect_url: String,
_rpcenv: &mut dyn RpcEnvironment,
) -> Result<String, Error> {
let (domains, _digest) = pbs_config::domains::config()?;
let config: OpenIdRealmConfig = domains.lookup("openid", &realm)?;

View File

@ -7,7 +7,7 @@ use serde_json::{json, Value};
use proxmox_router::{Permission, Router};
use proxmox_schema::api;
use pbs_api_types::{Role, SINGLE_LINE_COMMENT_SCHEMA, PRIVILEGES};
use pbs_api_types::{Role, PRIVILEGES, SINGLE_LINE_COMMENT_SCHEMA};
use pbs_config::acl::ROLE_NAMES;
#[api(
@ -56,5 +56,4 @@ fn list_roles() -> Result<Value, Error> {
Ok(list.into())
}
pub const ROUTER: Router = Router::new()
.get(&API_METHOD_LIST_ROLES);
pub const ROUTER: Router = Router::new().get(&API_METHOD_LIST_ROLES);

View File

@ -1,19 +1,18 @@
//! User Management
use anyhow::{bail, format_err, Error};
use serde::{Serialize, Deserialize};
use hex::FromHex;
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};
use std::collections::HashMap;
use hex::FromHex;
use proxmox_router::{ApiMethod, Router, RpcEnvironment, SubdirMap, Permission};
use proxmox_router::{ApiMethod, Permission, Router, RpcEnvironment, SubdirMap};
use proxmox_schema::api;
use pbs_api_types::{
PROXMOX_CONFIG_DIGEST_SCHEMA, SINGLE_LINE_COMMENT_SCHEMA, Authid,
Tokenname, UserWithTokens, Userid, User, UserUpdater, ApiToken,
ENABLE_USER_SCHEMA, EXPIRE_USER_SCHEMA, PBS_PASSWORD_SCHEMA,
PRIV_SYS_AUDIT, PRIV_PERMISSIONS_MODIFY,
ApiToken, Authid, Tokenname, User, UserUpdater, UserWithTokens, Userid, ENABLE_USER_SCHEMA,
EXPIRE_USER_SCHEMA, PBS_PASSWORD_SCHEMA, PRIV_PERMISSIONS_MODIFY, PRIV_SYS_AUDIT,
PROXMOX_CONFIG_DIGEST_SCHEMA, SINGLE_LINE_COMMENT_SCHEMA,
};
use pbs_config::token_shadow;
@ -59,7 +58,6 @@ pub fn list_users(
_info: &ApiMethod,
mut rpcenv: &mut dyn RpcEnvironment,
) -> Result<Vec<UserWithTokens>, Error> {
let (config, digest) = pbs_config::user::config()?;
let auth_id: Authid = rpcenv
@ -74,41 +72,34 @@ pub fn list_users(
let top_level_privs = user_info.lookup_privs(&auth_id, &["access", "users"]);
let top_level_allowed = (top_level_privs & PRIV_SYS_AUDIT) != 0;
let filter_by_privs = |user: &User| {
top_level_allowed || user.userid == *userid
};
let filter_by_privs = |user: &User| top_level_allowed || user.userid == *userid;
let list:Vec<User> = config.convert_to_typed_array("user")?;
let list: Vec<User> = config.convert_to_typed_array("user")?;
rpcenv["digest"] = hex::encode(&digest).into();
let iter = list.into_iter().filter(filter_by_privs);
let list = if include_tokens {
let tokens: Vec<ApiToken> = config.convert_to_typed_array("token")?;
let mut user_to_tokens = tokens
.into_iter()
.fold(
HashMap::new(),
|mut map: HashMap<Userid, Vec<ApiToken>>, token: ApiToken| {
let mut user_to_tokens = tokens.into_iter().fold(
HashMap::new(),
|mut map: HashMap<Userid, Vec<ApiToken>>, token: ApiToken| {
if token.tokenid.is_token() {
map
.entry(token.tokenid.user().clone())
map.entry(token.tokenid.user().clone())
.or_default()
.push(token);
}
map
});
iter
.map(|user: User| {
let mut user = new_user_with_tokens(user);
user.tokens = user_to_tokens.remove(&user.userid).unwrap_or_default();
user
})
.collect()
},
);
iter.map(|user: User| {
let mut user = new_user_with_tokens(user);
user.tokens = user_to_tokens.remove(&user.userid).unwrap_or_default();
user
})
.collect()
} else {
iter.map(new_user_with_tokens)
.collect()
iter.map(new_user_with_tokens).collect()
};
Ok(list)
@ -136,14 +127,17 @@ pub fn list_users(
pub fn create_user(
password: Option<String>,
config: User,
rpcenv: &mut dyn RpcEnvironment
rpcenv: &mut dyn RpcEnvironment,
) -> Result<(), Error> {
let _lock = pbs_config::user::lock_config()?;
let (mut section_config, _digest) = pbs_config::user::config()?;
if section_config.sections.get(config.userid.as_str()).is_some() {
if section_config
.sections
.get(config.userid.as_str())
.is_some()
{
bail!("user '{}' already exists.", config.userid);
}
@ -194,7 +188,7 @@ pub fn read_user(userid: Userid, mut rpcenv: &mut dyn RpcEnvironment) -> Result<
#[api()]
#[derive(Serialize, Deserialize)]
#[serde(rename_all="kebab-case")]
#[serde(rename_all = "kebab-case")]
#[allow(non_camel_case_types)]
pub enum DeletableProperty {
/// Delete the comment property.
@ -253,7 +247,6 @@ pub fn update_user(
digest: Option<String>,
rpcenv: &mut dyn RpcEnvironment,
) -> Result<(), Error> {
let _lock = pbs_config::user::lock_config()?;
let (mut config, expected_digest) = pbs_config::user::config()?;
@ -306,11 +299,19 @@ pub fn update_user(
}
if let Some(firstname) = update.firstname {
data.firstname = if firstname.is_empty() { None } else { Some(firstname) };
data.firstname = if firstname.is_empty() {
None
} else {
Some(firstname)
};
}
if let Some(lastname) = update.lastname {
data.lastname = if lastname.is_empty() { None } else { Some(lastname) };
data.lastname = if lastname.is_empty() {
None
} else {
Some(lastname)
};
}
if let Some(email) = update.email {
data.email = if email.is_empty() { None } else { Some(email) };
@ -345,10 +346,9 @@ pub fn update_user(
)]
/// Remove a user from the configuration file.
pub fn delete_user(userid: Userid, digest: Option<String>) -> Result<(), Error> {
let _lock = pbs_config::user::lock_config()?;
let _tfa_lock = crate::config::tfa::write_lock()?;
let (mut config, expected_digest) = pbs_config::user::config()?;
if let Some(ref digest) = digest {
@ -357,7 +357,9 @@ pub fn delete_user(userid: Userid, digest: Option<String>) -> Result<(), Error>
}
match config.sections.get(userid.as_str()) {
Some(_) => { config.sections.remove(userid.as_str()); },
Some(_) => {
config.sections.remove(userid.as_str());
}
None => bail!("user '{}' does not exist.", userid),
}
@ -365,7 +367,7 @@ pub fn delete_user(userid: Userid, digest: Option<String>) -> Result<(), Error>
let authenticator = crate::auth::lookup_authenticator(userid.realm())?;
match authenticator.remove_password(userid.name()) {
Ok(()) => {},
Ok(()) => {}
Err(err) => {
eprintln!(
"error removing password after deleting user {:?}: {}",
@ -417,7 +419,6 @@ pub fn read_token(
_info: &ApiMethod,
mut rpcenv: &mut dyn RpcEnvironment,
) -> Result<ApiToken, Error> {
let (config, digest) = pbs_config::user::config()?;
let tokenid = Authid::from((userid, Some(token_name)));
@ -483,7 +484,6 @@ pub fn generate_token(
expire: Option<i64>,
digest: Option<String>,
) -> Result<Value, Error> {
let _lock = pbs_config::user::lock_config()?;
let (mut config, expected_digest) = pbs_config::user::config()?;
@ -497,7 +497,11 @@ pub fn generate_token(
let tokenid_string = tokenid.to_string();
if config.sections.get(&tokenid_string).is_some() {
bail!("token '{}' for user '{}' already exists.", token_name.as_str(), userid);
bail!(
"token '{}' for user '{}' already exists.",
token_name.as_str(),
userid
);
}
let secret = format!("{:x}", proxmox_uuid::Uuid::generate());
@ -564,7 +568,6 @@ pub fn update_token(
expire: Option<i64>,
digest: Option<String>,
) -> Result<(), Error> {
let _lock = pbs_config::user::lock_config()?;
let (mut config, expected_digest) = pbs_config::user::config()?;
@ -632,7 +635,6 @@ pub fn delete_token(
token_name: Tokenname,
digest: Option<String>,
) -> Result<(), Error> {
let _lock = pbs_config::user::lock_config()?;
let (mut config, expected_digest) = pbs_config::user::config()?;
@ -646,8 +648,14 @@ pub fn delete_token(
let tokenid_string = tokenid.to_string();
match config.sections.get(&tokenid_string) {
Some(_) => { config.sections.remove(&tokenid_string); },
None => bail!("token '{}' of user '{}' does not exist.", token_name.as_str(), userid),
Some(_) => {
config.sections.remove(&tokenid_string);
}
None => bail!(
"token '{}' of user '{}' does not exist.",
token_name.as_str(),
userid
),
}
token_shadow::delete_secret(&tokenid)?;
@ -664,7 +672,7 @@ pub fn delete_token(
}
)]
#[derive(Serialize, Deserialize)]
#[serde(rename_all="kebab-case")]
#[serde(rename_all = "kebab-case")]
/// A Token Entry that contains the token-name
pub struct TokenApiEntry {
/// The Token name
@ -699,20 +707,16 @@ pub fn list_tokens(
_info: &ApiMethod,
mut rpcenv: &mut dyn RpcEnvironment,
) -> Result<Vec<TokenApiEntry>, Error> {
let (config, digest) = pbs_config::user::config()?;
let list:Vec<ApiToken> = config.convert_to_typed_array("token")?;
let list: Vec<ApiToken> = config.convert_to_typed_array("token")?;
rpcenv["digest"] = hex::encode(&digest).into();
let filter_by_owner = |token: ApiToken| {
if token.tokenid.is_token() && token.tokenid.user() == &userid {
let token_name = token.tokenid.tokenname().unwrap().to_owned();
Some(TokenApiEntry {
token_name,
token,
})
Some(TokenApiEntry { token_name, token })
} else {
None
}
@ -733,9 +737,7 @@ const TOKEN_ROUTER: Router = Router::new()
.get(&API_METHOD_LIST_TOKENS)
.match_all("token-name", &TOKEN_ITEM_ROUTER);
const USER_SUBDIRS: SubdirMap = &[
("token", &TOKEN_ROUTER),
];
const USER_SUBDIRS: SubdirMap = &[("token", &TOKEN_ROUTER)];
const USER_ROUTER: Router = Router::new()
.get(&API_METHOD_READ_USER)