Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cli): Add web3signer KeySource #513

Merged
merged 10 commits into from
Dec 5, 2024
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
fix TLS issue with reqwest
James Snewin committed Dec 5, 2024
commit 0461b6903ff7531ae3522e30fa3dfe6221ed02e3
79 changes: 79 additions & 0 deletions bolt-cli/Cargo.lock

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

2 changes: 1 addition & 1 deletion bolt-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -38,7 +38,7 @@ thiserror = "1.0"
hex = "0.4.3"
tracing = "0.1.40"
tracing-subscriber = "0.3.18"
reqwest = { version = "0.12.8", features = ["native-tls"] }
reqwest = { version = "0.12.9", features = ["rustls-tls"] }
rand = "0.8.5"

[dev-dependencies]
14 changes: 12 additions & 2 deletions bolt-cli/src/cli.rs
Original file line number Diff line number Diff line change
@@ -434,9 +434,19 @@ pub struct Web3SignerOpts {
pub url: String,

/// The TLS credentials for connecting to the Web3Signer keystore.
/// Note: it is at the users discretion to enable TLS on the Web3Signer.
#[clap(flatten)]
pub tls_credentials: TlsCredentials,
pub tls_credentials: RustTlsCredentials,
}

/// TLS credentials which are used for rustls-tls when connecting to reqwest.
#[derive(Debug, Clone, PartialEq, Eq, Parser)]
pub struct RustTlsCredentials {
tsnewnami marked this conversation as resolved.
Show resolved Hide resolved
/// Path to the CA certificate file. (.crt)
#[clap(long, env = "CA_CERT_PATH")]
pub ca_cert_path: String,
/// Path to the PEM encoded private key and certificate file. (.pem)
#[clap(long, env = "CLIENT_COMBINED_PEM")]
pub combined_pem_path: String,
}

/// TLS credentials for connecting to a remote server.
55 changes: 24 additions & 31 deletions bolt-cli/src/common/web3signer.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
use std::{
collections::HashMap,
fs::{self, File},
io::Read,
};
use std::{collections::HashMap, fs::File, io::Read};

use crate::cli::TlsCredentials;
use crate::cli::RustTlsCredentials;
use eyre::{Context, Result};
use reqwest::{Certificate, Identity, Url};
use serde::Deserialize;
@@ -22,16 +18,17 @@ pub struct Web3Signer {
client: reqwest::Client,
}

// Works: reqwest::Client::builder().add_root_certificate(cert).use_rustls_tls().build()?;

