-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add initial parsec-tool implementation
Signed-off-by: Joe Ellis <[email protected]>
- Loading branch information
Joe Ellis
committed
Jul 28, 2020
1 parent
a3f8a55
commit d8ea69f
Showing
9 changed files
with
1,351 additions
and
1 deletion.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ | |
"ionut-arm", | ||
"justincormack", | ||
"paulhowardarm", | ||
"joechrisellis", | ||
] | ||
|
||
[people] | ||
|
@@ -43,3 +44,7 @@ | |
Email = "[email protected]" | ||
GitHub = "paulhowardarm" | ||
|
||
[people.joechrisellis] | ||
Name = "Joe Ellis" | ||
Email = "[email protected]" | ||
GitHub = "joechrisellis" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// Copyright 2020 Contributors to the Parsec project. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
//! CLI implementation. | ||
use crate::common::{PROJECT_AUTHOR, PROJECT_DESC, PROJECT_NAME, PROJECT_VERSION}; | ||
use clap::{App, AppSettings, Arg}; | ||
|
||
#[derive(Debug)] | ||
pub enum Action { | ||
ListOpcodes(String), | ||
ListProviders, | ||
Ping, | ||
} | ||
|
||
#[derive(Debug)] | ||
pub struct CommandLineContext { | ||
pub action: Action, | ||
pub app_name: Option<String>, | ||
pub verbosity: u64, | ||
} | ||
|
||
pub fn parse_cli() -> CommandLineContext { | ||
let matches = App::new(PROJECT_NAME) | ||
.about(PROJECT_DESC) | ||
.author(PROJECT_AUTHOR) | ||
.version(PROJECT_VERSION) | ||
.setting(AppSettings::SubcommandRequiredElseHelp) | ||
.arg( | ||
Arg::with_name("v") | ||
.short('v') | ||
.multiple(true) | ||
.about("Sets the level of verbosity"), | ||
) | ||
.subcommand( | ||
App::new("list_opcodes").about("List the opcodes").arg( | ||
Arg::with_name("provider") | ||
.short('p') | ||
.takes_value(true) | ||
.required(true) | ||
.possible_values(&["core", "mbedcrypto", "pkcs11", "tpm"]) | ||
.about("The provider to get the opcodes for"), | ||
), | ||
) | ||
.subcommand(App::new("list_providers").about("List the providers")) | ||
.subcommand(App::new("ping").about("Ping the client")) | ||
.get_matches(); | ||
|
||
CommandLineContext { | ||
action: if let Some(matches) = matches.subcommand_matches("list_opcodes") { | ||
Action::ListOpcodes(String::from(matches.value_of("provider").unwrap())) | ||
} else if let Some(_matches) = matches.subcommand_matches("list_providers") { | ||
Action::ListProviders | ||
} else if let Some(_matches) = matches.subcommand_matches("ping") { | ||
Action::Ping | ||
} else { | ||
unreachable!() | ||
}, | ||
app_name: match matches.value_of("appname") { | ||
Some(app_name) => Some(String::from(app_name)), | ||
_ => None, | ||
}, | ||
verbosity: matches.occurrences_of("verbosity"), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
// Copyright 2020 Contributors to the Parsec project. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
//! Command implementations. Interacts with parsec-client-rust. | ||
use crate::cli::{Action, CommandLineContext}; | ||
use crate::error::ParsecCliError; | ||
use anyhow::{Context, Result}; | ||
use parsec_client::auth::AuthenticationData; | ||
use parsec_client::core::interface::requests::ProviderID; | ||
use parsec_client::BasicClient; | ||
|
||
fn get_unauthenticated_client() -> BasicClient { | ||
BasicClient::new(AuthenticationData::None) | ||
} | ||
|
||
/// Gets the list of availble opcodes for a given provider and outputs them. | ||
fn list_opcodes( | ||
_command_line_context: &CommandLineContext, | ||
provider: &str, | ||
) -> Result<(), ParsecCliError> { | ||
let client = get_unauthenticated_client(); | ||
|
||
let desired_provider = match provider { | ||
"core" => ProviderID::Core, | ||
"mbedcrypto" => ProviderID::MbedCrypto, | ||
"pkcs11" => ProviderID::Pkcs11, | ||
"tpm" => ProviderID::Tpm, | ||
_ => unreachable!(), | ||
}; | ||
|
||
let provider_opcodes = client | ||
.list_opcodes(desired_provider) | ||
.context("Failed to list opcodes.")?; | ||
|
||
e_info!("Available opcodes for provider {:?}:", desired_provider); | ||
for provider_opcode in provider_opcodes { | ||
print_colored!(Blue, "*"); | ||
println!(" {:?}", provider_opcode); | ||
} | ||
Ok(()) | ||
} | ||
|
||
/// Gets the list of available providers and outputs them. | ||
fn list_providers(_command_line_context: &CommandLineContext) -> Result<(), ParsecCliError> { | ||
let client = get_unauthenticated_client(); | ||
let available_providers = client | ||
.list_providers() | ||
.context("Failed to list providers.")?; | ||
|
||
e_info!("Available providers:"); | ||
for provider in available_providers { | ||
print!("["); | ||
print_colored!(Cyan, "0x{:02x} ({})", provider.id as u32, provider.id); | ||
println!("]"); | ||
|
||
print_colored!(Yellow, "Description"); | ||
println!(": {}", provider.description); | ||
|
||
print_colored!(Yellow, "Version"); | ||
println!( | ||
": {}.{}.{}", | ||
provider.version_maj, provider.version_min, provider.version_rev, | ||
); | ||
|
||
print_colored!(Yellow, "Vendor"); | ||
println!( | ||
": {}", | ||
if !provider.vendor.is_empty() { | ||
provider.vendor | ||
} else { | ||
"Unspecified".to_string() | ||
}, | ||
); | ||
|
||
print_colored!(Yellow, "UUID"); | ||
println!(": {}", provider.uuid); | ||
println!(); | ||
} | ||
Ok(()) | ||
} | ||
|
||
/// Attempts to ping the Parsec service. | ||
fn ping(_command_line_context: &CommandLineContext) -> Result<(), ParsecCliError> { | ||
e_info!("Pinging Parsec service..."); | ||
|
||
let client = get_unauthenticated_client(); | ||
let (wire_prot_v_maj, wire_prot_v_min) = | ||
client.ping().context("Failed to ping Parsec service.")?; | ||
|
||
success!( | ||
"Service wire protocol version is {}.{}.", | ||
wire_prot_v_maj, | ||
wire_prot_v_min | ||
); | ||
Ok(()) | ||
} | ||
|
||
pub fn dispatch_command(command_line_context: &CommandLineContext) -> Result<(), ParsecCliError> { | ||
match &command_line_context.action { | ||
Action::ListOpcodes(provider) => list_opcodes(command_line_context, provider), | ||
Action::ListProviders => list_providers(command_line_context), | ||
Action::Ping => ping(command_line_context), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
// Copyright 2020 Contributors to the Parsec project. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
//! Common variables. | ||
pub const PROJECT_NAME: &str = env!("CARGO_PKG_NAME"); | ||
pub const PROJECT_DESC: &str = env!("CARGO_PKG_DESCRIPTION"); | ||
pub const PROJECT_AUTHOR: &str = env!("CARGO_PKG_AUTHORS"); | ||
pub const PROJECT_VERSION: &str = env!("CARGO_PKG_VERSION"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// Copyright 2020 Contributors to the Parsec project. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
//! Error definitions/handling. | ||
use thiserror::Error; | ||
|
||
#[derive(Error, Debug)] | ||
pub enum ParsecCliError { | ||
#[error(transparent)] | ||
ClientError(#[from] anyhow::Error), | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
// Copyright 2020 Contributors to the Parsec project. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
//! Output helpers. | ||
// COLORS: | ||
// The output colour of a particular object of text should convey some information about what | ||
// exactly it is. These are not hard and fast rules, but generally speaking: | ||
// - Blue for general information. | ||
// - Green for success. | ||
// - Red for errors and warnings. | ||
// - Cyan should be used for section titles. | ||
// - Yellow should represent field names -- i.e. UUIDs, versions, etc. | ||
// | ||
// By sticking to this guideline we ensure that the CLI stays consistent. | ||
|
||
/// Gets a colorized message for outputting to a particular stream. Do not use colors if the stream | ||
/// is not a tty. | ||
#[macro_export] | ||
macro_rules! colorize { | ||
($color:ident, $stream:ident, $arg:tt) => {{ | ||
let style = if atty::is(atty::Stream::$stream) { | ||
ansi_term::Color::$color.normal() | ||
} else { | ||
ansi_term::Style::default() | ||
}; | ||
style.paint($arg) | ||
}}; | ||
($color:ident, $stream:ident, $($arg:tt)*) => {{ | ||
let style = if atty::is(atty::Stream::$stream) { | ||
ansi_term::Color::$color.normal() | ||
} else { | ||
ansi_term::Style::default() | ||
}; | ||
style.paint(format!($($arg)*)) | ||
}}; | ||
} | ||
|
||
/// Wrapper around `print!` that accepts a color as its first argument. | ||
#[macro_export] | ||
macro_rules! print_colored { | ||
($color:ident, $($arg:tt)*) => { | ||
print!("{}", colorize!($color, Stdout, $($arg)*)) | ||
}; | ||
} | ||
|
||
/// Wrapper around `println!` that accepts a color as its first argument. | ||
#[macro_export] | ||
macro_rules! println_colored { | ||
($color:ident, $($arg:tt)*) => { | ||
println!("{}", colorize!($color, Stdout, $($arg)*)) | ||
}; | ||
} | ||
|
||
/// Wrapper around `eprint!` that accepts a color as its first argument. | ||
#[macro_export] | ||
macro_rules! eprint_colored { | ||
($color:ident, $($arg:tt)*) => { | ||
eprint!("{}", colorize!($color, Stderr, $($arg)*)) | ||
}; | ||
} | ||
|
||
/// Wrapper around `eprintln!` that accepts a color as its first argument. | ||
#[macro_export] | ||
macro_rules! eprintln_colored { | ||
($color:ident, $($arg:tt)*) => { | ||
eprintln!("{}", colorize!($color, Stderr, $($arg)*)) | ||
}; | ||
} | ||
|
||
/// Write an info message to stdout. | ||
#[macro_export] | ||
macro_rules! info { | ||
($($arg:tt)*) => { | ||
print!("{}", colorize!(Blue, Stdout, "[INFO] ")); | ||
println!($($arg)*); | ||
}; | ||
} | ||
|
||
/// Write an error message to stdout. | ||
#[macro_export] | ||
macro_rules! err { | ||
($($arg:tt)*) => { | ||
print!("{}", colorize!(Red, Stdout, "[ERR] ")); | ||
println!($($arg)*); | ||
}; | ||
} | ||
|
||
/// Write a success message to stdout. | ||
#[macro_export] | ||
macro_rules! success { | ||
($($arg:tt)*) => { | ||
print!("{}", colorize!(Green, Stdout, "[SUCCESS] ")); | ||
println!($($arg)*); | ||
}; | ||
} | ||
|
||
/// Write an info message to stderr. | ||
#[macro_export] | ||
macro_rules! e_info { | ||
($($arg:tt)*) => { | ||
eprint!("{}", colorize!(Blue, Stderr, "[INFO] ")); | ||
eprintln!($($arg)*); | ||
}; | ||
} | ||
|
||
/// Write an error message to stderr. | ||
#[macro_export] | ||
macro_rules! e_err { | ||
($($arg:tt)*) => { | ||
eprint!("{}", colorize!(Red, Stderr, "[ERR] ")); | ||
eprintln!($($arg)*); | ||
}; | ||
} | ||
|
||
/// Write a success message to stderr. | ||
#[macro_export] | ||
macro_rules! e_success { | ||
($($arg:tt)*) => { | ||
eprint!("{}", colorize!(Green, Stderr, "[SUCCESS] ")); | ||
eprintln!($($arg)*); | ||
}; | ||
} |