0

I'm having trouble reconciling the differences between using the aws cli and the ruby sdk to make ssm connections to an instance. For example, if I try using the command like like this:

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]

the tool will pause as it opens up a port forwarding session from port 3000 on the destination instance to port 13000 on my local machine. I can then open up a web browser on my machine and point it at http://localhost:13000 to browse around an app running on the remote instance. Also, I can look at the AWS console UI and see that there's an active session until I Ctrl-C

The trouble I'm having is when I try to use the ruby sdk to do the same thing:

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

The result object is a struct that looks like the following:

=> #<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">

Again, I can see in the console UI that there is an active session. However, if I try to browse to http://localhost:13000 on my machine, the browser can't reach anything. How do I use the resulting stream url and token to actually create a connection to the ec2 instance?

additional details:

  • core gem version for the ruby sdk: 3.109.2
  • aws cli version - aws-cli/2.1.16
  • aws ssm agent version - amazon-ssm-agent-3.0.356.0-1.x86_64
matt
  • 9,113
  • 3
  • 44
  • 46

1 Answers1

1

What you get back from the API is a reference to a web socket. So you either need to create your own web socket to local listener proxy or use the session-manager-plugin as the aws cli utility does.

I recently figured out how to use the session-manager-plugin, the following snippet is Python but should be obvious enough to figure it out.

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

(And yes, this was just a quick and dirty prototype.;))