ssh_tunnels 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +32 -30
- data/README.md +56 -3
- data/bin/ssh_tunnels +32 -11
- data/doc/demo.png +0 -0
- data/lib/ssh_tunnels/tunnel.rb +6 -6
- data/lib/ssh_tunnels/ui.rb +5 -1
- data/lib/ssh_tunnels/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e4fe888d25ffab2361eb1978eab7e3c1a64e986388860c82a3aba981603afc1
|
4
|
+
data.tar.gz: a352882082070c6abd2faecbf0ca2b3e771cd88bd51107ee2d0d539853142561
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3899497544ac7e01a40605dcef63d9d3ddd0721eb36a0f1b4892f64769f39b185ee5aa70982123040c24e479366e830a04be416cf2edee0c2fb15a176bf121b9
|
7
|
+
data.tar.gz: 572f38e2af5076cec0604164ff59278296dec1ba7ce2e0e6d4635acc2ae122a3701f6fa86b86fb23590ed2d795858f5272e41835cc082f7386ce285ce9469197
|
data/Gemfile.lock
CHANGED
@@ -1,42 +1,44 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
ssh_tunnels (0.
|
4
|
+
ssh_tunnels (0.2.0)
|
5
5
|
curses (~> 1.3)
|
6
6
|
net-ssh-gateway (~> 2.0)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
ast (2.4.
|
12
|
-
concurrent-ruby (1.
|
13
|
-
curses (1.
|
14
|
-
diff-lcs (1.
|
15
|
-
i18n (1.
|
11
|
+
ast (2.4.2)
|
12
|
+
concurrent-ruby (1.2.3)
|
13
|
+
curses (1.4.4)
|
14
|
+
diff-lcs (1.5.1)
|
15
|
+
i18n (1.14.4)
|
16
16
|
concurrent-ruby (~> 1.0)
|
17
|
-
net-ssh (
|
17
|
+
net-ssh (7.2.3)
|
18
18
|
net-ssh-gateway (2.0.0)
|
19
19
|
net-ssh (>= 4.0.0)
|
20
|
-
paint (2.
|
21
|
-
parallel (1.
|
22
|
-
parser (
|
20
|
+
paint (2.3.0)
|
21
|
+
parallel (1.24.0)
|
22
|
+
parser (3.3.0.5)
|
23
23
|
ast (~> 2.4.1)
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
rspec-
|
31
|
-
|
32
|
-
rspec-
|
33
|
-
rspec-
|
24
|
+
racc
|
25
|
+
racc (1.7.3)
|
26
|
+
rainbow (3.1.1)
|
27
|
+
regexp_parser (2.9.0)
|
28
|
+
rexml (3.2.6)
|
29
|
+
rspec (3.13.0)
|
30
|
+
rspec-core (~> 3.13.0)
|
31
|
+
rspec-expectations (~> 3.13.0)
|
32
|
+
rspec-mocks (~> 3.13.0)
|
33
|
+
rspec-core (3.13.0)
|
34
|
+
rspec-support (~> 3.13.0)
|
35
|
+
rspec-expectations (3.13.0)
|
34
36
|
diff-lcs (>= 1.2.0, < 2.0)
|
35
|
-
rspec-support (~> 3.
|
36
|
-
rspec-mocks (3.
|
37
|
+
rspec-support (~> 3.13.0)
|
38
|
+
rspec-mocks (3.13.0)
|
37
39
|
diff-lcs (>= 1.2.0, < 2.0)
|
38
|
-
rspec-support (~> 3.
|
39
|
-
rspec-support (3.
|
40
|
+
rspec-support (~> 3.13.0)
|
41
|
+
rspec-support (3.13.1)
|
40
42
|
rubocop (0.86.0)
|
41
43
|
parallel (~> 1.10)
|
42
44
|
parser (>= 2.7.0.1)
|
@@ -46,13 +48,13 @@ GEM
|
|
46
48
|
rubocop-ast (>= 0.0.3, < 1.0)
|
47
49
|
ruby-progressbar (~> 1.7)
|
48
50
|
unicode-display_width (>= 1.4.0, < 2.0)
|
49
|
-
rubocop-ast (0.0
|
50
|
-
parser (>= 2.7.
|
51
|
-
ruby-progressbar (1.
|
52
|
-
strong_versions (0.4.
|
53
|
-
i18n (>= 0.5
|
51
|
+
rubocop-ast (0.8.0)
|
52
|
+
parser (>= 2.7.1.5)
|
53
|
+
ruby-progressbar (1.13.0)
|
54
|
+
strong_versions (0.4.5)
|
55
|
+
i18n (>= 0.5)
|
54
56
|
paint (~> 2.0)
|
55
|
-
unicode-display_width (1.
|
57
|
+
unicode-display_width (1.8.0)
|
56
58
|
|
57
59
|
PLATFORMS
|
58
60
|
ruby
|
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# SshTunnels
|
2
2
|
|
3
|
-
Interactive _SSH_ tunnel management.
|
3
|
+
Interactive _SSH_ tunnel management. Console UI powered by [ncurses](https://invisible-island.net/ncurses/).
|
4
|
+
|
5
|
+

|
4
6
|
|
5
7
|
## Installation
|
6
8
|
|
@@ -14,14 +16,64 @@ gem install ssh_tunnels
|
|
14
16
|
ssh_tunnels -c config.yml
|
15
17
|
```
|
16
18
|
|
19
|
+
Alternatively, default to using `~/.ssh_tunnels.yml` for configuration:
|
20
|
+
|
21
|
+
```bash
|
22
|
+
ssh_tunnels
|
23
|
+
```
|
24
|
+
|
17
25
|
## Configuration
|
18
26
|
|
27
|
+
### Gateways
|
28
|
+
|
29
|
+
There are two ways to configure an SSH gateway. Both can be used together, but at least one must be defined:
|
30
|
+
|
31
|
+
1. Define a `default_gateway` section in your configuration file.
|
32
|
+
1. Define a `gateways` section in your conifguration file.
|
33
|
+
|
34
|
+
The `default_gateway` is a map containing these keys:
|
35
|
+
|
36
|
+
* `host`: hostname or IP address of gateway (required).
|
37
|
+
* `port`: SSH port on gateway (default: `22`).
|
38
|
+
* `user`: Username on gateway to connect with (default: `$USER`).
|
39
|
+
|
40
|
+
The `gateways` section is also a map, but each key represents a named gateway, and each gateway is configured using the same parameters as `default_gateway`.
|
41
|
+
|
42
|
+
Each named gateway can be referred to in the `gateway` field for each tunnel.
|
43
|
+
|
19
44
|
```yaml
|
20
45
|
# config.yml
|
21
46
|
|
22
|
-
|
47
|
+
default_gateway:
|
23
48
|
host: gateway.example.com
|
24
|
-
|
49
|
+
|
50
|
+
gateways:
|
51
|
+
aws:
|
52
|
+
host: 111.111.111.111
|
53
|
+
user: ubuntu
|
54
|
+
azure:
|
55
|
+
host: 222.222.222.222
|
56
|
+
user: william
|
57
|
+
```
|
58
|
+
|
59
|
+
### Tunnels
|
60
|
+
|
61
|
+
The `tunnels` section is a map where each key represents a named tunnel. Each tunnel can be configured using the following parameters:
|
62
|
+
|
63
|
+
* `host`: The remote host to connect to from the gateway.
|
64
|
+
* `remote`: The remote port to use for forwarding.
|
65
|
+
* `local`: The local port to bind to (defaults to the `remote` port).
|
66
|
+
|
67
|
+
```yaml
|
68
|
+
# config.yml
|
69
|
+
|
70
|
+
default_gateway:
|
71
|
+
host: gateway.example.com
|
72
|
+
|
73
|
+
gateways:
|
74
|
+
aws:
|
75
|
+
host: 111.111.111.111
|
76
|
+
user: ubuntu
|
25
77
|
|
26
78
|
tunnels:
|
27
79
|
my_host:
|
@@ -29,6 +81,7 @@ tunnels:
|
|
29
81
|
host: my.host.example.com
|
30
82
|
remote: 4567
|
31
83
|
other_host:
|
84
|
+
gateway: aws
|
32
85
|
local: 1111
|
33
86
|
host: other.host.example.com
|
34
87
|
remote: 5555
|
data/bin/ssh_tunnels
CHANGED
@@ -20,24 +20,40 @@ OptionParser.new do |opts|
|
|
20
20
|
end
|
21
21
|
end.parse!
|
22
22
|
|
23
|
-
|
24
|
-
warn('Must provide configuration path. See --help')
|
25
|
-
exit 1
|
26
|
-
end
|
23
|
+
config_path = options.fetch(:config_path, File.expand_path('~/.ssh_tunnels.yml'))
|
27
24
|
|
28
|
-
unless File.exist?(
|
29
|
-
warn("Unable to locate configuration file: #{
|
25
|
+
unless File.exist?(config_path)
|
26
|
+
warn("Unable to locate configuration file: #{config_path}")
|
30
27
|
exit 1
|
31
28
|
end
|
32
29
|
|
33
|
-
config = YAML.safe_load(File.read(
|
30
|
+
config = YAML.safe_load(File.read(config_path))
|
34
31
|
|
35
32
|
begin
|
36
|
-
|
33
|
+
default_gateway = config.fetch('default_gateway', nil)
|
34
|
+
if !config.key?('tunnels')
|
35
|
+
warn('Configuration file must provide `tunnels` section. Exiting.')
|
36
|
+
exit 1
|
37
|
+
end
|
38
|
+
|
39
|
+
gateways = config.fetch('gateways', {})
|
40
|
+
|
37
41
|
tunnels = config.fetch('tunnels')
|
38
|
-
|
39
|
-
|
40
|
-
|
42
|
+
error = false
|
43
|
+
tunnels.each do |key, tunnel|
|
44
|
+
if tunnel.key?('gateway') && !gateways.key?(tunnel.fetch('gateway'))
|
45
|
+
error = true
|
46
|
+
warn("Tunnel `#{key}` references unknown gateway `#{tunnel.fetch('gateway')}`")
|
47
|
+
elsif !tunnel.key?('gateway') && default_gateway.nil?
|
48
|
+
error = true
|
49
|
+
warn("Tunnel `#{key}` must provide `gateway` key or define a top-level `default_gateway` configuration.")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
if error
|
54
|
+
warn("Configuration errors detected. Exiting.")
|
55
|
+
exit 1
|
56
|
+
end
|
41
57
|
end
|
42
58
|
|
43
59
|
user = ENV.fetch('USER')
|
@@ -47,6 +63,11 @@ puts
|
|
47
63
|
|
48
64
|
begin
|
49
65
|
tunnels = tunnels.map do |name, tunnel_config|
|
66
|
+
gateway = if tunnel_config.key?('gateway')
|
67
|
+
gateways.fetch(tunnel_config.fetch('gateway'))
|
68
|
+
else
|
69
|
+
default_gateway
|
70
|
+
end
|
50
71
|
SshTunnels::Tunnel.new(name, user, tunnel_config, gateway, passphrase)
|
51
72
|
end
|
52
73
|
ui = SshTunnels::UI.new(tunnels)
|
data/doc/demo.png
ADDED
Binary file
|
data/lib/ssh_tunnels/tunnel.rb
CHANGED
@@ -27,11 +27,11 @@ module SshTunnels
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def open
|
30
|
-
@connection = Net::SSH::Gateway.new(@gateway.fetch('host'), @user, options)
|
30
|
+
@connection = Net::SSH::Gateway.new(@gateway.fetch('host'), @gateway.fetch('user', @user), options)
|
31
31
|
@connection.open(remote_host, remote_port, local_port)
|
32
|
-
rescue
|
33
|
-
@error = e.to_s
|
32
|
+
rescue StandardError => e
|
34
33
|
shutdown
|
34
|
+
raise
|
35
35
|
end
|
36
36
|
|
37
37
|
def active?
|
@@ -41,7 +41,7 @@ module SshTunnels
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def shutdown
|
44
|
-
@connection
|
44
|
+
@connection&.shutdown!
|
45
45
|
end
|
46
46
|
|
47
47
|
private
|
@@ -55,14 +55,14 @@ module SshTunnels
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def local_port
|
58
|
-
@config.fetch('local_port')
|
58
|
+
@config.fetch('local_port', remote_port)
|
59
59
|
end
|
60
60
|
|
61
61
|
def options
|
62
62
|
{
|
63
63
|
keepalive: true,
|
64
64
|
keepalive_interval: 5,
|
65
|
-
port: @gateway.fetch('port'),
|
65
|
+
port: @gateway.fetch('port', 22),
|
66
66
|
passphrase: @passphrase
|
67
67
|
}
|
68
68
|
end
|
data/lib/ssh_tunnels/ui.rb
CHANGED
data/lib/ssh_tunnels/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ssh_tunnels
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bob Farrell
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-04-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: curses
|
@@ -100,6 +100,7 @@ files:
|
|
100
100
|
- bin/console
|
101
101
|
- bin/setup
|
102
102
|
- bin/ssh_tunnels
|
103
|
+
- doc/demo.png
|
103
104
|
- lib/ssh_tunnels.rb
|
104
105
|
- lib/ssh_tunnels/tunnel.rb
|
105
106
|
- lib/ssh_tunnels/ui.rb
|