key: add show-master-pubkey command
and print public key when generating/importing.. Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
This commit is contained in:
parent
05f17d1ec4
commit
42c0f784e2
|
@ -1360,3 +1360,35 @@ pub struct KeyInfo {
|
||||||
#[serde(skip_serializing_if="Option::is_none")]
|
#[serde(skip_serializing_if="Option::is_none")]
|
||||||
pub hint: Option<String>,
|
pub hint: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[api]
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
/// RSA public key information
|
||||||
|
pub struct RsaPubKeyInfo {
|
||||||
|
/// Path to key (if stored in a file)
|
||||||
|
#[serde(skip_serializing_if="Option::is_none")]
|
||||||
|
pub path: Option<String>,
|
||||||
|
/// RSA exponent
|
||||||
|
pub exponent: String,
|
||||||
|
/// Hex-encoded RSA modulus
|
||||||
|
pub modulus: String,
|
||||||
|
/// Key (modulus) length in bits
|
||||||
|
pub length: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::convert::TryFrom<openssl::rsa::Rsa<openssl::pkey::Public>> for RsaPubKeyInfo {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
fn try_from(value: openssl::rsa::Rsa<openssl::pkey::Public>) -> Result<Self, Self::Error> {
|
||||||
|
let modulus = value.n().to_hex_str()?.to_string();
|
||||||
|
let exponent = value.e().to_dec_str()?.to_string();
|
||||||
|
let length = value.size() as usize * 8;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
path: None,
|
||||||
|
exponent,
|
||||||
|
modulus,
|
||||||
|
length,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
use anyhow::{bail, format_err, Error};
|
use anyhow::{bail, format_err, Error};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
@ -25,6 +26,7 @@ use proxmox_backup::{
|
||||||
PASSWORD_HINT_SCHEMA,
|
PASSWORD_HINT_SCHEMA,
|
||||||
KeyInfo,
|
KeyInfo,
|
||||||
Kdf,
|
Kdf,
|
||||||
|
RsaPubKeyInfo,
|
||||||
},
|
},
|
||||||
backup::{
|
backup::{
|
||||||
rsa_decrypt_key_config,
|
rsa_decrypt_key_config,
|
||||||
|
@ -366,9 +368,16 @@ fn show_key(path: Option<String>, param: Value) -> Result<(), Error> {
|
||||||
fn import_master_pubkey(path: String) -> Result<(), Error> {
|
fn import_master_pubkey(path: String) -> Result<(), Error> {
|
||||||
let pem_data = file_get_contents(&path)?;
|
let pem_data = file_get_contents(&path)?;
|
||||||
|
|
||||||
if let Err(err) = openssl::pkey::PKey::public_key_from_pem(&pem_data) {
|
match openssl::pkey::PKey::public_key_from_pem(&pem_data) {
|
||||||
bail!("Unable to decode PEM data - {}", err);
|
Ok(key) => {
|
||||||
}
|
let info = RsaPubKeyInfo::try_from(key.rsa()?)?;
|
||||||
|
println!("Found following key at {:?}", path);
|
||||||
|
println!("Modulus: {}", info.modulus);
|
||||||
|
println!("Exponent: {}", info.exponent);
|
||||||
|
println!("Length: {}", info.length);
|
||||||
|
},
|
||||||
|
Err(err) => bail!("Unable to decode PEM data - {}", err),
|
||||||
|
};
|
||||||
|
|
||||||
let target_path = place_default_master_pubkey()?;
|
let target_path = place_default_master_pubkey()?;
|
||||||
|
|
||||||
|
@ -388,7 +397,18 @@ fn create_master_key() -> Result<(), Error> {
|
||||||
bail!("unable to create master key - no tty");
|
bail!("unable to create master key - no tty");
|
||||||
}
|
}
|
||||||
|
|
||||||
let rsa = openssl::rsa::Rsa::generate(4096)?;
|
let bits = 4096;
|
||||||
|
println!("Generating {}-bit RSA key..", bits);
|
||||||
|
let rsa = openssl::rsa::Rsa::generate(bits)?;
|
||||||
|
let public = openssl::rsa::Rsa::from_public_components(
|
||||||
|
rsa.n().to_owned()?,
|
||||||
|
rsa.e().to_owned()?,
|
||||||
|
)?;
|
||||||
|
let info = RsaPubKeyInfo::try_from(public)?;
|
||||||
|
println!("Modulus: {}", info.modulus);
|
||||||
|
println!("Exponent: {}", info.exponent);
|
||||||
|
println!();
|
||||||
|
|
||||||
let pkey = openssl::pkey::PKey::from_rsa(rsa)?;
|
let pkey = openssl::pkey::PKey::from_rsa(rsa)?;
|
||||||
|
|
||||||
let password = String::from_utf8(tty::read_and_verify_password("Master Key Password: ")?)?;
|
let password = String::from_utf8(tty::read_and_verify_password("Master Key Password: ")?)?;
|
||||||
|
@ -408,6 +428,56 @@ fn create_master_key() -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[api(
|
||||||
|
input: {
|
||||||
|
properties: {
|
||||||
|
path: {
|
||||||
|
description: "Path to the PEM formatted RSA public key. Default location will be used if not specified.",
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
"output-format": {
|
||||||
|
schema: OUTPUT_FORMAT,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)]
|
||||||
|
/// List information about master key
|
||||||
|
fn show_master_pubkey(path: Option<String>, param: Value) -> Result<(), Error> {
|
||||||
|
let path = match path {
|
||||||
|
Some(path) => PathBuf::from(path),
|
||||||
|
None => find_default_master_pubkey()?
|
||||||
|
.ok_or_else(|| format_err!("No path specified and no default master key available."))?,
|
||||||
|
};
|
||||||
|
|
||||||
|
let path = path.canonicalize()?;
|
||||||
|
|
||||||
|
let output_format = get_output_format(¶m);
|
||||||
|
|
||||||
|
let pem_data = file_get_contents(path.clone())?;
|
||||||
|
let rsa = openssl::rsa::Rsa::public_key_from_pem(&pem_data)?;
|
||||||
|
|
||||||
|
let mut info = RsaPubKeyInfo::try_from(rsa)?;
|
||||||
|
info.path = Some(path.display().to_string());
|
||||||
|
|
||||||
|
let options = proxmox::api::cli::default_table_format_options()
|
||||||
|
.column(ColumnConfig::new("path"))
|
||||||
|
.column(ColumnConfig::new("modulus"))
|
||||||
|
.column(ColumnConfig::new("exponent"))
|
||||||
|
.column(ColumnConfig::new("length"));
|
||||||
|
|
||||||
|
let return_type = ReturnType::new(false, &RsaPubKeyInfo::API_SCHEMA);
|
||||||
|
|
||||||
|
format_and_print_result_full(
|
||||||
|
&mut serde_json::to_value(info)?,
|
||||||
|
&return_type,
|
||||||
|
&output_format,
|
||||||
|
&options,
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[api(
|
#[api(
|
||||||
input: {
|
input: {
|
||||||
properties: {
|
properties: {
|
||||||
|
@ -467,6 +537,9 @@ pub fn cli() -> CliCommandMap {
|
||||||
let key_import_master_pubkey_cmd_def = CliCommand::new(&API_METHOD_IMPORT_MASTER_PUBKEY)
|
let key_import_master_pubkey_cmd_def = CliCommand::new(&API_METHOD_IMPORT_MASTER_PUBKEY)
|
||||||
.arg_param(&["path"])
|
.arg_param(&["path"])
|
||||||
.completion_cb("path", tools::complete_file_name);
|
.completion_cb("path", tools::complete_file_name);
|
||||||
|
let key_show_master_pubkey_cmd_def = CliCommand::new(&API_METHOD_SHOW_MASTER_PUBKEY)
|
||||||
|
.arg_param(&["path"])
|
||||||
|
.completion_cb("path", tools::complete_file_name);
|
||||||
|
|
||||||
let key_show_cmd_def = CliCommand::new(&API_METHOD_SHOW_KEY)
|
let key_show_cmd_def = CliCommand::new(&API_METHOD_SHOW_KEY)
|
||||||
.arg_param(&["path"])
|
.arg_param(&["path"])
|
||||||
|
@ -483,5 +556,6 @@ pub fn cli() -> CliCommandMap {
|
||||||
.insert("import-master-pubkey", key_import_master_pubkey_cmd_def)
|
.insert("import-master-pubkey", key_import_master_pubkey_cmd_def)
|
||||||
.insert("change-passphrase", key_change_passphrase_cmd_def)
|
.insert("change-passphrase", key_change_passphrase_cmd_def)
|
||||||
.insert("show", key_show_cmd_def)
|
.insert("show", key_show_cmd_def)
|
||||||
|
.insert("show-master-pubkey", key_show_master_pubkey_cmd_def)
|
||||||
.insert("paperkey", paper_key_cmd_def)
|
.insert("paperkey", paper_key_cmd_def)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue