photoncloud-monorepo/creditservice/crates/creditservice-server/tests/mtls_integration.rs

77 lines
2.7 KiB
Rust

use creditservice_api::{CreditServiceImpl, InMemoryStorage};
use creditservice_proto::credit_service_server::CreditServiceServer;
use creditservice_client::{Client, TlsConfig};
use rcgen::generate_simple_self_signed;
use std::net::SocketAddr;
use std::sync::Arc;
use tokio::sync::oneshot;
use tonic::transport::{Identity, Server, ServerTlsConfig};
#[tokio::test]
async fn mtls_connects_and_allows_rpc() {
// --- Generate self-signed server and client certs ---
let server = generate_simple_self_signed(vec!["creditservice.local".into()]).unwrap();
let server_cert_pem = server.cert.pem();
let server_key_pem = server.key_pair.serialize_pem();
let client = generate_simple_self_signed(vec!["creditservice-client".into()]).unwrap();
let client_cert_pem = client.cert.pem();
let client_key_pem = client.key_pair.serialize_pem();
// --- Start CreditService server with mTLS ---
let addr: SocketAddr = "127.0.0.1:50057".parse().unwrap();
let storage: Arc<dyn creditservice_api::CreditStorage> = InMemoryStorage::new();
let svc = Arc::new(CreditServiceImpl::new(storage));
let identity = Identity::from_pem(server_cert_pem.clone(), server_key_pem.clone());
let client_ca = tonic::transport::Certificate::from_pem(client_cert_pem.clone());
let (tx, rx) = oneshot::channel::<()>();
let server = Server::builder()
.tls_config(
ServerTlsConfig::new()
.identity(identity)
.client_ca_root(client_ca),
)
.unwrap()
.add_service(CreditServiceServer::new(svc.as_ref().clone()))
.serve_with_shutdown(addr, async {
let _ = rx.await;
});
let server_handle = tokio::spawn(server);
// Give the server a moment to start
tokio::time::sleep(std::time::Duration::from_millis(200)).await;
// --- Client with mTLS ---
let mut client = Client::builder(format!("https://127.0.0.1:{}", addr.port()))
.tls(TlsConfig {
domain: Some("creditservice.local".into()),
ca_cert_pem: Some(server_cert_pem.clone()),
client_cert_pem: Some(client_cert_pem.clone()),
client_key_pem: Some(client_key_pem.clone()),
})
.build()
.await
.expect("client build");
// Simple RPC: create wallet then get wallet
let wallet = client
.create_wallet("proj-mtls", "org-mtls", 1000)
.await
.expect("create_wallet");
assert_eq!(wallet.project_id, "proj-mtls");
assert_eq!(wallet.org_id, "org-mtls");
let fetched = client
.get_wallet("proj-mtls", "org-mtls")
.await
.expect("get_wallet");
assert_eq!(fetched.balance, 1000);
// Shutdown server
let _ = tx.send(());
let _ = server_handle.await;
}