Skip to content

Commit

Permalink
jcli: allow to provide a custom TLS root certificate for REST API que…
Browse files Browse the repository at this point in the history
…ries
  • Loading branch information
eugene-babichenko committed Nov 19, 2020
1 parent 4c28778 commit b4d7c13
Show file tree
Hide file tree
Showing 22 changed files with 236 additions and 67 deletions.
9 changes: 7 additions & 2 deletions jcli/src/jcli_app/rest/v0/account/mod.rs
@@ -1,5 +1,7 @@
use crate::jcli_app::rest::Error;
use crate::jcli_app::utils::{AccountId, DebugFlag, HostAddr, OutputFormat, RestApiSender};
use crate::jcli_app::utils::{
AccountId, DebugFlag, HostAddr, OutputFormat, RestApiSender, TlsCert,
};
use structopt::StructOpt;

#[derive(StructOpt)]
Expand All @@ -16,6 +18,8 @@ pub enum Account {
/// An Account ID either in the form of an address of kind account, or an account public key
#[structopt(parse(try_from_str = AccountId::try_from_str))]
account_id: AccountId,
#[structopt(flatten)]
tls: TlsCert,
},
}

Expand All @@ -26,12 +30,13 @@ impl Account {
debug,
output_format,
account_id,
tls,
} = self;
let url = addr
.with_segments(&["v0", "account", &account_id.to_url_arg()])?
.into_url();
let builder = reqwest::blocking::Client::new().get(url);
let response = RestApiSender::new(builder, &debug).send()?;
let response = RestApiSender::new(builder, &debug, &tls).send()?;
response.ok_response()?;
let state = response.body().json_value()?;
let formatted = output_format.format_json(state)?;
Expand Down
14 changes: 11 additions & 3 deletions jcli/src/jcli_app/rest/v0/block/next_id.rs
@@ -1,5 +1,5 @@
use crate::jcli_app::rest::Error;
use crate::jcli_app::utils::{DebugFlag, HostAddr, RestApiSender};
use crate::jcli_app::utils::{DebugFlag, HostAddr, RestApiSender, TlsCert};
use chain_crypto::Blake2b256;
use structopt::StructOpt;

Expand All @@ -15,13 +15,20 @@ pub enum NextId {
/// Maximum number of IDs, must be between 1 and 100, default 1
#[structopt(short, long)]
count: Option<usize>,
#[structopt(flatten)]
tls: TlsCert,
},
}

