@@ -229,6 +229,81 @@ pub async fn get_public_key(
229229 Ok ( JsonResponse :: build ( ) . set_item ( Some ( response) ) . ok ( "OK" ) )
230230}
231231
232+ /// Response for SSH validation
233+ #[ derive( Debug , Clone , Default , Serialize ) ]
234+ pub struct ValidateResponse {
235+ pub valid : bool ,
236+ pub server_id : i32 ,
237+ pub srv_ip : Option < String > ,
238+ pub message : String ,
239+ }
240+
241+ /// Validate SSH connection for a server
242+ /// POST /server/{id}/ssh-key/validate
243+ ///
244+ /// This endpoint validates that:
245+ /// 1. The server exists and belongs to the user
246+ /// 2. The SSH key is active
247+ /// 3. The key can be retrieved from Vault
248+ ///
249+ /// Note: This does not actually test the SSH connection to the remote server
250+ /// (that would require an SSH client library). It validates the key is ready for use.
251+ #[ tracing:: instrument( name = "Validate SSH key for server." ) ]
252+ #[ post( "/{id}/ssh-key/validate" ) ]
253+ pub async fn validate_key (
254+ path : web:: Path < ( i32 , ) > ,
255+ user : web:: ReqData < Arc < models:: User > > ,
256+ pg_pool : web:: Data < PgPool > ,
257+ vault_client : web:: Data < VaultClient > ,
258+ ) -> Result < impl Responder > {
259+ let server_id = path. 0 ;
260+ let server = verify_server_ownership ( pg_pool. get_ref ( ) , server_id, & user. id ) . await ?;
261+
262+ // Check if server has an active key
263+ if server. key_status != "active" {
264+ let response = ValidateResponse {
265+ valid : false ,
266+ server_id,
267+ srv_ip : server. srv_ip . clone ( ) ,
268+ message : format ! ( "SSH key status is '{}', not active" , server. key_status) ,
269+ } ;
270+ return Ok ( JsonResponse :: build ( )
271+ . set_item ( Some ( response) )
272+ . ok ( "Validation failed" ) ) ;
273+ }
274+
275+ // Verify we can fetch the key from Vault
276+ match vault_client
277+ . get_ref ( )
278+ . fetch_ssh_public_key ( & user. id , server_id)
279+ . await
280+ {
281+ Ok ( _public_key) => {
282+ let response = ValidateResponse {
283+ valid : true ,
284+ server_id,
285+ srv_ip : server. srv_ip . clone ( ) ,
286+ message : "SSH key is valid and ready for connection" . to_string ( ) ,
287+ } ;
288+ Ok ( JsonResponse :: build ( )
289+ . set_item ( Some ( response) )
290+ . ok ( "SSH key validated successfully" ) )
291+ }
292+ Err ( e) => {
293+ tracing:: warn!( "Failed to fetch SSH key from Vault during validation: {}" , e) ;
294+ let response = ValidateResponse {
295+ valid : false ,
296+ server_id,
297+ srv_ip : server. srv_ip . clone ( ) ,
298+ message : "SSH key could not be retrieved from secure storage" . to_string ( ) ,
299+ } ;
300+ Ok ( JsonResponse :: build ( )
301+ . set_item ( Some ( response) )
302+ . ok ( "Validation failed" ) )
303+ }
304+ }
305+ }
306+
232307/// Delete SSH key for a server (disconnect)
233308/// DELETE /server/{id}/ssh-key
234309#[ tracing:: instrument( name = "Delete SSH key for server." ) ]
0 commit comments