impl Web3Signer {
pub async fn connect(addr: String, credentials: TlsCredentials) -> Result<Self> {
pub async fn connect(addr: String, credentials: RustTlsCredentials) -> Result<Self> {
// Establish connection with TLS config.
let base_url = addr.parse()?;
let (cert, identity) = compose_credentials(credentials)?;
let client = reqwest::Client::builder()
// TODO: handle this properly
.danger_accept_invalid_certs(true)
.add_root_certificate(cert)
.identity(identity)
.use_rustls_tls()
.build()?;

Ok(Self { base_url, client })
@@ -99,20 +96,20 @@ impl Web3Signer {
}
}

pub fn compose_credentials(credentials: TlsCredentials) -> Result<(Certificate, Identity)> {
// Create certificate.
pub fn compose_credentials(credentials: RustTlsCredentials) -> Result<(Certificate, Identity)> {
// Create pem certificate.
let mut buff = Vec::new();
File::open(credentials.client_cert_path.clone())
File::open(credentials.ca_cert_path)
.wrap_err("Failed to read client cert")?
.read_to_end(&mut buff)
.wrap_err("Failed to read client cert into buffer")?;
let cert = Certificate::from_pem(&buff)?;

// Create identity.
let cert_read =
fs::read(credentials.client_cert_path).wrap_err("Failed to read client cert")?;
let key_read = fs::read(credentials.client_key_path).wrap_err("Failed to read client key")?;
let identity = Identity::from_pkcs8_pem(&cert_read, &key_read)?;
// Create pem identity.
let mut buff = Vec::new();
File::open(credentials.combined_pem_path).unwrap().read_to_end(&mut buff).unwrap();
let identity = Identity::from_pem(&buff).unwrap();

Ok((cert, identity))
}

@@ -123,18 +120,21 @@ pub mod test_util {
time::Duration,
};

use crate::cli::TlsCredentials;
use crate::cli::RustTlsCredentials;
use eyre::{bail, Ok};

pub async fn start_web3signer_test_server() -> eyre::Result<(String, Child, TlsCredentials)> {
pub async fn start_web3signer_test_server() -> eyre::Result<(String, Child, RustTlsCredentials)>
{
// Key store test data.
let test_data_dir =
env!("CARGO_MANIFEST_DIR").to_string() + "/test_data/web3signer/keystore";

// TLS test data.
let tls_dir = env!("CARGO_MANIFEST_DIR").to_string() + "/test_data/web3signer/tls/";
let tls_keystore = tls_dir.clone() + "key.p12";
let tls_password = tls_dir + "password.txt";
let tls_password = tls_dir.clone() + "password.txt";
let tls_cirt = tls_dir.clone() + "web3signer.crt";
let combined_pem = tls_dir.clone() + "combined.pem";

// Check if web3signer is installed (in $PATH).
if Command::new("web3signer").spawn().is_err() {
@@ -168,16 +168,9 @@ pub mod test_util {
tokio::time::sleep(Duration::from_secs(5)).await;

// TLS client test data.
let client_tls_dir = env!("CARGO_MANIFEST_DIR").to_string() + "/test_data/dirk_single";

// TLS credentials.
let credentials = TlsCredentials {
client_cert_path: client_tls_dir.clone() + "/client1.crt",
client_key_path: client_tls_dir + "/client1.key",
ca_cert_path: None,
};

// Connect to the Web3Signer client.
let credentials =
RustTlsCredentials { ca_cert_path: tls_cirt, combined_pem_path: combined_pem };
// The URL of the web3signer.
let url = "https://127.0.0.1:9000".to_string();

Ok((url, web3signer_proc, credentials))
@@ -191,7 +184,7 @@ mod tests {
/// Test for connecting to the Web3Signer and listing accounts.
///
/// ```shell
/// cargo test --package bolt --bin bolt -- common::web3signer::tests
/// cargo test --package bolt --bin bolt -- common::web3signer::tests::test_web3signer_connection_e2e
/// --exact --show-output --ignored
/// ```
#[tokio::test]
83 changes: 83 additions & 0 deletions bolt-cli/test_data/web3signer/tls/combined.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
-----BEGIN CERTIFICATE-----
MIIFVzCCAz+gAwIBAgIUS6WAuJjrNKU6qzOR3/cxTooU9/IwDQYJKoZIhvcNAQEL
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNDEwMjIwOTA2MjFaFw0yOTEw
MjEwOTA2MjFaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEB
BQADggIPADCCAgoCggIBANyTDRfa37FhTG2qEPckYPR6vP1tFcUqatK1V5mhKk7p
U38dF5YtCwuNX0FH/iG4fe7w3Xavt86aVVOpUF/Vxy3becv+RThpmUbRzCN/FlfT
ZzxsEMN/VFABRarxQK24UCbjnQ7p/yHiXOeRE5pAgBanp5uKKkSq+qEo9sb7s0w9
c6ifgXQR/GuX68yui1XiJgE3WlkTk/hvKbbOAAhuzE0x9atndbFfBRMO1Sz7zScH
HF0cp/YI2SRx5cx7ovj9biOR0hi0Af+DuHT15vznDkfMo4sAT28CeBjtXBM1eYY9
cm6gD7zm35+kcD2xulVkw4a/AueBLOwiszclnIKULC1t4ubuwYx6Be2uGrwBy2x3
sJh8NoMVqGqZLfVmZ7qpah1iBMsuGhH+NjZtdiKeFtU2KhOkbpUlSVHCoL3Qn8xY
eytg7IqyfXZ0YSVnE3YsAJDCOjh1vQXTK0FMkt4z4uaM8UepG5ucurhQpGcEbcSj
DLxLbHMlR4dMFNlR825OPBBVpNLxXyfsHNuftJmX0OziSS2glVjYERqRWpkglgh2
EHL2P2R63LRMNr9qKJBdZbHzschURvcZLuNr8dqkCS83vtOhHhCH9Hyl+QZC9w+F
MgIgdbxyE0iSUwVu2gwWqoPLC9gf0rssLxySkaKXUEizpbcuyb9qnT/JlNxahaDd
AgMBAAGjcDBuMB8GA1UdIwQYMBaAFO3Lnl1Id4OcqYwhtgbFXrx6min4MAkGA1Ud
EwQCMAAwCwYDVR0PBAQDAgTwMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDAdBgNVHQ4E
FgQUWlWshAUj6JXYhYHPlSKkBCx2A9swDQYJKoZIhvcNAQELBQADggIBACuvuqA1
aL+iiyZw8DUnPgBFHoFRbViLKLxg6Qiqv/ldvoLYKYzE5rlCuSoSRoh2cd7Du3i8
66cRrp8eh70XiHM5P7034BdYzIo7oCHfEmVPJpo1+G85+WbNzTf2ZLNFGoeudOGw
Kvwkxb4gr2xX03EOms/w2EyVycdQ0u7Y0yaDluDhXQF2ynJYnXDGx5oIrwp9YQWF
neGSyCTP4A67QybKYaA1p1Jibhv3i4QPcFHFOSOFOidqWn01zY/TS0kxQvFpX9cB
7LjMTujHiTdZGZVHFAf9gAlMXQ1jvYdUf9r1qOXvnBOLI/aqV5fLKqgXXmqt5WFZ
bhtbUVhEu4OEavgboPOt3WUpbXSnHyVR7t/f/wtycOnfTcYcQb2dZAGRyLP/cVQt
nDBElrpUHizysNuNMa1rfd/3WC0FvC0/M2OwNK1ad9itctGKel0UrTvCU59/GO3C
P6Q2EFxyQc1wAgekkBZQX5se9RcTo8VJlV16ZMlo4tm3l57YtHwipKCVVf7EUgxu
Bsj21nBY5nOIHzaYAqF5Bz7/Lg/9IFuVx/sPatcMYmUcYkPSvm/1uRB17lr30sQp
bOKGbxzv00JFBwF0t6ZO/XnpLQiHLBtbwgGKMUak0/wZiFiZPmcdaljHLqq08fPV
S3zuTPjwU2aaQsAqAu9F/B1Cn2/gFiJEL/Mg
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
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
nJqYM6m13Q+F0Wu8krDMA65Wi5nA
-----END PRIVATE KEY-----
Loading