Skip to content
Closed
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
69 changes: 60 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ members = [
"src/dfx_derive",
"src/dfx_info",
"src/ic_http_agent",
"src/ic_pem_identity",
"src/serde_idl",
]
7 changes: 7 additions & 0 deletions e2e/assets/identity_mo/id_ed25519.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACCbHmRAJATgFut1PhPs6f6UFf7dIAUGB6P4liaGrrANSgAAAJhBYtcDQWLX
AwAAAAtzc2gtZWQyNTUxOQAAACCbHmRAJATgFut1PhPs6f6UFf7dIAUGB6P4liaGrrANSg
AAAEBNNCqQE4QqDWd36q81t7ZLYm1mac35E+5gPl7plR/aYJseZEAkBOAW63U+E+zp/pQV
/t0gBQYHo/iWJoausA1KAAAAEWhhbnNsQEdyaW1tLmxvY2FsAQIDBA==
-----END OPENSSH PRIVATE KEY-----
1 change: 1 addition & 0 deletions e2e/assets/identity_mo/id_ed25519.pem.pub
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJseZEAkBOAW63U+E+zp/pQV/t0gBQYHo/iWJoausA1K dfinity@test.local
5 changes: 5 additions & 0 deletions e2e/assets/identity_mo/identity.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
actor Identity {
public shared(ctx) func get_id() : async [Word32] {
ctx.caller
};
}
1 change: 1 addition & 0 deletions e2e/assets/identity_mo/patch.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dfx config canisters/hello/main identity.mo
26 changes: 26 additions & 0 deletions e2e/identity.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/env bats

load utils/_

setup() {
# We want to work from a temporary directory, different for every test.
cd $(mktemp -d -t dfx-e2e-XXXXXXXX)
export RUST_BACKTRACE=1

dfx_new
}

teardown() {
dfx_stop
}

@test "Can use an identity PEM file to send requests" {
install_asset identity_mo
dfx build
dfx start --background
dfx canister install --all

assert_command dfx canister -p id_ed25519.pem call e2e_project get_id
assert_match "0"
}

1 change: 1 addition & 0 deletions src/dfx/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ flate2 = "1.0.11"
futures = "0.1.28"
hex = "0.3.2"
ic-http-agent = { path = "../ic_http_agent" }
ic_pem_identity = { path = "../ic_pem_identity" }
indicatif = "0.13.0"
lazy-init = "0.3.0"
lazy_static = "1.4.0"
Expand Down
27 changes: 26 additions & 1 deletion src/dfx/src/commands/canister/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use crate::lib::environment::{AgentEnvironment, Environment};
use crate::lib::error::{DfxError, DfxResult};
use crate::lib::message::UserMessage;
use clap::{App, Arg, ArgMatches, SubCommand};
use ic_http_agent::Waiter;
use ic_http_agent::{Signer, Waiter};
use std::path::PathBuf;
use std::time::Duration;

mod call;
Expand Down Expand Up @@ -44,18 +45,42 @@ pub fn construct() -> App<'static, 'static> {
})
.takes_value(true),
)
.arg(
Arg::with_name("profile")
.help(UserMessage::CanisterClient.to_str())
.long("profile")
.short("p")
.validator(|v| {
if PathBuf::from(v).exists() {
Ok(())
} else {
Err("Profile file must exist.".to_string())
}
})
.takes_value(true),
)
.subcommands(builtins().into_iter().map(|x| x.get_subcommand().clone()))
}

pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult {
let subcommand = args.subcommand();

// Need storage for ClientEnvironment ownership.
let maybe_signer: Option<Box<dyn Signer>> = if args.is_present("profile") {
let profile = args.value_of("profile").expect("Could not find profile.");
let profile_path = PathBuf::from(profile);
Some(Box::new(ic_pem_identity::PemIdentity::from_file(
&profile_path,
)?))
} else {
None
};
let mut _client_env: Option<AgentEnvironment<'_>> = None;
let env = if args.is_present("client") {
_client_env = Some(AgentEnvironment::new(
env,
args.value_of("client").expect("Could not find client."),
maybe_signer,
));
_client_env.as_ref().unwrap()
} else {
Expand Down
2 changes: 2 additions & 0 deletions src/dfx/src/commands/new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,8 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult {
)?;

if !dry_run {
ic_pem_identity::PemIdentity::generate(&project_name.join("id.pem"))?;

// If on mac, we should validate that XCode toolchain was installed.
#[cfg(target_os = "macos")]
{
Expand Down
34 changes: 25 additions & 9 deletions src/dfx/src/lib/environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::config::dfx_version;
use crate::lib::error::DfxResult;
use crate::lib::progress_bar::ProgressBar;

use ic_http_agent::{Agent, AgentConfig};
use ic_http_agent::{Agent, AgentConfig, Signer};
use lazy_init::Lazy;
use semver::Version;
use slog::Record;
Expand Down Expand Up @@ -194,14 +194,30 @@ pub struct AgentEnvironment<'a> {
}

impl<'a> AgentEnvironment<'a> {
pub fn new(backend: &'a dyn Environment, agent_url: &str) -> Self {
AgentEnvironment {
backend,
agent: Agent::new(AgentConfig {
url: agent_url,
..AgentConfig::default()
})
.unwrap(),
pub fn new(
backend: &'a dyn Environment,
agent_url: &str,
signer: Option<Box<dyn Signer>>,
) -> Self {
if let Some(signer) = signer {
AgentEnvironment {
backend,
agent: Agent::new(AgentConfig {
url: agent_url,
signer,
..AgentConfig::default()
})
.unwrap(),
}
} else {
AgentEnvironment {
backend,
agent: Agent::new(AgentConfig {
url: agent_url,
..AgentConfig::default()
})
.unwrap(),
}
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions src/dfx/src/lib/error/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mod cache;

pub use build::BuildErrorKind;
pub use cache::CacheErrorKind;
use ic_pem_identity::PemIdentityError;

// TODO: refactor this enum into a *Kind enum and a struct DfxError.
#[derive(Debug)]
Expand Down Expand Up @@ -77,6 +78,9 @@ pub enum DfxError {

/// String provided is not a port
CouldNotParsePort(std::num::ParseIntError),

/// Identity load error when using PEM files.
PemIdentityError(ic_pem_identity::PemIdentityError),
}

/// The result of running a DFX command.
Expand Down Expand Up @@ -117,3 +121,9 @@ impl From<semver::SemVerError> for DfxError {
DfxError::VersionCouldNotBeParsed(err)
}
}

impl From<ic_pem_identity::PemIdentityError> for DfxError {
fn from(err: PemIdentityError) -> Self {
DfxError::PemIdentityError(err)
}
}
Loading