如何用Rust的AWS SSM SDK从WSS URL创建交互式终端会话并认证?
Rust版AWS SSM SDK创建EC2交互式终端会话指南
一、tokio_tungstenite的适用性及最佳实践
tokio_tungstenite是Rust生态中适配Tokio异步 runtime的WebSocket客户端,完全适合用于SSM会话的WSS连接——AWS SSM会话本身就是基于WebSocket协议实现终端数据双向传输,和你使用的异步版AWS SSM SDK天然兼容,这是合理的技术选型。
你当前的代码存在核心问题:建立WebSocket连接后立即终止会话,无法实现交互式终端功能。要完成完整的交互式会话,需要同时处理两个异步任务:
- 读取本地终端输入并发送到WebSocket流
- 接收WebSocket返回的SSM实例输出并打印到本地终端
以下是优化后的代码示例,包含认证处理、双向消息传输及会话生命周期管理:
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader}; use tokio_tungstenite::tungstenite::Message; use aws_sdk_ssm::Client; use std::error::Error; pub async fn create_ssh_session(client: &Client, instance_id: &str) -> Result<(), Box<dyn Error>> { // 启动SSM会话 let session_output = client .start_session() .document_name("SSM-SessionManagerRunShell") .target(instance_id) .send() .await?; let wss_url = session_output.stream_url().ok_or("Failed to get stream URL")?; let session_token = session_output.token().ok_or("Failed to get session token")?; let session_id = session_output.session_id().ok_or("Failed to get session ID")?; // 构建带认证头的WebSocket请求 let url = url::Url::parse(wss_url)?; let request = http::Request::get(url) .header("X-Aws-Ssm-Session-Token", session_token) .body(())?; // 建立WebSocket连接 let (mut ws_stream, response) = tokio_tungstenite::connect_async(request).await?; println!("Connected: {}", response.status()); // 任务1:读取本地终端输入并发送到SSM会话 let mut stdin = BufReader::new(tokio::io::stdin()).lines(); let mut ws_sender = ws_stream.split().0; let input_task = tokio::spawn(async move { while let Some(line) = stdin.next_line().await.unwrap() { if let Err(e) = ws_sender.send(Message::Text(format!("{}\n", line))).await { eprintln!("Failed to send message: {}", e); break; } } }); // 任务2:接收SSM会话输出并打印到本地终端 let mut ws_receiver = ws_stream.split().1; let output_task = tokio::spawn(async move { while let Some(msg) = ws_receiver.next().await { match msg { Ok(Message::Text(text)) => print!("{}", text), Ok(Message::Binary(data)) => print!("{}", String::from_utf8_lossy(&data)), Err(e) => { eprintln!("Failed to receive message: {}", e); break; } _ => {}, } } }); // 等待任一任务结束(比如用户退出输入) tokio::select! { _ = input_task => {}, _ = output_task => {}, } // 终止SSM会话 client .terminate_session() .session_id(session_id) .send() .await?; Ok(()) }
二、状态码101(Switching Protocols)的含义
101是HTTP协议的正常响应状态码,代表服务器同意客户端的协议切换请求。在WebSocket连接流程中:
- 客户端先发送HTTP请求,携带
Upgrade: websocket和Connection: Upgrade头,请求从HTTP协议切换到WebSocket协议 - 服务器返回101响应,确认协议切换完成
- 后续通信不再使用HTTP格式,改用WebSocket帧传输数据
这个状态码说明你的WebSocket握手已经成功,无需担心。
三、Session Token的认证方式
SSM返回的Session Token是验证会话合法性的凭证,需要在WebSocket握手请求中通过自定义请求头传递:
- 头名称:
X-Aws-Ssm-Session-Token - 头值:
start_session接口返回的token字段值
在代码中,你需要通过http::Request构建自定义请求(而非直接传入URL),将Token添加到请求头中,如上述示例代码所示。这样SSM服务端就能验证你的会话权限,允许建立数据流连接。
内容的提问来源于stack exchange,提问作者Souldiv
相关产品推荐
相关产品推荐

