From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 9DB5F61E6F for ; Mon, 28 Sep 2020 18:27:47 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 932CA83AA for ; Mon, 28 Sep 2020 18:27:17 +0200 (CEST) Received: from elsa.proxmox.com (212-186-127-178.static.upcbusiness.at [212.186.127.178]) by firstgate.proxmox.com (Proxmox) with ESMTP id 3F637839E for ; Mon, 28 Sep 2020 18:27:16 +0200 (CEST) Received: by elsa.proxmox.com (Postfix, from userid 0) id 0EA4AAE4710; Mon, 28 Sep 2020 18:27:16 +0200 (CEST) From: Dietmar Maurer To: pbs-devel@lists.proxmox.com Date: Mon, 28 Sep 2020 18:27:12 +0200 Message-Id: <20200928162712.13867-1-dietmar@proxmox.com> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL -1.077 Adjusted score from AWL reputation of From: address KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: [pbs-devel] [PATCH proxmox-backup] proxmox_backup_client key: add new paper-key command X-BeenThere: pbs-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Backup Server development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 28 Sep 2020 16:27:47 -0000 --- debian/control.in | 2 +- src/bin/proxmox_backup_client/key.rs | 67 ++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/debian/control.in b/debian/control.in index 8e2312d..2e6d82f 100644 --- a/debian/control.in +++ b/debian/control.in @@ -19,7 +19,7 @@ Description: Proxmox Backup Server daemon with tools and GUI Package: proxmox-backup-client Architecture: any -Depends: ${misc:Depends}, ${shlibs:Depends} +Depends: qrencode ${misc:Depends}, ${shlibs:Depends} Description: Proxmox Backup Client tools This package contains the Proxmox Backup client, which provides a simple command line tool to create and restore backups. diff --git a/src/bin/proxmox_backup_client/key.rs b/src/bin/proxmox_backup_client/key.rs index f60687e..e87f048 100644 --- a/src/bin/proxmox_backup_client/key.rs +++ b/src/bin/proxmox_backup_client/key.rs @@ -1,4 +1,6 @@ use std::path::PathBuf; +use std::io::Write; +use std::process::{Stdio, Command}; use anyhow::{bail, format_err, Error}; use serde::{Deserialize, Serialize}; @@ -261,6 +263,66 @@ fn create_master_key() -> Result<(), Error> { Ok(()) } +#[api( + input: { + properties: { + path: { + description: "Key file. Without this the default key's will be used.", + optional: true, + }, + subject: { + description: "Include the specified subject as titel text.", + optional: true, + }, + }, + }, +)] +/// Generate a printable, human readable text file containing the encryption key. +/// +/// This also includes a scanable QR code for fast key restore. +fn paper_key(path: Option, subject: Option) -> Result<(), Error> { + let path = match path { + Some(path) => PathBuf::from(path), + None => { + let path = find_default_encryption_key()? + .ok_or_else(|| { + format_err!("no encryption file provided and no default file found") + })?; + path + } + }; + + let data = file_get_contents(&path)?; + let key_config: KeyConfig = serde_json::from_slice(&data)?; + let key_text = serde_json::to_string_pretty(&key_config)?; + + if let Some(subject) = subject { + println!("Subject: {}\n", subject); + } + + println!("-----BEGIN PROXMOX BACKUP KEY-----"); + println!("{}", key_text); + println!("-----END PROXMOX BACKUP KEY-----"); + + let mut child = Command::new("qrencode") + .args(&["-t", "utf8i", "-lm"]) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn()?; + + { + let stdin = child.stdin.as_mut().expect("Failed to open stdin"); + stdin.write_all(key_text.as_bytes()).expect("Failed to write to stdin"); + } + + let output = child.wait_with_output().expect("Failed to read stdout"); + + println!("{}", String::from_utf8_lossy(&output.stdout)); + + Ok(()) +} + + pub fn cli() -> CliCommandMap { let key_create_cmd_def = CliCommand::new(&API_METHOD_CREATE) .arg_param(&["path"]) @@ -275,9 +337,14 @@ pub fn cli() -> CliCommandMap { .arg_param(&["path"]) .completion_cb("path", tools::complete_file_name); + let paper_key_cmd_def = CliCommand::new(&API_METHOD_PAPER_KEY) + .arg_param(&["path"]) + .completion_cb("path", tools::complete_file_name); + CliCommandMap::new() .insert("create", key_create_cmd_def) .insert("create-master-key", key_create_master_key_cmd_def) .insert("import-master-pubkey", key_import_master_pubkey_cmd_def) .insert("change-passphrase", key_change_passphrase_cmd_def) + .insert("paper-key", paper_key_cmd_def) } -- 2.20.1