Как создать сеанс терминала на основе URL-адреса WSS, полученного от клиента aws-sdk-ssm в Rust?

Я хочу подключиться к своему экземпляру ec2, используя aws ssm sdk для ржавчины. Как лучше всего создать интерактивный сеанс терминала? Вот следующий код, который я использую для создания сеанса ssm:

    pub async fn create_ssh_session(&self, instance_id: &str) -> Result<()> {
        let output = self
            .client
            .start_session()
            .document_name("SSM-SessionManagerRunShell")
            .target(instance_id)
            .send()
            .await?;

            let wss_url = output.stream_url().unwrap();
            let (mut ws_stream, response) = tokio_tungstenite::connect_async(Url::parse(wss_url)?).await?;

            // Print response to confirm successful connection
            println!("Connected: {}", response.status());

        
            let output = self
            .client
            .terminate_session()
            .session_id(output.session_id().unwrap())
            .send()
            .await?;
        // println!("{:#?}", output);
        Ok(())
    }

Я попытался подключиться к URL-адресу WSS с помощью Tokio Tungstenite, но не уверен, что это лучший способ.

Обновлено: когда я пытаюсь подключиться, мне выдается код состояния 101 (протоколы переключения), что это значит, и после запуска сеанса с ssm я получаю wss_url и токен. Согласно документации, там говорится, что токен используется для аутентификации соединения с управляемым узлом. Я хочу знать, как это сделать при создании потока.

Что вы подразумеваете под «лучшим способом»? Не удается ли этому коду установить соединение, и если да, то в чем заключается ошибка соединения?

user2407038 29.04.2024 18:36

@user2407038 user2407038 Я хочу знать, как правильно создать этот сеанс и присоединиться к нему, а также как я могу создать опыт, подобный ssh. Я обновил вопрос, добавив более подробную информацию!

Souldiv 29.04.2024 21:05
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
0
2
88
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

(вот информация, которую я собрал при создании инструментов с помощью ssm-agent start-session API)

Согласно документации awscli ssm start-session, для вашей ОС требуется sessionmanager-plugin. (ПРИМЕЧАНИЕ: awscli использует тот же API, что и aws SDK)

ДОКУМЕНТЫ: https://docs.aws.amazon.com/cli/latest/reference/ssm/start-session.html#description

sessionmanager-plugin — это набор golang кода, который обрабатывает потоки и протокол веб-сокета (IE: консоль, переадресация портов и т. д.).

https://github.com/aws/session-manager-plugin

Приведенный выше код не упакован как модуль golang, вы можете использовать его в своем проекте в качестве библиотеки для создания двоичных файлов для ваших настроек.

Ответ принят как подходящий

Вместо того, чтобы напрямую общаться с агентом ssm в экземпляре, я решил, что будет проще взаимодействовать с session-manager-plugin, как предложил @john. Я не смог найти достоверной информации об использовании плагина диспетчера сеансов из командной строки, и я задал этот вопрос здесь.

вот основной рабочий процесс создания сеанса с использованием aws sdk для ржавчины с помощью session-manager-plugin:

pub async fn create_ssh_session(&self, instance_id: &str) -> Result<()> {
        // start session get session_id, token_value and stream_url
        let output = self
            .client
            .start_session()
            .document_name("SSM-SessionManagerRunShell")
            .target(instance_id)
            .send()
            .await?;
        
        // create ssm plugin json message
        let response = ResponseJson {
            SessionId: output.session_id().unwrap().to_string(),
            TokenValue: output.token_value().unwrap().to_string(), // Assuming `token` is defined elsewhere
            StreamUrl: output.stream_url().unwrap().to_string(),
        };

        // commenting code for reference 
        // let template =r#"{"Target" : "{instance_id}","DocumentName": "AWS-StartPortForwardingSession","Parameters" : {"portNumber": [22],"localPortNumber": [3232] }}"#;
        // let ssm_plugin_document = json!(template.replace("{instance_id}", instance_id.into()));
        // let plugin_string = serde_json::to_string(&ssm_plugin_document)?;
        let response_string = serde_json::to_string(&response)?;
        let mut session_manager_plugin = Command::new("session-manager-plugin");
        let run_command_output = session_manager_plugin
            .args([
                response_string,
                "ap-southeast-2".into(),
                "StartSession".into(),
                "https://ssm.ap-southeast-2.amazonaws.com/".into(),
            ])
            .spawn()?;
        let result = run_command_output.wait_with_output()?;

        let output = self
            .client
            .terminate_session()
            .session_id(output.session_id().unwrap())
            .send()
            .await?;
        Ok(())
    }

Я просто создаю session-manager-plugin как процесс с правильными аргументами, используя документ SSM-SessionManagerRunShell.

Другие вопросы по теме