vpcjump 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/Gemfile +4 -0
- data/README.md +87 -0
- data/Rakefile +2 -0
- data/exe/vpcjump +95 -0
- data/lib/vpcjump/version.rb +3 -0
- data/lib/vpcjump.rb +5 -0
- data/vpcjump.gemspec +29 -0
- metadata +136 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 91bc9c02d6d0df3b88ee4e7660859087db1666ef
|
4
|
+
data.tar.gz: 058a24349db38b81fb048eb9a464493c47701559
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 269e9d7410ab40a60c21bd3625b948e3cd96ca0e4712109dab73c7debf413a4ed94fcbb0ebeb48332f43567e908d9780bffe87169d5cd5cd6a6b7d8472d16699
|
7
|
+
data.tar.gz: 2cf93eb463b09b39e2da84b575e38c7fd016de82089d7b7815d1bc265b670b65023aba0f5f28c54ea234bdc64c407a49801ab1e89e581c55df1bb739c644e4ed
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
# `vpcjump`
|
2
|
+
|
3
|
+
`vpcjump` is a helper tool to make it as easy as possible to connect to a jumpbox in an AWS [VPC](https://aws.amazon.com/vpc/).
|
4
|
+
|
5
|
+
What makes `vpcjump` unique is that your jumpbox doesn't need a public IP nor needs to open any ports in a security group. What it _does_ need is outbound Internet connectivity on port 443 - whether via a [NAT instance](http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_NAT_Instance.html), Amazon-managed [NAT gateway](http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/vpc-nat-gateway.html) or some custom solution.
|
6
|
+
|
7
|
+
## Setup
|
8
|
+
|
9
|
+
* Install the tool: `gem install vpcjump`
|
10
|
+
* Sign up for [ngrok](https://ngrok.com/) and note down your authentication token
|
11
|
+
* Start an instance in EC2 - this only needs to be done once.
|
12
|
+
|
13
|
+
You can launch the EC2 instance from the AWS web console. Amazon Linux on a t2.nano is sufficient. The t2.nano is less than $5/month (as little as $2.16/month if paid upfront!) so leaving it always up is quite affordable.
|
14
|
+
|
15
|
+
When on step 3 (**Configure Instance Details**), expand **Advanced Details** and paste the following into **User data**:
|
16
|
+
|
17
|
+
```
|
18
|
+
#!/bin/bash
|
19
|
+
cd /tmp
|
20
|
+
curl https://amazon-ssm-ap-southeast-2.s3.amazonaws.com/latest/linux_amd64/amazon-ssm-agent.rpm -o amazon-ssm-agent.rpm
|
21
|
+
yum install -y amazon-ssm-agent.rpm
|
22
|
+
curl https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip -o ngrok.zip
|
23
|
+
unzip ngrok.zip
|
24
|
+
mv ngrok /usr/bin/
|
25
|
+
```
|
26
|
+
|
27
|
+
You will also need to create and select an **IAM Role** for this instance to grant it permission to use [SSM](http://docs.aws.amazon.com/ssm/latest/APIReference/Welcome.html). To do this, you:
|
28
|
+
|
29
|
+
* Click **Create new IAM role**
|
30
|
+
* Click **Create New Role**
|
31
|
+
* Specify a role name of your choice, e.g.`SSMForVpcjump`, then hit next.
|
32
|
+
* Under **AWS Service Roles**, select **Amazon EC2 Role for Simple Systems Manager**, then hit next.
|
33
|
+
* Tick the checkbox for **AmazonEC2RoleforSSM**, then next.
|
34
|
+
* Click **Create Role**.
|
35
|
+
* Return to the instance creation screen, hit refresh next to **IAM Role**, then select the role you just created.
|
36
|
+
|
37
|
+
You can now proceed through the instance creation process - all the default values are fine. You can delete the security group rule opening up access to port 22 if you wish, this is unneeded. Once the instance has launched, note down the instance ID (looks like `i-abcdef`) as you will use it later.
|
38
|
+
|
39
|
+
## Usage
|
40
|
+
|
41
|
+
Invocation can be as simple as `vpcjump --ngrok-token <auth token> --instance-id i-abc123 ssh`. This takes about 30 seconds and will SSH you into the jumpbox instance. The complete list of options is:
|
42
|
+
|
43
|
+
```
|
44
|
+
$ vpcjump --help
|
45
|
+
Usage:
|
46
|
+
vpcjump [OPTIONS] SUBCOMMAND [ARG] ...
|
47
|
+
|
48
|
+
Parameters:
|
49
|
+
SUBCOMMAND subcommand
|
50
|
+
[ARG] ... subcommand arguments
|
51
|
+
|
52
|
+
Subcommands:
|
53
|
+
kill Terminate ngrok tunnel
|
54
|
+
ssh SSH into the jumpbox
|
55
|
+
|
56
|
+
Options:
|
57
|
+
--instance-id INSTANCE ID EC2 instance id of jump box (e.g. i-abc123)
|
58
|
+
--name INSTANCE NAME EC2 instance name of jump box
|
59
|
+
--ngrok-token NGROK TOKEN ngrok auth token
|
60
|
+
--ngrok-region NGROK REGION ngrok region (default: "us")
|
61
|
+
-v, --verbose Output AWS API calls
|
62
|
+
-h, --help print help
|
63
|
+
|
64
|
+
$ vpcjump ssh --help
|
65
|
+
Usage:
|
66
|
+
vpcjump ssh [OPTIONS] [SSHPARAMS] ...
|
67
|
+
|
68
|
+
Parameters:
|
69
|
+
[SSHPARAMS] ... Arguments to pass to SSH
|
70
|
+
|
71
|
+
Options:
|
72
|
+
--ssh-user SSH USER SSH user (default: "ec2-user")
|
73
|
+
```
|
74
|
+
|
75
|
+
Often you will want to use the jumpbox as an intermediary in order to connect to a second instance. This can be done using SSH port forwarding, e.g. `vpcjump --ngrok-token <auth token> --instance-id i-abc123 ssh -- -L 3389:172.16.0.1:3389` - This will let you to connect to Microsoft Remote Desktop on 127.0.0.1 and it will connect to the remote instance!
|
76
|
+
|
77
|
+
Finally, you may wish to terminate the jumpbox tunnel early. This can be done as such: `vpcjump --instance-id i-abc123 kill`.
|
78
|
+
|
79
|
+
## How it works
|
80
|
+
|
81
|
+
`vpcjump` uses AWS SSM to remotely execute shell commands on your jumpbox. You can see the precise SSM and SSH commands it executes on your behalf by passing the `--verbose` flag during execution. It does the following:
|
82
|
+
|
83
|
+
* Use SSM to execute `ngrok tcp 22` with your provided auth token. This creates a tunnel over HTTPS between the instance and ngrok's tunnelling service.
|
84
|
+
* Use SSM to query ngrok's local API: `curl -s http://localhost:4040/api/tunnels`. This returns the ngrok hostname and port that are forwarded to port 22 on your jump box.
|
85
|
+
* Execute `ssh -p <ngrok port> <ssh user>@<ngrok host>` to log into your jumpbox through the ngrok tunnel.
|
86
|
+
* Use SSM to execute `killall ngrok` on the remote instance when you explicitly terminate the tunnel. If you don't do this, the SSM agent process on the remote instance will terminate the ngrok tunnel after a predefined period.
|
87
|
+
|
data/Rakefile
ADDED
data/exe/vpcjump
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'uri'
|
3
|
+
require 'json'
|
4
|
+
require 'clamp'
|
5
|
+
require 'aws-sdk'
|
6
|
+
require 'logger'
|
7
|
+
|
8
|
+
module VpcJump
|
9
|
+
class CLI < Clamp::Command
|
10
|
+
option '--instance-id', 'INSTANCE ID', 'EC2 instance id of jump box (e.g. i-abc123)'
|
11
|
+
option '--name', 'INSTANCE NAME', 'EC2 instance name of jump box'
|
12
|
+
option '--ngrok-token', 'NGROK TOKEN', 'ngrok auth token'
|
13
|
+
option '--ngrok-region', 'NGROK REGION', 'ngrok region', default: 'us'
|
14
|
+
option ['-v', '--verbose'], :flag, 'Output AWS API calls'
|
15
|
+
|
16
|
+
subcommand 'kill', 'Terminate ngrok tunnel' do
|
17
|
+
def execute
|
18
|
+
Aws.config[:logger] = Logger.new($stdout) if verbose?
|
19
|
+
|
20
|
+
id = instance_id
|
21
|
+
ssm_exec id, 'killall ngrok'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
subcommand 'ssh', 'SSH into the jumpbox' do
|
26
|
+
option '--ssh-user', 'SSH USER', 'SSH user', default: 'ec2-user'
|
27
|
+
parameter '[SSHPARAMS] ...', 'Arguments to pass to SSH'
|
28
|
+
|
29
|
+
def default_sshparams_list
|
30
|
+
[]
|
31
|
+
end
|
32
|
+
|
33
|
+
def execute
|
34
|
+
Aws.config[:logger] = Logger.new($stdout) if verbose?
|
35
|
+
|
36
|
+
id = instance_id
|
37
|
+
|
38
|
+
ssm_exec id, "ngrok tcp --log stdout --region #{ngrok_region} --authtoken #{ngrok_token} 22"
|
39
|
+
sleep 20
|
40
|
+
|
41
|
+
tunnels = []
|
42
|
+
|
43
|
+
loop do
|
44
|
+
resp = ssm_exec id, 'curl -s http://localhost:4040/api/tunnels'
|
45
|
+
output = ssm_output resp.command_id
|
46
|
+
json = JSON.parse output
|
47
|
+
tunnels = json['tunnels']
|
48
|
+
break if tunnels.length > 0
|
49
|
+
end
|
50
|
+
|
51
|
+
url = tunnels[0]['public_url']
|
52
|
+
uri = URI.parse url
|
53
|
+
port = uri.port
|
54
|
+
host = uri.hostname
|
55
|
+
|
56
|
+
cmd = "ssh -p #{port} #{sshparams_list.join(' ')} #{ssh_user}@#{host}"
|
57
|
+
puts cmd if verbose?
|
58
|
+
exec cmd
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def ssm_exec(instance_id, command)
|
63
|
+
ssm = Aws::SSM::Client.new
|
64
|
+
|
65
|
+
resp = ssm.send_command(
|
66
|
+
instance_ids: [instance_id],
|
67
|
+
document_name: 'AWS-RunShellScript',
|
68
|
+
parameters: {
|
69
|
+
commands: [command]
|
70
|
+
}
|
71
|
+
)
|
72
|
+
|
73
|
+
resp.command
|
74
|
+
end
|
75
|
+
|
76
|
+
def ssm_output(command_id)
|
77
|
+
ssm = Aws::SSM::Client.new
|
78
|
+
|
79
|
+
loop do
|
80
|
+
sleep 1
|
81
|
+
response = ssm.list_command_invocations command_id: command_id, details: true
|
82
|
+
invocation = response.command_invocations.first
|
83
|
+
|
84
|
+
if ['Pending', 'InProgress'].include?(invocation.status)
|
85
|
+
next
|
86
|
+
end
|
87
|
+
|
88
|
+
escaped = invocation.command_plugins[0].output
|
89
|
+
return escaped.gsub('"', '"')
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
VpcJump::CLI.run
|
data/lib/vpcjump.rb
ADDED
data/vpcjump.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'vpcjump/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'vpcjump'
|
8
|
+
spec.version = Vpcjump::VERSION
|
9
|
+
spec.authors = ['Aidan Steele']
|
10
|
+
spec.email = ['aidan.steele@glassechidna.com.au']
|
11
|
+
spec.homepage = 'https://github.com/aidansteele/vpcjump'
|
12
|
+
|
13
|
+
spec.summary = %q{Helper tool for connecting to jumpboxes in AWS.}
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
16
|
+
f.match(%r{^(test|spec|features)/})
|
17
|
+
end
|
18
|
+
spec.bindir = 'exe'
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ['lib']
|
21
|
+
|
22
|
+
spec.add_development_dependency 'bundler', '~> 1.13'
|
23
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
24
|
+
spec.add_development_dependency 'pry-rescue'
|
25
|
+
spec.add_development_dependency 'pry-stack_explorer'
|
26
|
+
|
27
|
+
spec.add_dependency 'clamp'
|
28
|
+
spec.add_dependency 'aws-sdk', '~> 2'
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vpcjump
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Aidan Steele
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-11-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.13'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.13'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry-rescue
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry-stack_explorer
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: clamp
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: aws-sdk
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '2'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '2'
|
97
|
+
description:
|
98
|
+
email:
|
99
|
+
- aidan.steele@glassechidna.com.au
|
100
|
+
executables:
|
101
|
+
- vpcjump
|
102
|
+
extensions: []
|
103
|
+
extra_rdoc_files: []
|
104
|
+
files:
|
105
|
+
- ".gitignore"
|
106
|
+
- Gemfile
|
107
|
+
- README.md
|
108
|
+
- Rakefile
|
109
|
+
- exe/vpcjump
|
110
|
+
- lib/vpcjump.rb
|
111
|
+
- lib/vpcjump/version.rb
|
112
|
+
- vpcjump.gemspec
|
113
|
+
homepage: https://github.com/aidansteele/vpcjump
|
114
|
+
licenses: []
|
115
|
+
metadata: {}
|
116
|
+
post_install_message:
|
117
|
+
rdoc_options: []
|
118
|
+
require_paths:
|
119
|
+
- lib
|
120
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - ">="
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '0'
|
130
|
+
requirements: []
|
131
|
+
rubyforge_project:
|
132
|
+
rubygems_version: 2.4.5.1
|
133
|
+
signing_key:
|
134
|
+
specification_version: 4
|
135
|
+
summary: Helper tool for connecting to jumpboxes in AWS.
|
136
|
+
test_files: []
|