From e240d8be0b744c2304826ee834e13b016638d79e Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Sat, 10 Aug 2019 09:12:17 +0200 Subject: [PATCH] src/bin/proxmox-backup-client.rs: implement login/logout --- src/bin/proxmox-backup-client.rs | 47 ++++++++++++++++++++++++++++++++ src/client/http_client.rs | 31 ++++++++++++++++++++- 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/src/bin/proxmox-backup-client.rs b/src/bin/proxmox-backup-client.rs index f602199b..5193f733 100644 --- a/src/bin/proxmox-backup-client.rs +++ b/src/bin/proxmox-backup-client.rs @@ -389,6 +389,35 @@ fn forget_snapshots( Ok(result) } +fn api_login( + param: Value, + _info: &ApiMethod, + _rpcenv: &mut dyn RpcEnvironment, +) -> Result { + + let repo = extract_repository_from_value(¶m)?; + + let client = HttpClient::new(repo.host(), repo.user())?; + client.login().wait()?; + + record_repository(&repo); + + Ok(Value::Null) +} + +fn api_logout( + param: Value, + _info: &ApiMethod, + _rpcenv: &mut dyn RpcEnvironment, +) -> Result { + + let repo = extract_repository_from_value(¶m)?; + + delete_ticket_info(repo.host(), repo.user())?; + + Ok(Value::Null) +} + fn dump_catalog( param: Value, _info: &ApiMethod, @@ -1640,6 +1669,22 @@ We do not extraxt '.pxar' archives when writing to stdandard output. )) .completion_cb("repository", complete_repository); + let login_cmd_def = CliCommand::new( + ApiMethod::new( + api_login, + ObjectSchema::new("Try to login. If successful, store ticket.") + .optional("repository", REPO_URL_SCHEMA.clone()) + )) + .completion_cb("repository", complete_repository); + + let logout_cmd_def = CliCommand::new( + ApiMethod::new( + api_logout, + ObjectSchema::new("Logout (delete stored ticket).") + .optional("repository", REPO_URL_SCHEMA.clone()) + )) + .completion_cb("repository", complete_repository); + let cmd_def = CliCommandMap::new() .insert("backup".to_owned(), backup_cmd_def.into()) .insert("upload-log".to_owned(), upload_log_cmd_def.into()) @@ -1647,6 +1692,8 @@ We do not extraxt '.pxar' archives when writing to stdandard output. .insert("catalog".to_owned(), catalog_cmd_def.into()) .insert("garbage-collect".to_owned(), garbage_collect_cmd_def.into()) .insert("list".to_owned(), list_cmd_def.into()) + .insert("login".to_owned(), login_cmd_def.into()) + .insert("logout".to_owned(), logout_cmd_def.into()) .insert("prune".to_owned(), prune_cmd_def.into()) .insert("restore".to_owned(), restore_cmd_def.into()) .insert("snapshots".to_owned(), snapshots_cmd_def.into()) diff --git a/src/client/http_client.rs b/src/client/http_client.rs index 281ba4ff..6e6322ff 100644 --- a/src/client/http_client.rs +++ b/src/client/http_client.rs @@ -34,7 +34,7 @@ use super::merge_known_chunks::*; use crate::backup::*; #[derive(Clone)] -struct AuthInfo { +pub struct AuthInfo { username: String, ticket: String, token: String, @@ -47,6 +47,27 @@ pub struct HttpClient { auth: BroadcastFuture, } +/// Delete stored ticket data (logout) +pub fn delete_ticket_info(server: &str, username: &str) -> Result<(), Error> { + + let base = BaseDirectories::with_prefix("proxmox-backup")?; + + // usually /run/user//... + let path = base.place_runtime_file("tickets")?; + + let mode = nix::sys::stat::Mode::from_bits_truncate(0o0600); + + let mut data = file_get_json(&path, Some(json!({})))?; + + if let Some(map) = data[server].as_object_mut() { + map.remove(username); + } + + file_set_contents(path, data.to_string().as_bytes(), Some(mode))?; + + Ok(()) +} + fn store_ticket_info(server: &str, username: &str, ticket: &str, token: &str) -> Result<(), Error> { let base = BaseDirectories::with_prefix("proxmox-backup")?; @@ -144,6 +165,14 @@ impl HttpClient { }) } + /// Login future + /// + /// Login is done on demand, so this is onyl required if you need + /// access to authentication data in 'AuthInfo'. + pub fn login(&self) -> impl Future { + self.auth.listen() + } + fn get_password(_username: &str) -> Result { use std::env::VarError::*; match std::env::var("PBS_PASSWORD") { -- 2.39.2