use clap::Parser; use jwt_simple::algorithms::HS256Key; use jwt_simple::prelude::{Clock, Duration, JWTClaims, MACLike}; use matrix_gateway::extractors::client_auth::TokenClaims; use matrix_gateway::utils::rand_str; use std::ops::Add; use std::os::unix::prelude::CommandExt; use std::process::Command; /// cURL wrapper to query MatrixGW #[derive(Parser, Debug)] #[command(version, about, long_about = None)] struct Args { /// URL of Matrix GW #[arg(short('U'), long, env, default_value = "http://localhost:8000")] matrix_gw_url: String, /// Token ID #[arg(short('i'), long, env)] token_id: String, /// User ID #[arg(short('u'), long, env)] user_id: String, /// Token secret #[arg(short('t'), long, env)] token_secret: String, /// Request verb #[arg(short('X'), long, default_value = "GET")] method: String, /// Payload SHA256 digest #[arg(short('D'), long)] payload_digest: Option, /// Request URI uri: String, /// Command line arguments to pass to cURL #[clap(trailing_var_arg = true, allow_hyphen_values = true)] run: Vec, } fn main() { let args: Args = Args::parse(); let full_url = format!("{}{}", args.matrix_gw_url, args.uri); log::debug!("Full URL: {full_url}"); let key = HS256Key::from_bytes(args.token_secret.as_bytes()); let claims = JWTClaims:: { issued_at: Some(Clock::now_since_epoch()), expires_at: Some(Clock::now_since_epoch().add(Duration::from_mins(15))), invalid_before: None, issuer: None, subject: None, audiences: None, jwt_id: None, nonce: Some(rand_str(10)), custom: TokenClaims { method: args.method.to_string(), uri: args.uri, payload_sha256: args.payload_digest.clone(), }, }; let jwt = key .with_key_id(&format!( "{}#{}", urlencoding::encode(&args.user_id), urlencoding::encode(&args.token_id) )) .authenticate(claims) .expect("Failed to sign JWT!"); let _ = Command::new("curl") .args(["-X", &args.method]) .args(["-H", &format!("x-client-auth: {jwt}")]) .args(args.run) .arg(full_url) .exec(); panic!("Failed to run curl!") }