update proxmox-tfa to 2.0

and fix still-very-bad updater usage in config api call...

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2021-11-29 11:19:49 +01:00
parent 0fee4ff2a4
commit e6e2927e72
4 changed files with 58 additions and 17 deletions

View File

@ -100,7 +100,7 @@ proxmox-lang = "1"
proxmox-router = { version = "1.1", features = [ "cli" ] }
proxmox-schema = { version = "1", features = [ "api-macro" ] }
proxmox-section-config = "1"
proxmox-tfa = { version = "1.3", features = [ "api", "api-types" ] }
proxmox-tfa = { version = "2", features = [ "api", "api-types" ] }
proxmox-time = "1"
proxmox-uuid = "1"
proxmox-serde = "0.1"

View File

@ -228,6 +228,7 @@ fn add_tfa_entry(
value,
challenge,
r#type,
None,
)?;
crate::config::tfa::write(&data)?;
Ok(out)

View File

@ -1,12 +1,13 @@
//! For now this only has the TFA subdir, which is in this file.
//! If we add more, it should be moved into a sub module.
use anyhow::Error;
use anyhow::{format_err, Error};
use hex::FromHex;
use serde::{Deserialize, Serialize};
use proxmox_router::{Router, RpcEnvironment, Permission, SubdirMap};
use proxmox_schema::api;
use proxmox_router::list_subdirs_api_method;
use proxmox_router::{Permission, Router, RpcEnvironment, SubdirMap};
use proxmox_schema::api;
use pbs_api_types::PROXMOX_CONFIG_DIGEST_SCHEMA;
@ -47,6 +48,15 @@ pub fn get_webauthn_config(
Ok(Some(config))
}
#[api()]
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
/// Deletable property name
pub enum DeletableProperty {
/// Delete the origin property.
Origin,
}
#[api(
protected: true,
input: {
@ -55,6 +65,14 @@ pub fn get_webauthn_config(
flatten: true,
type: WebauthnConfigUpdater,
},
delete: {
description: "List of properties to delete.",
type: Array,
optional: true,
items: {
type: DeletableProperty,
}
},
digest: {
optional: true,
schema: PROXMOX_CONFIG_DIGEST_SCHEMA,
@ -65,6 +83,7 @@ pub fn get_webauthn_config(
/// Update the TFA configuration.
pub fn update_webauthn_config(
webauthn: WebauthnConfigUpdater,
delete: Option<Vec<DeletableProperty>>,
digest: Option<String>,
) -> Result<(), Error> {
let _lock = tfa::write_lock();
@ -79,13 +98,34 @@ pub fn update_webauthn_config(
&crate::config::tfa::webauthn_config_digest(&wa)?,
)?;
}
if let Some(ref rp) = webauthn.rp { wa.rp = rp.clone(); }
if let Some(ref origin) = webauthn.origin { wa.origin = origin.clone(); }
if let Some(ref id) = webauthn.id { wa.id = id.clone(); }
if let Some(delete) = delete {
for delete in delete {
match delete {
DeletableProperty::Origin => {
wa.origin = None;
}
}
}
}
if let Some(rp) = webauthn.rp {
wa.rp = rp;
}
if webauthn.origin.is_some() {
wa.origin = webauthn.origin;
}
if let Some(id) = webauthn.id {
wa.id = id;
}
} else {
let rp = webauthn.rp.unwrap();
let origin = webauthn.origin.unwrap();
let id = webauthn.id.unwrap();
let rp = webauthn
.rp
.ok_or_else(|| format_err!("missing proeprty: 'rp'"))?;
let origin = webauthn.origin;
let id = webauthn
.id
.ok_or_else(|| format_err!("missing property: 'id'"))?;
tfa.webauthn = Some(WebauthnConfig { rp, origin, id });
}

View File

@ -127,7 +127,7 @@ impl TfaUserChallengeData {
/// Get an optional TFA challenge for a user.
pub fn login_challenge(userid: &Userid) -> Result<Option<TfaChallenge>, Error> {
let _lock = write_lock()?;
read()?.authentication_challenge(UserAccess, userid.as_str())
read()?.authentication_challenge(UserAccess, userid.as_str(), None)
}
/// Add a TOTP entry for a user. Returns the ID.
@ -176,7 +176,7 @@ pub fn add_webauthn_registration(userid: &Userid, description: String) -> Result
let _lock = crate::config::tfa::write_lock();
let mut data = read()?;
let challenge =
data.webauthn_registration_challenge(UserAccess, userid.as_str(), description)?;
data.webauthn_registration_challenge(UserAccess, userid.as_str(), description, None)?;
write(&data)?;
Ok(challenge)
}
@ -189,7 +189,8 @@ pub fn finish_webauthn_registration(
) -> Result<String, Error> {
let _lock = crate::config::tfa::write_lock();
let mut data = read()?;
let id = data.webauthn_registration_finish(UserAccess, userid.as_str(), challenge, response)?;
let id =
data.webauthn_registration_finish(UserAccess, userid.as_str(), challenge, response, None)?;
write(&data)?;
Ok(id)
}
@ -203,7 +204,7 @@ pub fn verify_challenge(
let _lock = crate::config::tfa::write_lock();
let mut data = read()?;
if data
.verify(UserAccess, userid.as_str(), challenge, response)?
.verify(UserAccess, userid.as_str(), challenge, response, None)?
.needs_saving()
{
write(&data)?;
@ -261,11 +262,10 @@ impl proxmox_tfa::api::OpenUserChallengeData for UserAccess {
Err(err) => {
eprintln!(
"failed to parse challenge data for user {}: {}",
userid,
err
userid, err
);
Default::default()
},
}
}
};