Skip to content

Commit 71fadee

Browse files
committed
Merge main
2 parents 7a4e23d + 71d1442 commit 71fadee

File tree

6 files changed

+487
-12
lines changed

6 files changed

+487
-12
lines changed

Cargo.lock

Lines changed: 84 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ license = "MIT"
99

1010
[dependencies]
1111
tokio = { version = "1.48.0", features = ["full"] }
12-
tokio-rustls = { version = "0.26.4", default-features = false, features = ["ring"] }
12+
tokio-rustls = { version = "0.26.4", default-features = false, features = [
13+
"ring",
14+
] }
1315
sha2 = "0.10.9"
1416
x509-parser = "0.18.0"
1517
thiserror = "2.0.17"
@@ -31,7 +33,9 @@ http = "1.3.1"
3133
serde_json = "1.0.145"
3234
serde = "1.0.228"
3335
base64 = "0.22.1"
34-
reqwest = { version = "0.12.23", default-features = false, features = ["rustls-tls-webpki-roots-no-provider"] }
36+
reqwest = { version = "0.12.23", default-features = false, features = [
37+
"rustls-tls-webpki-roots-no-provider",
38+
] }
3539
tracing = "0.1.41"
3640
tracing-subscriber = { version = "0.3.20", features = ["env-filter", "json"] }
3741
parity-scale-codec = "3.7.5"
@@ -42,10 +46,12 @@ num-bigint = "0.4.6"
4246
webpki = { package = "rustls-webpki", version = "0.103.8" }
4347
time = "0.3.44"
4448
once_cell = "1.21.3"
49+
axum = "0.8.6"
50+
tower-http = { version = "0.6.7", features = ["fs"] }
4551

4652
[dev-dependencies]
4753
rcgen = "0.14.5"
48-
axum = "0.8.6"
54+
tempfile = "3.23.0"
4955

5056
[features]
5157
default = ["azure"]

src/attested_get.rs

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
use crate::{AttestationGenerator, AttestationVerifier, ProxyClient, ProxyError};
2+
use tokio_rustls::rustls::pki_types::CertificateDer;
3+
4+
/// Start a proxy-client, send a single HTTP GET request to the given path and return the
5+
/// [reqwest::Response]
6+
pub async fn attested_get(
7+
target_addr: String,
8+
url_path: &str,
9+
attestation_verifier: AttestationVerifier,
10+
remote_certificate: Option<CertificateDer<'static>>,
11+
) -> Result<reqwest::Response, ProxyError> {
12+
let proxy_client = ProxyClient::new(
13+
None,
14+
"127.0.0.1:0".to_string(),
15+
target_addr,
16+
AttestationGenerator::with_no_attestation(),
17+
attestation_verifier,
18+
remote_certificate,
19+
)
20+
.await?;
21+
22+
attested_get_with_client(proxy_client, url_path).await
23+
}
24+
25+
/// Given a configured [ProxyClient], make a GET request to the given path and return the
26+
/// [reqwest::Response]
27+
async fn attested_get_with_client(
28+
proxy_client: ProxyClient,
29+
url_path: &str,
30+
) -> Result<reqwest::Response, ProxyError> {
31+
let proxy_client_addr = proxy_client.local_addr().unwrap();
32+
33+
// Accept a single connection in a separate task
34+
tokio::spawn(async move {
35+
if let Err(err) = proxy_client.accept().await {
36+
tracing::warn!("Atttested get - failed to accept connection: {err}");
37+
}
38+
});
39+
40+
// Remove leading '/' if present
41+
let url_path = url_path.strip_prefix("/").unwrap_or(url_path);
42+
43+
// Make a GET request
44+
let request = reqwest::Request::new(
45+
reqwest::Method::GET,
46+
reqwest::Url::parse(&format!("http://{proxy_client_addr}/{url_path}")).unwrap(),
47+
);
48+
let client = reqwest::Client::new();
49+
let response = client.execute(request).await.unwrap();
50+
Ok(response)
51+
}
52+
53+
#[cfg(test)]
54+
mod tests {
55+
use super::*;
56+
use crate::{
57+
attestation::AttestationType,
58+
file_server::static_file_server,
59+
test_helpers::{generate_certificate_chain, generate_tls_config},
60+
ProxyServer,
61+
};
62+
use tempfile::tempdir;
63+
64+
#[tokio::test]
65+
async fn test_attested_get() {
66+
// Create a temporary directory with a file to serve
67+
let dir = tempdir().unwrap();
68+
let file_path = dir.path().join("foo.txt");
69+
tokio::fs::write(file_path, b"bar").await.unwrap();
70+
71+
// Start a static file server
72+
let target_addr = static_file_server(dir.path().to_path_buf()).await.unwrap();
73+
74+
// Create TLS configuration
75+
let (cert_chain, private_key) = generate_certificate_chain("127.0.0.1".parse().unwrap());
76+
let (server_config, client_config) = generate_tls_config(cert_chain.clone(), private_key);
77+
78+
// Setup a proxy server targetting the static file server
79+
let proxy_server = ProxyServer::new_with_tls_config(
80+
cert_chain,
81+
server_config,
82+
"127.0.0.1:0",
83+
target_addr,
84+
AttestationGenerator::new_not_dummy(AttestationType::DcapTdx).unwrap(),
85+
AttestationVerifier::expect_none(),
86+
)
87+
.await
88+
.unwrap();
89+
90+
let proxy_addr = proxy_server.local_addr().unwrap();
91+
92+
// Accept a single connction
93+
tokio::spawn(async move {
94+
proxy_server.accept().await.unwrap();
95+
});
96+
97+
// Setup a proxy client
98+
let proxy_client = ProxyClient::new_with_tls_config(
99+
client_config,
100+
"127.0.0.1:0".to_string(),
101+
proxy_addr.to_string(),
102+
AttestationGenerator::with_no_attestation(),
103+
AttestationVerifier::mock(),
104+
None,
105+
)
106+
.await
107+
.unwrap();
108+
109+
// Make a GET request
110+
let response = attested_get_with_client(proxy_client, "foo.txt")
111+
.await
112+
.unwrap();
113+
114+
// Check the response
115+
let content_type = response
116+
.headers()
117+
.get(reqwest::header::CONTENT_TYPE)
118+
.and_then(|h| h.to_str().ok())
119+
.unwrap()
120+
.to_string();
121+
122+
let body = response.bytes().await.unwrap();
123+
assert_eq!(content_type, "text/plain");
124+
assert_eq!(&body.to_vec(), b"bar");
125+
}
126+
}

0 commit comments

Comments
 (0)