首页 > 解决方案 > 如何使用以 ruby​​ 启动的 SSM 端口转发会话的结果?

问题描述

我无法协调使用 aws cli 和 ruby​​ sdk 与实例建立 ssm 连接之间的差异。例如,如果我尝试使用如下命令:

aws ssm start-session \
  --target 'i-abc123' \
  --document-name AWS-StartPortForwardingSession \
  --parameters '{
    "portNumber": ["3000"], 
    "localPortNumber": ["13000"]
  }'
Starting session with SessionId: username-def456
Port 13000 opened for sessionId username-def456.
Waiting for connections...

Connection accepted for session [username-def456]

该工具将暂停,因为它打开了从目标实例上的端口 3000 到我的本地计算机上的端口 13000 的端口转发会话。然后,我可以在我的机器上打开一个 Web 浏览器并将其指向http://localhost:13000以浏览远程实例上运行的应用程序。此外,我可以查看 AWS 控制台 UI 并看到有一个活动会话,直到我 Ctrl-C

我遇到的麻烦是当我尝试使用 ruby​​ sdk 做同样的事情时:

result = ssm.start_session(
  target: 'i-abc123',  
  document_name: 'AWS-StartPortForwardingSession',  
  parameters: {  
    'portNumber' => %w[3000],    
    'localPortNumber' => %w[13000]    
  }    
)  

result对象是一个结构,如下所示:

=> #<struct Aws::SSM::Types::StartSessionResponse
 session_id="username-def456",
 token_value="...",
 stream_url="wss://ssmmessages.us-east-1.amazonaws.com/v1/data-channel/username-def456? 
 role=publish_subscribe">

同样,我可以在控制台 UI 中看到有一个活动会话。但是,如果我尝试http://localhost:13000在我的机器上浏览,浏览器将无法访问任何内容。如何使用生成的流 url 和令牌来实际创建到 ec2 实例的连接?

额外细节:

标签: rubyaws-sdkaws-ssmaws-sdk-ruby

解决方案


您从 API 中得到的是对 Web 套接字的引用。因此,您要么需要为本地侦听器代理创建自己的 Web 套接字,要么像 aws cli 实用程序那样使用 session-manager-plugin。

我最近想出了如何使用 session-manager-plugin,下面的代码片段是 Python,但应该足够明显,可以弄清楚。

def start_aws_ssm_plugin(self, create_session_response, parameters, profile, region):
    print('start_aws_ssm_plugin() called: ' + str( create_session_response))

    arg0 = '"' + self.config.get_ssm_plugin() + '"'
    arg1 = '"' + str(create_session_response).replace('\'', '\\"') + '"'
    arg2 = region
    arg3 = 'StartSession'
    arg4 = profile
    arg5 = '"' + str(parameters).replace('\'', '\\"') + '"'
    arg6 = 'https://ssm.{region}.amazonaws.com'.format(region=region)

    command = arg0 + ' ' + arg1 + ' ' + arg2 + ' ' + arg3 + ' ' + arg4 + ' ' + arg5 + ' ' + arg6

    print(command)
    # print('session-manager-plugin', arg1, arg2, arg3, arg4, arg5, arg6)

    pid = subprocess.Popen(command).pid
    return pid

# end def

(是的,这只是一个快速而肮脏的原型。;))


推荐阅读