Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
451 changes: 426 additions & 25 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[workspace]
members = ["crates/*"]
resolver = "2"
resolver = "2"
3 changes: 3 additions & 0 deletions crates/common/src/api/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ pub trait ApiClient {
AuthMode::NoAuth => request_builder,
AuthMode::ApiKey(api_key) => request_builder.header("api-key", api_key),
AuthMode::BearerAuth(token) => request_builder.bearer_auth(token),
AuthMode::BasicAuth((api_key, app_uuid)) => {
request_builder.basic_auth(app_uuid, Some(api_key))
}
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions crates/common/src/api/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
pub mod assets;
pub mod client;
pub mod papi;

pub use reqwest::Client;

pub type BasicAuth = (String, String);

#[derive(Clone)]
pub enum AuthMode {
NoAuth,
ApiKey(String),
BearerAuth(String),
BasicAuth(BasicAuth),
}
79 changes: 79 additions & 0 deletions crates/common/src/api/papi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use self::client::{ApiResult, HandleResponse};
use crate::relay::{CreateRelay, Relay};

use super::*;
use super::{
client::{ApiClient, ApiClientError, GenericApiClient},
AuthMode, BasicAuth,
};

/// Client for Evervault API
pub struct EvApiClient {
inner: GenericApiClient,
}

impl ApiClient for EvApiClient {
fn client(&self) -> &reqwest::Client {
self.inner.client()
}

fn base_url(&self) -> String {
let domain = std::env::var("EV_DOMAIN").unwrap_or_else(|_| String::from("evervault.com"));
format!("https://api.{}", domain)
}

fn auth(&self) -> &AuthMode {
self.inner.auth()
}

fn update_auth(&mut self, _: AuthMode) -> Result<(), ApiClientError> {
Err(ApiClientError::AuthModeNotSupported)
}
}

impl EvApiClient {
pub fn new(auth: BasicAuth) -> Self {
Self {
inner: GenericApiClient::from(AuthMode::BasicAuth(auth)),
}
}
}

#[async_trait::async_trait]
#[cfg_attr(test, mockall::automock)]
pub trait EvApi {
async fn update_relay(&self, relay: &Relay) -> ApiResult<crate::relay::Relay>;
async fn create_relay(&self, relay: &Relay) -> ApiResult<crate::relay::Relay>;
}

#[async_trait::async_trait]
impl EvApi for EvApiClient {
async fn update_relay(&self, relay: &Relay) -> ApiResult<crate::relay::Relay> {
let update_relay_url = format!(
"{}/relays/{}",
self.base_url(),
relay.id.clone().expect("Relay ID is required")
);

self.patch(&update_relay_url)
.json(&CreateRelay {
encrypt_empty_strings: relay.encrypt_empty_strings,
authentication: relay.authentication.clone(),
routes: relay.routes.clone(),
})
.send()
.await
.handle_json_response()
.await
}

async fn create_relay(&self, relay: &Relay) -> ApiResult<crate::relay::Relay> {
let create_relay_url = format!("{}/relays", self.base_url());
self.post(&create_relay_url)
.json(&relay)
.send()
.await
.handle_json_response()
.await
}
}
2 changes: 1 addition & 1 deletion crates/common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pub mod api;
pub mod enclave;

pub mod relay;
pub trait CliError {
fn exitcode(&self) -> exitcode::ExitCode;
}
58 changes: 58 additions & 0 deletions crates/common/src/relay/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use serde::{Deserialize, Serialize};

#[derive(Deserialize, Debug, Clone, Serialize)]
pub struct RelaySelections {
r#type: String,
#[serde(skip_serializing_if = "Option::is_none")]
role: Option<String>,
selector: String,
}

#[derive(Deserialize, Debug, Clone, Serialize)]
pub struct RelayAction {
action: String,
selections: Vec<RelaySelections>,
}

#[derive(Deserialize, Debug, Serialize)]
pub struct RelayResponse {
method: String,
path: String,
relay: String,
}

#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct RelayRoutes {
method: Option<String>,
path: String,
request: Option<Vec<RelayAction>>,
response: Option<Vec<RelayAction>>,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Relays {
pub data: Vec<Relay>,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Relay {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
pub destination_domain: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub evervault_domain: Option<String>,
pub encrypt_empty_strings: bool,
pub authentication: Option<String>,
pub routes: Vec<RelayRoutes>,
#[serde(skip_serializing_if = "Option::is_none")]
pub app: Option<String>,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateRelay {
pub encrypt_empty_strings: bool,
pub authentication: Option<String>,
pub routes: Vec<RelayRoutes>,
}
34 changes: 20 additions & 14 deletions crates/ev-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,26 +1,32 @@
[package]
edition = "2021"
name = "ev-cli"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
async-trait = "0.1.80"
attestation-doc-validation = "0.7.4"
atty = "0.2.14"
clap = { version = "4.5.4", features = ["derive"] }
serde = { version= "1.0.199", features = ["derive"] }
serde_json = "1.0.116"
thiserror = "1.0.59"
tokio = { version = "1.37.0", features = ["rt", "rt-multi-thread", "macros", "fs"] }
human-panic = "1.0.3"
log = "0.4.17"
chrono = "0.4.19"
clap = {version = "4.5.4", features = ["derive"]}
common = {path = "../common"}
dialoguer = "0.10.2"
env_logger = "0.9.0"
ev-enclave = {path = "../ev-enclave"}
exitcode = "1.1.2"
dialoguer = "0.10.2"
attestation-doc-validation = "0.7.4"
ev-enclave = { path = "../ev-enclave" }
common = { path = "../common" }
chrono = "0.4.19"
toml = "0.5.9"
human-panic = "1.0.3"
lazy_static = "1.4.0"
log = "0.4.17"
regex = "1.10.4"
semver = "1.0.20"
sentry = "0.32.3"
serde = {version = "1.0.199", features = ["derive"]}
serde_json = "1.0.116"
strum = { version = "0.26.2", features = [ "derive", "strum_macros" ]}
strum_macros = "0.26.2"
tempfile = "3.3.0"
thiserror = "1.0.59"
tokio = {version = "1.37.0", features = ["rt", "rt-multi-thread", "macros", "fs"]}
toml = "0.5.9"
45 changes: 21 additions & 24 deletions crates/ev-cli/src/auth.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,29 @@
#[macro_export]
macro_rules! get_auth {
() => {
match (std::env::var("EV_API_KEY"), std::env::var("EV_APP_UUID")) {
(Ok(api_key), Ok(app_uuid)) => (api_key, app_uuid),
(Err(_), Err(_)) => {
log::error!(
"No App UUID or API key found. Make sure you have correctly set the \
pub fn get_auth() -> (String, String) {
match (std::env::var("EV_API_KEY"), std::env::var("EV_APP_UUID")) {
(Ok(api_key), Ok(app_uuid)) => (api_key, app_uuid),
(Err(_), Err(_)) => {
log::error!(
"No App UUID or API key found. Make sure you have correctly set the \
EV_APP_UUID and EV_API_KEY environment variables. See \
https://docs.evervault.com/sdks/cli for more information."
);
return crate::errors::NOUSER;
}
(Err(_), _) => {
log::error!(
"No API Key found. Make sure you have correctly set the EV_API_KEY \
);
std::process::exit(crate::errors::NOUSER);
}
(Err(_), _) => {
log::error!(
"No API Key found. Make sure you have correctly set the EV_API_KEY \
environment variable. See https://docs.evervault.com/sdks/cli for more \
information."
);
return crate::errors::NOUSER;
}
(_, Err(_)) => {
log::error!(
"No App UUID found. Make sure you have correctly set the EV_APP_UUID \
);
std::process::exit(crate::errors::NOUSER);
}
(_, Err(_)) => {
log::error!(
"No App UUID found. Make sure you have correctly set the EV_APP_UUID \
environment variable. See https://docs.evervault.com/sdks/cli for more \
information."
);
return crate::errors::NOUSER;
}
);
std::process::exit(crate::errors::NOUSER);
}
};
}
}
11 changes: 6 additions & 5 deletions crates/ev-cli/src/commands/enclave/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ pub struct EnclaveArgs {
}

#[derive(Parser, Debug)]
#[command(name = "enclave")]
pub enum EnclaveCommand {
#[cfg(not(target_os = "windows"))]
Attest(attest::AttestArgs),
Expand All @@ -46,16 +45,16 @@ pub enum AuthenticatedEnclaveCommand {
Scale(scale::ScaleArgs),
}

pub async fn run(enclave_args: EnclaveArgs) -> i32 {
match enclave_args.action {
pub async fn run(enclave_args: EnclaveArgs) {
let exitcode = match enclave_args.action {
EnclaveCommand::Build(build_args) => build::run(build_args).await,
EnclaveCommand::Describe(describe_args) => describe::run(describe_args).await,
EnclaveCommand::Migrate(migrate_args) => migrate::run(migrate_args).await,
#[cfg(not(target_os = "windows"))]
EnclaveCommand::Attest(attest_args) => attest::run(attest_args).await,
EnclaveCommand::Update(update_args) => update::run(update_args).await,
EnclaveCommand::Authenticated(authenticated_command) => {
let (api_key, _) = crate::get_auth!();
let (api_key, _) = crate::get_auth();

match authenticated_command {
AuthenticatedEnclaveCommand::Cert(cert_args) => cert::run(cert_args, api_key).await,
Expand All @@ -76,5 +75,7 @@ pub async fn run(enclave_args: EnclaveArgs) -> i32 {
}
}
}
}
};

std::process::exit(exitcode);
}
Loading