* [pbs-devel] [PATCH v2 manager 0/2] add user tfa {list, delete} commands
@ 2023-06-20 13:39 Maximiliano Sandoval
2023-06-20 13:39 ` [pbs-devel] [PATCH v2 manager 1/2] api: Fix schema return annotation of tfa_update_auth Maximiliano Sandoval
2023-06-20 13:39 ` [pbs-devel] [PATCH v2 manager 2/2] fix #4734: manager: add user tfa {list, delete} commands Maximiliano Sandoval
0 siblings, 2 replies; 5+ messages in thread
From: Maximiliano Sandoval @ 2023-06-20 13:39 UTC (permalink / raw)
To: pbs-devel
Changes in v2:
- Rebase on top of master
- Removed the tfa add command, I might submit it in a separate patch if there
is interest
- list commands under user instead of tfa, matching pveum
- Rename variable defined in config/tfa.rs from json to data
- Improve doc string for list_user_tfa
- Move the schema fixup into a separate commit
Maximiliano Sandoval (2):
api: Fix schema return annotation of tfa_update_auth
fix #4734: manager: add user tfa {list,delete} commands
src/api2/access/tfa.rs | 9 ++++-
src/bin/proxmox_backup_manager/user.rs | 53 ++++++++++++++++++++++++++
src/config/tfa.rs | 48 +++++++++++++++++++++++
3 files changed, 108 insertions(+), 2 deletions(-)
--
2.39.2
^ permalink raw reply [flat|nested] 5+ messages in thread
* [pbs-devel] [PATCH v2 manager 1/2] api: Fix schema return annotation of tfa_update_auth
2023-06-20 13:39 [pbs-devel] [PATCH v2 manager 0/2] add user tfa {list, delete} commands Maximiliano Sandoval
@ 2023-06-20 13:39 ` Maximiliano Sandoval
2023-06-23 6:02 ` [pbs-devel] applied: " Wolfgang Bumiller
2023-06-20 13:39 ` [pbs-devel] [PATCH v2 manager 2/2] fix #4734: manager: add user tfa {list, delete} commands Maximiliano Sandoval
1 sibling, 1 reply; 5+ messages in thread
From: Maximiliano Sandoval @ 2023-06-20 13:39 UTC (permalink / raw)
To: pbs-devel
In the next commit we expose a command to list the tfa methods of a
user. Without this annotation one would get the following error
unable to format result: got unexpected data (expected null).
when running the proposed cli command.
Signed-off-by: Maximiliano Sandoval <m.sandoval@proxmox.com>
---
src/api2/access/tfa.rs | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/api2/access/tfa.rs b/src/api2/access/tfa.rs
index 4b27c0db..89d7e353 100644
--- a/src/api2/access/tfa.rs
+++ b/src/api2/access/tfa.rs
@@ -56,6 +56,11 @@ async fn tfa_update_auth(
input: {
properties: { userid: { type: Userid } },
},
+ returns: {
+ description: "The list of TFA entries.",
+ type: Array,
+ items: { type: methods::TypedTfaInfo }
+ },
access: {
permission: &Permission::Or(&[
&Permission::Privilege(&["access", "users"], PRIV_PERMISSIONS_MODIFY, false),
--
2.39.2
^ permalink raw reply [flat|nested] 5+ messages in thread
* [pbs-devel] [PATCH v2 manager 2/2] fix #4734: manager: add user tfa {list, delete} commands
2023-06-20 13:39 [pbs-devel] [PATCH v2 manager 0/2] add user tfa {list, delete} commands Maximiliano Sandoval
2023-06-20 13:39 ` [pbs-devel] [PATCH v2 manager 1/2] api: Fix schema return annotation of tfa_update_auth Maximiliano Sandoval
@ 2023-06-20 13:39 ` Maximiliano Sandoval
2023-06-23 6:04 ` Wolfgang Bumiller
1 sibling, 1 reply; 5+ messages in thread
From: Maximiliano Sandoval @ 2023-06-20 13:39 UTC (permalink / raw)
To: pbs-devel
Adds the commands
proxmox-backup-manager user tfa list <userid>
proxmox-backup-manager user tfa delete <userid> <id>
Signed-off-by: Maximiliano Sandoval <m.sandoval@proxmox.com>
---
src/api2/access/tfa.rs | 4 +-
src/bin/proxmox_backup_manager/user.rs | 53 ++++++++++++++++++++++++++
src/config/tfa.rs | 48 +++++++++++++++++++++++
3 files changed, 103 insertions(+), 2 deletions(-)
diff --git a/src/api2/access/tfa.rs b/src/api2/access/tfa.rs
index 89d7e353..589535a6 100644
--- a/src/api2/access/tfa.rs
+++ b/src/api2/access/tfa.rs
@@ -69,7 +69,7 @@ async fn tfa_update_auth(
},
)]
/// Add a TOTP secret to the user.
-fn list_user_tfa(userid: Userid) -> Result<Vec<methods::TypedTfaInfo>, Error> {
+pub fn list_user_tfa(userid: Userid) -> Result<Vec<methods::TypedTfaInfo>, Error> {
let _lock = crate::config::tfa::read_lock()?;
methods::list_user_tfa(&crate::config::tfa::read()?, userid.as_str())
@@ -122,7 +122,7 @@ fn get_tfa_entry(userid: Userid, id: String) -> Result<methods::TypedTfaInfo, Er
},
)]
/// Delete a single TFA entry.
-async fn delete_tfa(
+pub async fn delete_tfa(
userid: Userid,
id: String,
password: Option<String>,
diff --git a/src/bin/proxmox_backup_manager/user.rs b/src/bin/proxmox_backup_manager/user.rs
index ecaaa554..1a36f393 100644
--- a/src/bin/proxmox_backup_manager/user.rs
+++ b/src/bin/proxmox_backup_manager/user.rs
@@ -157,6 +157,40 @@ fn list_permissions(param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<Val
Ok(Value::Null)
}
+#[api(
+ input: {
+ properties: {
+ "output-format": {
+ schema: OUTPUT_FORMAT,
+ optional: true,
+ },
+ userid: {
+ type: Userid,
+ }
+ },
+ }
+)]
+/// List all tfa methods for a user.
+fn list_user_tfa(param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<Value, Error> {
+ let output_format = get_output_format(¶m);
+
+ let info = &api2::access::tfa::API_METHOD_LIST_USER_TFA;
+ let mut data = match info.handler {
+ ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
+ _ => unreachable!(),
+ };
+
+ let options = default_table_format_options()
+ .column(ColumnConfig::new("id"))
+ .column(ColumnConfig::new("type"))
+ .column(ColumnConfig::new("description"))
+ .column(ColumnConfig::new("created").renderer(pbs_tools::format::render_epoch));
+
+ format_and_print_result_full(&mut data, &info.returns, &output_format, &options);
+
+ Ok(Value::Null)
+}
+
pub fn user_commands() -> CommandLineInterface {
let cmd_def = CliCommandMap::new()
.insert("list", CliCommand::new(&API_METHOD_LIST_USERS))
@@ -196,6 +230,7 @@ pub fn user_commands() -> CommandLineInterface {
.completion_cb("userid", pbs_config::user::complete_userid)
.completion_cb("token-name", pbs_config::user::complete_token_name),
)
+ .insert("tfa", tfa_commands())
.insert(
"permissions",
CliCommand::new(&API_METHOD_LIST_PERMISSIONS)
@@ -206,3 +241,21 @@ pub fn user_commands() -> CommandLineInterface {
cmd_def.into()
}
+
+fn tfa_commands() -> CommandLineInterface {
+ CliCommandMap::new()
+ .insert(
+ "list",
+ CliCommand::new(&API_METHOD_LIST_USER_TFA)
+ .arg_param(&["userid"])
+ .completion_cb("userid", pbs_config::user::complete_userid),
+ )
+ .insert(
+ "delete",
+ CliCommand::new(&api2::access::tfa::API_METHOD_DELETE_TFA)
+ .arg_param(&["userid", "id"])
+ .completion_cb("userid", pbs_config::user::complete_userid)
+ .completion_cb("id", proxmox_backup::config::tfa::complete_tfa_id),
+ )
+ .into()
+}
diff --git a/src/config/tfa.rs b/src/config/tfa.rs
index 6b1312bb..3cd7f9aa 100644
--- a/src/config/tfa.rs
+++ b/src/config/tfa.rs
@@ -1,3 +1,4 @@
+use std::collections::HashMap;
use std::fs::File;
use std::io::{self, Read, Seek, SeekFrom};
use std::os::unix::fs::OpenOptionsExt;
@@ -302,3 +303,50 @@ impl proxmox_tfa::api::UserChallengeAccess for TfaUserChallengeData {
TfaUserChallengeData::save(self)
}
}
+
+// shell completion helper
+pub fn complete_tfa_id(_arg: &str, param: &HashMap<String, String>) -> Vec<String> {
+ let mut results = Vec::new();
+
+ let data = match read() {
+ Ok(data) => data,
+ Err(_err) => return results,
+ };
+ let user = match param
+ .get("userid")
+ .and_then(|user_name| data.users.get(user_name))
+ {
+ Some(user) => user,
+ None => return results,
+ };
+
+ results.extend(
+ user.totp
+ .iter()
+ .map(|token| token.info.id.clone())
+ .collect::<Vec<_>>(),
+ );
+ results.extend(
+ user.u2f
+ .iter()
+ .map(|token| token.info.id.clone())
+ .collect::<Vec<_>>(),
+ );
+ results.extend(
+ user.webauthn
+ .iter()
+ .map(|token| token.info.id.clone())
+ .collect::<Vec<_>>(),
+ );
+ results.extend(
+ user.yubico
+ .iter()
+ .map(|token| token.info.id.clone())
+ .collect::<Vec<_>>(),
+ );
+ if user.recovery.is_some() {
+ results.push("recovery".to_string());
+ };
+
+ results
+}
--
2.39.2
^ permalink raw reply [flat|nested] 5+ messages in thread
* [pbs-devel] applied: [PATCH v2 manager 1/2] api: Fix schema return annotation of tfa_update_auth
2023-06-20 13:39 ` [pbs-devel] [PATCH v2 manager 1/2] api: Fix schema return annotation of tfa_update_auth Maximiliano Sandoval
@ 2023-06-23 6:02 ` Wolfgang Bumiller
0 siblings, 0 replies; 5+ messages in thread
From: Wolfgang Bumiller @ 2023-06-23 6:02 UTC (permalink / raw)
To: Maximiliano Sandoval; +Cc: pbs-devel
applied this one
On Tue, Jun 20, 2023 at 03:39:07PM +0200, Maximiliano Sandoval wrote:
> In the next commit we expose a command to list the tfa methods of a
> user. Without this annotation one would get the following error
>
> unable to format result: got unexpected data (expected null).
>
> when running the proposed cli command.
>
> Signed-off-by: Maximiliano Sandoval <m.sandoval@proxmox.com>
> ---
> src/api2/access/tfa.rs | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/src/api2/access/tfa.rs b/src/api2/access/tfa.rs
> index 4b27c0db..89d7e353 100644
> --- a/src/api2/access/tfa.rs
> +++ b/src/api2/access/tfa.rs
> @@ -56,6 +56,11 @@ async fn tfa_update_auth(
> input: {
> properties: { userid: { type: Userid } },
> },
> + returns: {
> + description: "The list of TFA entries.",
> + type: Array,
> + items: { type: methods::TypedTfaInfo }
> + },
> access: {
> permission: &Permission::Or(&[
> &Permission::Privilege(&["access", "users"], PRIV_PERMISSIONS_MODIFY, false),
> --
> 2.39.2
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [pbs-devel] [PATCH v2 manager 2/2] fix #4734: manager: add user tfa {list, delete} commands
2023-06-20 13:39 ` [pbs-devel] [PATCH v2 manager 2/2] fix #4734: manager: add user tfa {list, delete} commands Maximiliano Sandoval
@ 2023-06-23 6:04 ` Wolfgang Bumiller
0 siblings, 0 replies; 5+ messages in thread
From: Wolfgang Bumiller @ 2023-06-23 6:04 UTC (permalink / raw)
To: Maximiliano Sandoval; +Cc: pbs-devel
1 minor thing I missed in the 1st round
On Tue, Jun 20, 2023 at 03:39:08PM +0200, Maximiliano Sandoval wrote:
(...)
> diff --git a/src/config/tfa.rs b/src/config/tfa.rs
> index 6b1312bb..3cd7f9aa 100644
> --- a/src/config/tfa.rs
> +++ b/src/config/tfa.rs
> @@ -1,3 +1,4 @@
> +use std::collections::HashMap;
> use std::fs::File;
> use std::io::{self, Read, Seek, SeekFrom};
> use std::os::unix::fs::OpenOptionsExt;
> @@ -302,3 +303,50 @@ impl proxmox_tfa::api::UserChallengeAccess for TfaUserChallengeData {
> TfaUserChallengeData::save(self)
> }
> }
> +
> +// shell completion helper
> +pub fn complete_tfa_id(_arg: &str, param: &HashMap<String, String>) -> Vec<String> {
> + let mut results = Vec::new();
> +
> + let data = match read() {
> + Ok(data) => data,
> + Err(_err) => return results,
> + };
> + let user = match param
> + .get("userid")
> + .and_then(|user_name| data.users.get(user_name))
> + {
> + Some(user) => user,
> + None => return results,
> + };
> +
> + results.extend(
> + user.totp
> + .iter()
> + .map(|token| token.info.id.clone())
> + .collect::<Vec<_>>(),
^ .extend() takes an `IntoIterator`, you already have an iterator, you
can drop the `.collect()` call here
> + );
> + results.extend(
> + user.u2f
> + .iter()
> + .map(|token| token.info.id.clone())
> + .collect::<Vec<_>>(),
^ and here
> + );
> + results.extend(
> + user.webauthn
> + .iter()
> + .map(|token| token.info.id.clone())
> + .collect::<Vec<_>>(),
^ and here
> + );
> + results.extend(
> + user.yubico
> + .iter()
> + .map(|token| token.info.id.clone())
> + .collect::<Vec<_>>(),
^ and here
> + );
> + if user.recovery.is_some() {
> + results.push("recovery".to_string());
> + };
> +
> + results
> +}
> --
> 2.39.2
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2023-06-23 6:04 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-20 13:39 [pbs-devel] [PATCH v2 manager 0/2] add user tfa {list, delete} commands Maximiliano Sandoval
2023-06-20 13:39 ` [pbs-devel] [PATCH v2 manager 1/2] api: Fix schema return annotation of tfa_update_auth Maximiliano Sandoval
2023-06-23 6:02 ` [pbs-devel] applied: " Wolfgang Bumiller
2023-06-20 13:39 ` [pbs-devel] [PATCH v2 manager 2/2] fix #4734: manager: add user tfa {list, delete} commands Maximiliano Sandoval
2023-06-23 6:04 ` Wolfgang Bumiller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox