@@ -1524,16 +1524,75 @@ fn registration_failures_keep_causes_and_suppress_repeated_errors_until_recovery
15241524#[ tokio:: test]
15251525async fn registration_token_errors_do_not_expose_secret_file_excerpts ( ) {
15261526 let file = tempfile:: NamedTempFile :: new ( ) . unwrap ( ) ;
1527- std:: fs:: write ( file. path ( ) , br#"{"secret":"do-not-log-this-secret"}"# ) . unwrap ( ) ;
15281527 let provider = stargate_auth:: AuthTokenProvider :: JsonFile {
15291528 path : file. path ( ) . to_owned ( ) ,
15301529 key : vec ! [ "missing" . into( ) ] ,
15311530 } ;
1531+ for contents in [
1532+ r#"{"secret":"do-not-log-this-secret"}"# ,
1533+ r#"{"secret":"do-not-log-this-secret","missing":invalid}"# ,
1534+ ] {
1535+ std:: fs:: write ( file. path ( ) , contents) . unwrap ( ) ;
1536+ let error = super :: router_stream:: resolve_registration_token ( & provider)
1537+ . await
1538+ . unwrap_err ( ) ;
1539+ let detail = recorded_registration_error ( error. as_ref ( ) ) ;
1540+ assert ! ( detail. contains( "failed to resolve registration token" ) ) ;
1541+ assert ! ( detail. contains( "failed to extract key" ) ) ;
1542+ assert ! ( !detail. contains( "do-not-log-this-secret" ) ) ;
1543+ }
1544+ }
1545+
1546+ #[ tokio:: test]
1547+ async fn registration_token_errors_preserve_io_causes ( ) {
1548+ let directory = tempfile:: tempdir ( ) . unwrap ( ) ;
1549+ let provider = stargate_auth:: AuthTokenProvider :: File ( directory. path ( ) . join ( "missing-token" ) ) ;
15321550 let error = super :: router_stream:: resolve_registration_token ( & provider)
15331551 . await
15341552 . unwrap_err ( ) ;
1535- let detail = format ! ( "{error:#}" ) ;
1536- assert ! ( detail. contains( "failed to resolve registration token" ) ) ;
1537- assert ! ( detail. contains( "failed to extract key" ) ) ;
1538- assert ! ( !detail. contains( "do-not-log-this-secret" ) ) ;
1553+ let cause = error. downcast_ref :: < std:: io:: Error > ( ) . unwrap ( ) ;
1554+ assert_eq ! ( cause. kind( ) , std:: io:: ErrorKind :: NotFound ) ;
1555+ let detail = recorded_registration_error ( error. as_ref ( ) ) ;
1556+ assert ! ( detail. contains( "failed to read" ) ) ;
1557+ assert ! ( detail. contains( & cause. to_string( ) ) ) ;
1558+ }
1559+
1560+ #[ tokio:: test]
1561+ async fn registration_http_errors_keep_transport_causes_without_sensitive_urls ( ) {
1562+ let listener = tokio:: net:: TcpListener :: bind ( "127.0.0.1:0" ) . await . unwrap ( ) ;
1563+ let address = listener. local_addr ( ) . unwrap ( ) ;
1564+ // An HTTP peer that closes before responding produces a local client error.
1565+ let server = tokio:: spawn ( async move {
1566+ let ( socket, _) = listener. accept ( ) . await . unwrap ( ) ;
1567+ drop ( socket) ;
1568+ } ) ;
1569+ let error = reqwest:: Client :: new ( )
1570+ . get ( format ! (
1571+ "http://test:private-password@{address}/token?key=private-query"
1572+ ) )
1573+ . send ( )
1574+ . await
1575+ . unwrap_err ( ) ;
1576+ server. await . unwrap ( ) ;
1577+ let detail = recorded_registration_error ( & error) ;
1578+ assert ! ( detail. starts_with( "HTTP " ) , "{detail}" ) ;
1579+ assert ! ( detail. contains( & std:: error:: Error :: source( & error) . unwrap( ) . to_string( ) ) ) ;
1580+ assert ! ( !detail. contains( "private-password" ) ) ;
1581+ assert ! ( !detail. contains( "private-query" ) ) ;
1582+ }
1583+
1584+ fn recorded_registration_error ( error : & ( dyn std:: error:: Error + ' static ) ) -> String {
1585+ let subscriber = RecordingTracingSubscriber :: default ( ) ;
1586+ let dispatch = tracing:: Dispatch :: new ( subscriber. clone ( ) ) ;
1587+ let _guard = tracing:: dispatcher:: set_default ( & dispatch) ;
1588+ super :: grpc_endpoint:: RegistrationFailureLog :: default ( ) . report (
1589+ & grpc_endpoint ( "router.example.test:50071" ) ,
1590+ "register_inference_server" ,
1591+ error,
1592+ ) ;
1593+ subscriber
1594+ . events ( )
1595+ . into_iter ( )
1596+ . find_map ( |event| event. fields . get ( "error" ) . cloned ( ) )
1597+ . unwrap ( )
15391598}
0 commit comments