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
33 changes: 33 additions & 0 deletions src/attested_get.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,25 @@
use crate::{AttestationGenerator, AttestationVerifier, ProxyClient, ProxyError};
use tokio_rustls::rustls::pki_types::CertificateDer;

/// Split an `attested-get` target into a proxy target and an optional request path.
///
/// This lets users write `127.0.0.1:3000/some/path` and still keep the proxy
/// connection target separate from the HTTP request path.
pub fn split_target_and_path(target: &str) -> (String, Option<String>) {
let Some((target_addr, url_path)) = target.split_once('/') else {
return (target.to_string(), None);
};

let url_path = url_path.trim_start_matches('/').to_string();
let url_path = if url_path.is_empty() {
None
} else {
Some(url_path)
};

(target_addr.to_string(), url_path)
}

/// Start a proxy-client, send a single HTTP GET request to the given path and return the
/// [reqwest::Response]
pub async fn attested_get(
Expand Down Expand Up @@ -138,4 +157,18 @@ mod tests {
assert_eq!(content_type, "text/plain");
assert_eq!(&body.to_vec(), b"bar");
}

#[test]
fn split_target_and_path_handles_embedded_path() {
let (target, path) = split_target_and_path("127.0.0.1:3000/some/path");
assert_eq!(target, "127.0.0.1:3000");
assert_eq!(path.as_deref(), Some("some/path"));
}

#[test]
fn split_target_and_path_leaves_bare_target_alone() {
let (target, path) = split_target_and_path("127.0.0.1:3000");
assert_eq!(target, "127.0.0.1:3000");
assert_eq!(path, None);
}
}
17 changes: 11 additions & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use tracing::level_filters::LevelFilter;

use attested_tls_proxy::{
AttestationGenerator, ProxyClient, ProxyServer,
attested_get::attested_get,
attested_get::{attested_get, split_target_and_path},
attested_tls::{
TlsCertAndKey,
attestation::{AttestationType, AttestationVerifier, measurements::MeasurementPolicy},
Expand Down Expand Up @@ -156,17 +156,19 @@ enum CliCommand {
/// Start a proxy-client, send a single HTTP GET request to the given path and print the
/// response to standard output
AttestedGet {
/// The hostname:port or ip:port of the proxy server (port defaults to 443)
/// The hostname:port or ip:port of the proxy server (port defaults to 443) together
/// with the URL path to GET from the target service, eg: 127.0.0.1:3000/foobar
target_addr: String,
#[arg(long)]
/// path to GET (defaults to '/')
url_path: Option<String>,
/// Additional CA certificate to verify against (PEM) Defaults to no additional TLS certs.
#[arg(long)]
tls_ca_certificate: Option<PathBuf>,
/// Enables verification of self-signed TLS certificates
#[arg(long)]
allow_self_signed: bool,
/// Optional path to GET (defaults to '/') - this takes precedence over giving the path
/// as part of the target address.
#[arg(long)]
url_path: Option<String>,
},
}

Expand Down Expand Up @@ -429,9 +431,12 @@ async fn main() -> anyhow::Result<()> {
None => None,
};

let (target_addr, embedded_url_path) = split_target_and_path(&target_addr);
let url_path = url_path.or(embedded_url_path);

let mut response = attested_get(
target_addr,
&url_path.unwrap_or_default(),
url_path.as_deref().unwrap_or("/"),
attestation_verifier,
remote_tls_cert,
allow_self_signed,
Expand Down
Loading