impl NextId {
pub fn exec(self, block_id: String) -> Result<(), Error> {
match self {
NextId::Get { addr, debug, count } => exec_get(block_id, addr, debug, count),
NextId::Get {
addr,
debug,
count,
tls,
} => exec_get(block_id, addr, debug, tls, count),
}
}
}
Expand All @@ -30,6 +37,7 @@ fn exec_get(
block_id: String,
addr: HostAddr,
debug: DebugFlag,
tls: TlsCert,
count: Option<usize>,
) -> Result<(), Error> {
let url = addr
Expand All @@ -38,7 +46,7 @@ fn exec_get(
let builder = reqwest::blocking::Client::new()
.get(url)
.query(&[("count", count)]);
let response = RestApiSender::new(builder, &debug).send()?;
let response = RestApiSender::new(builder, &debug, &tls).send()?;
response.ok_response()?;
let body = response.body().binary();
for block_id in body.chunks(Blake2b256::HASH_SIZE) {
Expand Down
10 changes: 6 additions & 4 deletions jcli/src/jcli_app/rest/v0/block/subcommand.rs
@@ -1,6 +1,6 @@
use super::next_id::NextId;
use crate::jcli_app::rest::Error;
use crate::jcli_app::utils::{DebugFlag, HostAddr, RestApiSender};
use crate::jcli_app::utils::{DebugFlag, HostAddr, RestApiSender, TlsCert};
use structopt::StructOpt;

#[derive(StructOpt)]
Expand All @@ -12,6 +12,8 @@ pub enum Subcommand {
addr: HostAddr,
#[structopt(flatten)]
debug: DebugFlag,
#[structopt(flatten)]
tls: TlsCert,
},
/// Get block descendant ID
NextId(NextId),
Expand All @@ -20,16 +22,16 @@ pub enum Subcommand {
impl Subcommand {
pub fn exec(self, block_id: String) -> Result<(), Error> {
match self {
Subcommand::Get { addr, debug } => exec_get(block_id, addr, debug),
Subcommand::Get { addr, debug, tls } => exec_get(block_id, addr, debug, tls),
Subcommand::NextId(next_id) => next_id.exec(block_id),
}
}
}

fn exec_get(block_id: String, addr: HostAddr, debug: DebugFlag) -> Result<(), Error> {
fn exec_get(block_id: String, addr: HostAddr, debug: DebugFlag, tls: TlsCert) -> Result<(), Error> {
let url = addr.with_segments(&["v0", "block", &block_id])?.into_url();
let builder = reqwest::blocking::Client::new().get(url);
let response = RestApiSender::new(builder, &debug).send()?;
let response = RestApiSender::new(builder, &debug, &tls).send()?;
response.ok_response()?;
let body = response.body().binary();
println!("{}", hex::encode(&body));
Expand Down
10 changes: 6 additions & 4 deletions jcli/src/jcli_app/rest/v0/diagnostic/mod.rs
@@ -1,5 +1,5 @@
use crate::jcli_app::rest::Error;
use crate::jcli_app::utils::{DebugFlag, HostAddr, RestApiSender};
use crate::jcli_app::utils::{DebugFlag, HostAddr, RestApiSender, TlsCert};
use structopt::StructOpt;

#[derive(StructOpt)]
Expand All @@ -11,17 +11,19 @@ pub enum Diagnostic {
addr: HostAddr,
#[structopt(flatten)]
debug: DebugFlag,
#[structopt(flatten)]
tls: TlsCert,
},
}

impl Diagnostic {
pub fn exec(self) -> Result<(), Error> {
let (addr, debug) = match self {
Diagnostic::Get { addr, debug } => (addr, debug),
let (addr, debug, tls) = match self {
Diagnostic::Get { addr, debug, tls } => (addr, debug, tls),
};
let url = addr.with_segments(&["v0", "diagnostic"])?.into_url();
let builder = reqwest::blocking::Client::new().get(url);
let response = RestApiSender::new(builder, &debug).send()?;
let response = RestApiSender::new(builder, &debug, &tls).send()?;
response.ok_response()?;
let diagnostic = response.body().text();
println!("{}", diagnostic.as_ref());
Expand Down
61 changes: 48 additions & 13 deletions jcli/src/jcli_app/rest/v0/leaders/mod.rs
@@ -1,5 +1,5 @@
use crate::jcli_app::rest::Error;
use crate::jcli_app::utils::{io, DebugFlag, HostAddr, OutputFormat, RestApiSender};
use crate::jcli_app::utils::{io, DebugFlag, HostAddr, OutputFormat, RestApiSender, TlsCert};
use std::path::PathBuf;
use structopt::StructOpt;

Expand All @@ -14,6 +14,8 @@ pub enum Leaders {
debug: DebugFlag,
#[structopt(flatten)]
output_format: OutputFormat,
#[structopt(flatten)]
tls: TlsCert,
},
/// Register new leader and get its ID
Post {
Expand All @@ -26,6 +28,8 @@ pub enum Leaders {
/// If not provided, YAML will be read from stdin.
#[structopt(short, long)]
file: Option<PathBuf>,
#[structopt(flatten)]
tls: TlsCert,
},
/// Delete leader
Delete {
Expand All @@ -35,6 +39,8 @@ pub enum Leaders {
debug: DebugFlag,
/// ID of deleted leader
id: u32,
#[structopt(flatten)]
tls: TlsCert,
},

/// Leadership log operations
Expand All @@ -52,6 +58,8 @@ pub enum GetLogs {
debug: DebugFlag,
#[structopt(flatten)]
output_format: OutputFormat,
#[structopt(flatten)]
tls: TlsCert,
},
}

Expand All @@ -62,56 +70,83 @@ impl Leaders {
addr,
debug,
output_format,
} => get(addr, debug, output_format),
Leaders::Post { addr, debug, file } => post(addr, debug, file),
Leaders::Delete { id, addr, debug } => delete(addr, debug, id),
tls,
} => get(addr, debug, tls, output_format),
Leaders::Post {
addr,
debug,
tls,
file,
} => post(addr, debug, tls, file),
Leaders::Delete {
id,
addr,
debug,
tls,
} => delete(addr, debug, tls, id),
Leaders::Logs(GetLogs::Get {
addr,
debug,
output_format,
}) => get_logs(addr, debug, output_format),
tls,
}) => get_logs(addr, debug, tls, output_format),
}
}
}

fn get(addr: HostAddr, debug: DebugFlag, output_format: OutputFormat) -> Result<(), Error> {
fn get(
addr: HostAddr,
debug: DebugFlag,
tls: TlsCert,
output_format: OutputFormat,
) -> Result<(), Error> {
let url = addr.with_segments(&["v0", "leaders"])?.into_url();
let builder = reqwest::blocking::Client::new().get(url);
let response = RestApiSender::new(builder, &debug).send()?;
let response = RestApiSender::new(builder, &debug, &tls).send()?;
response.ok_response()?;
let leaders = response.body().json_value()?;
let formatted = output_format.format_json(leaders)?;
println!("{}", formatted);
Ok(())
}

fn post(addr: HostAddr, debug: DebugFlag, file: Option<PathBuf>) -> Result<(), Error> {
fn post(
addr: HostAddr,
debug: DebugFlag,
tls: TlsCert,
file: Option<PathBuf>,
) -> Result<(), Error> {
let url = addr.with_segments(&["v0", "leaders"])?.into_url();
let builder = reqwest::blocking::Client::new().post(url);
let input: serde_json::Value = io::read_yaml(&file)?;
let response = RestApiSender::new(builder, &debug)
let response = RestApiSender::new(builder, &debug, &tls)
.with_json_body(&input)?
.send()?;
response.ok_response()?;
println!("{}", response.body().text().as_ref());
Ok(())
}

fn delete(addr: HostAddr, debug: DebugFlag, id: u32) -> Result<(), Error> {
fn delete(addr: HostAddr, debug: DebugFlag, tls: TlsCert, id: u32) -> Result<(), Error> {
let url = addr
.with_segments(&["v0", "leaders", &id.to_string()])?
.into_url();
let builder = reqwest::blocking::Client::new().delete(url);
let response = RestApiSender::new(builder, &debug).send()?;
let response = RestApiSender::new(builder, &debug, &tls).send()?;
response.ok_response()?;
println!("Success");
Ok(())
}

fn get_logs(addr: HostAddr, debug: DebugFlag, output_format: OutputFormat) -> Result<(), Error> {
fn get_logs(
addr: HostAddr,
debug: DebugFlag,
tls: TlsCert,
output_format: OutputFormat,
) -> Result<(), Error> {
let url = addr.with_segments(&["v0", "leaders", "logs"])?.into_url();
let builder = reqwest::blocking::Client::new().get(url);
let response = RestApiSender::new(builder, &debug).send()?;
let response = RestApiSender::new(builder, &debug, &tls).send()?;
response.ok_response()?;
let logs = response.body().json_value()?;
let formatted = output_format.format_json(logs)?;
Expand Down
34 changes: 27 additions & 7 deletions jcli/src/jcli_app/rest/v0/message/mod.rs
@@ -1,6 +1,6 @@
use crate::jcli_app::{
rest::Error,
utils::{io, DebugFlag, HostAddr, OutputFormat, RestApiSender},
utils::{io, DebugFlag, HostAddr, OutputFormat, RestApiSender, TlsCert},
};
use chain_core::property::Deserialize;
use chain_impl_mockchain::fragment::Fragment;
Expand All @@ -20,6 +20,8 @@ pub enum Message {
/// If not provided, message will be read from stdin.
#[structopt(short, long)]
file: Option<PathBuf>,
#[structopt(flatten)]
tls: TlsCert,
},

/// get the node's logs on the message pool. This will provide information
Expand All @@ -32,41 +34,59 @@ pub enum Message {
debug: DebugFlag,
#[structopt(flatten)]
output_format: OutputFormat,
#[structopt(flatten)]
tls: TlsCert,
},
}

impl Message {
pub fn exec(self) -> Result<(), Error> {
match self {
Message::Post { addr, debug, file } => post_message(file, addr, debug),
Message::Post {
addr,
debug,
tls,
file,
} => post_message(file, addr, debug, tls),
Message::Logs {
addr,
debug,
output_format,
} => get_logs(addr, debug, output_format),
tls,
} => get_logs(addr, debug, tls, output_format),
}
}
}

fn get_logs(addr: HostAddr, debug: DebugFlag, output_format: OutputFormat) -> Result<(), Error> {
fn get_logs(
addr: HostAddr,
debug: DebugFlag,
tls: TlsCert,
output_format: OutputFormat,
) -> Result<(), Error> {
let url = addr.with_segments(&["v0", "fragment", "logs"])?.into_url();
let builder = reqwest::blocking::Client::new().get(url);
let response = RestApiSender::new(builder, &debug).send()?;
let response = RestApiSender::new(builder, &debug, &tls).send()?;
response.ok_response()?;
let status = response.body().json_value()?;
let formatted = output_format.format_json(status)?;
println!("{}", formatted);
Ok(())
}

fn post_message(file: Option<PathBuf>, addr: HostAddr, debug: DebugFlag) -> Result<(), Error> {
fn post_message(
file: Option<PathBuf>,
addr: HostAddr,
debug: DebugFlag,
tls: TlsCert,
) -> Result<(), Error> {
let msg_hex = io::read_line(&file)?;
let msg_bin = hex::decode(&msg_hex)?;
let _fragment =
Fragment::deserialize(msg_bin.as_slice()).map_err(Error::InputFragmentMalformed)?;
let url = addr.with_segments(&["v0", "message"])?.into_url();
let builder = reqwest::blocking::Client::new().post(url);
let response = RestApiSender::new(builder, &debug)
let response = RestApiSender::new(builder, &debug, &tls)
.with_binary_body(msg_bin)
.send()?;
response.ok_response()?;
Expand Down
7 changes: 5 additions & 2 deletions jcli/src/jcli_app/rest/v0/network/stats.rs
@@ -1,5 +1,5 @@
use crate::jcli_app::rest::Error;
use crate::jcli_app::utils::{DebugFlag, HostAddr, OutputFormat, RestApiSender};
use crate::jcli_app::utils::{DebugFlag, HostAddr, OutputFormat, RestApiSender, TlsCert};
use structopt::StructOpt;

#[derive(StructOpt)]
Expand All @@ -13,6 +13,8 @@ pub enum Stats {
debug: DebugFlag,
#[structopt(flatten)]
output_format: OutputFormat,
#[structopt(flatten)]
tls: TlsCert,
},
}

Expand All @@ -22,10 +24,11 @@ impl Stats {
addr,
debug,
output_format,
tls,
} = self;
let url = addr.with_segments(&["v0", "network", "stats"])?.into_url();
let builder = reqwest::blocking::Client::new().get(url);
let response = RestApiSender::new(builder, &debug).send()?;
let response = RestApiSender::new(builder, &debug, &tls).send()?;
response.ok_response()?;
let status = response.body().json_value()?;
let formatted = output_format.format_json(status)?;
Expand Down

0 comments on commit b4d7c13

Please sign in to comment.