remotus 0.4.0 → 0.5.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/.github/workflows/main.yml +5 -4
- data/.rubocop.yml +1 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +3 -1
- data/Gemfile.lock +25 -20
- data/README.md +9 -0
- data/docker/Dockerfile +16 -0
- data/docker/entrypoint.sh +3 -0
- data/docker/ssh_integration_script.sh +8 -0
- data/docker/ssh_integration_spec.rb +84 -0
- data/docker-compose.yml +10 -0
- data/lib/remotus/host_pool.rb +7 -0
- data/lib/remotus/result.rb +1 -1
- data/lib/remotus/ssh_connection.rb +97 -17
- data/lib/remotus/version.rb +1 -1
- data/remotus.gemspec +1 -0
- metadata +23 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b375e9a93879a30b113991e9b653e602f30d970743925527af92a964298d7a27
|
|
4
|
+
data.tar.gz: 97bab3f384551a63e665d173e9b90330f03d3e8b56e6e89a9c216b18e37c2a66
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6b3ded8d0ceb3c4b36736e875ca9ed80a85d77d388d1fb26f5a9659350622230c4f17efaee017e7765ddc081cd0ba52e767af960514a54c4061f667b38f1933c
|
|
7
|
+
data.tar.gz: 53aaf5d724c91a5639ce5f7928c6049b5912c21a523f2d1e5697191fb2511611e384fa5ce14fe92a53affaa8e707e42f5a5539ce83c93a16549bc1ac0fb3e5e5
|
data/.github/workflows/main.yml
CHANGED
|
@@ -6,21 +6,22 @@ jobs:
|
|
|
6
6
|
build:
|
|
7
7
|
runs-on: ubuntu-latest
|
|
8
8
|
steps:
|
|
9
|
-
- uses: actions/checkout@
|
|
9
|
+
- uses: actions/checkout@v3
|
|
10
10
|
- name: Set up Ruby
|
|
11
11
|
uses: ruby/setup-ruby@v1
|
|
12
12
|
with:
|
|
13
|
-
ruby-version:
|
|
13
|
+
ruby-version: 3.0.4
|
|
14
14
|
- name: Run unit tests and code linting
|
|
15
15
|
run: |
|
|
16
|
-
gem install bundler -v 2.2.
|
|
16
|
+
gem install bundler -v 2.2.33
|
|
17
17
|
bundle install
|
|
18
18
|
bundle exec rake
|
|
19
|
+
bundle exec rspec docker
|
|
19
20
|
bundle exec yard
|
|
20
21
|
|
|
21
22
|
- name: Deploy documentation
|
|
22
23
|
if: github.ref == 'refs/heads/main'
|
|
23
|
-
uses: crazy-max/ghaction-github-pages@
|
|
24
|
+
uses: crazy-max/ghaction-github-pages@v3.0.0
|
|
24
25
|
with:
|
|
25
26
|
target_branch: gh-pages
|
|
26
27
|
build_dir: doc
|
data/.rubocop.yml
CHANGED
data/.ruby-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.0.4
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
remotus (0.
|
|
4
|
+
remotus (0.5.0)
|
|
5
5
|
connection_pool (~> 2.2)
|
|
6
6
|
net-scp (~> 3.0)
|
|
7
7
|
net-ssh (~> 6.1)
|
|
8
|
+
net-ssh-gateway (~> 2.0)
|
|
8
9
|
winrm (~> 2.3)
|
|
9
10
|
winrm-elevated (~> 1.2)
|
|
10
11
|
winrm-fs (~> 1.3)
|
|
@@ -14,9 +15,9 @@ GEM
|
|
|
14
15
|
specs:
|
|
15
16
|
ast (2.4.2)
|
|
16
17
|
builder (3.2.4)
|
|
17
|
-
connection_pool (2.
|
|
18
|
+
connection_pool (2.3.0)
|
|
18
19
|
diff-lcs (1.5.0)
|
|
19
|
-
erubi (1.
|
|
20
|
+
erubi (1.11.0)
|
|
20
21
|
ffi (1.15.5)
|
|
21
22
|
gssapi (1.3.1)
|
|
22
23
|
ffi (>= 1.0.1)
|
|
@@ -24,6 +25,7 @@ GEM
|
|
|
24
25
|
builder (>= 2.1.2)
|
|
25
26
|
rexml (~> 3.0)
|
|
26
27
|
httpclient (2.8.3)
|
|
28
|
+
json (2.6.2)
|
|
27
29
|
little-plugger (1.1.4)
|
|
28
30
|
logging (2.3.1)
|
|
29
31
|
little-plugger (~> 1.1)
|
|
@@ -32,13 +34,15 @@ GEM
|
|
|
32
34
|
net-scp (3.0.0)
|
|
33
35
|
net-ssh (>= 2.6.5, < 7.0.0)
|
|
34
36
|
net-ssh (6.1.0)
|
|
37
|
+
net-ssh-gateway (2.0.0)
|
|
38
|
+
net-ssh (>= 4.0.0)
|
|
35
39
|
nori (2.6.0)
|
|
36
|
-
parallel (1.
|
|
37
|
-
parser (3.1.
|
|
40
|
+
parallel (1.22.1)
|
|
41
|
+
parser (3.1.2.1)
|
|
38
42
|
ast (~> 2.4.1)
|
|
39
43
|
rainbow (3.1.1)
|
|
40
44
|
rake (13.0.6)
|
|
41
|
-
regexp_parser (2.
|
|
45
|
+
regexp_parser (2.5.0)
|
|
42
46
|
rexml (3.2.5)
|
|
43
47
|
rspec (3.11.0)
|
|
44
48
|
rspec-core (~> 3.11.0)
|
|
@@ -46,32 +50,33 @@ GEM
|
|
|
46
50
|
rspec-mocks (~> 3.11.0)
|
|
47
51
|
rspec-core (3.11.0)
|
|
48
52
|
rspec-support (~> 3.11.0)
|
|
49
|
-
rspec-expectations (3.11.
|
|
53
|
+
rspec-expectations (3.11.1)
|
|
50
54
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
51
55
|
rspec-support (~> 3.11.0)
|
|
52
|
-
rspec-mocks (3.11.
|
|
56
|
+
rspec-mocks (3.11.1)
|
|
53
57
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
54
58
|
rspec-support (~> 3.11.0)
|
|
55
|
-
rspec-support (3.11.
|
|
56
|
-
rubocop (1.
|
|
59
|
+
rspec-support (3.11.1)
|
|
60
|
+
rubocop (1.36.0)
|
|
61
|
+
json (~> 2.3)
|
|
57
62
|
parallel (~> 1.10)
|
|
58
|
-
parser (>= 3.1.
|
|
63
|
+
parser (>= 3.1.2.1)
|
|
59
64
|
rainbow (>= 2.2.2, < 4.0)
|
|
60
65
|
regexp_parser (>= 1.8, < 3.0)
|
|
61
|
-
rexml
|
|
62
|
-
rubocop-ast (>= 1.
|
|
66
|
+
rexml (>= 3.2.5, < 4.0)
|
|
67
|
+
rubocop-ast (>= 1.20.1, < 2.0)
|
|
63
68
|
ruby-progressbar (~> 1.7)
|
|
64
69
|
unicode-display_width (>= 1.4.0, < 3.0)
|
|
65
|
-
rubocop-ast (1.
|
|
66
|
-
parser (>= 3.
|
|
70
|
+
rubocop-ast (1.21.0)
|
|
71
|
+
parser (>= 3.1.1.0)
|
|
67
72
|
rubocop-rake (0.6.0)
|
|
68
73
|
rubocop (~> 1.0)
|
|
69
|
-
rubocop-rspec (2.
|
|
70
|
-
rubocop (~> 1.
|
|
74
|
+
rubocop-rspec (2.13.1)
|
|
75
|
+
rubocop (~> 1.33)
|
|
71
76
|
ruby-progressbar (1.11.0)
|
|
72
77
|
rubyntlm (0.6.3)
|
|
73
78
|
rubyzip (2.3.2)
|
|
74
|
-
unicode-display_width (2.
|
|
79
|
+
unicode-display_width (2.3.0)
|
|
75
80
|
webrick (1.7.0)
|
|
76
81
|
winrm (2.3.6)
|
|
77
82
|
builder (>= 2.1.2)
|
|
@@ -91,7 +96,7 @@ GEM
|
|
|
91
96
|
logging (>= 1.6.1, < 3.0)
|
|
92
97
|
rubyzip (~> 2.0)
|
|
93
98
|
winrm (~> 2.0)
|
|
94
|
-
yard (0.9.
|
|
99
|
+
yard (0.9.28)
|
|
95
100
|
webrick (~> 1.7.0)
|
|
96
101
|
|
|
97
102
|
PLATFORMS
|
|
@@ -108,4 +113,4 @@ DEPENDENCIES
|
|
|
108
113
|
yard (~> 0.9)
|
|
109
114
|
|
|
110
115
|
BUNDLED WITH
|
|
111
|
-
2.2.
|
|
116
|
+
2.2.33
|
data/README.md
CHANGED
|
@@ -30,6 +30,15 @@ connection = Remotus.connect("remotehost.local", proto: :ssh, port: 2222)
|
|
|
30
30
|
# Initialize a new connection pool to remotehost.local with a defined protocol and port and arbitrary metadata
|
|
31
31
|
connection = Remotus.connect("remotehost.local", proto: :ssh, port: 2222, company: "Test Corp", location: "Oslo")
|
|
32
32
|
|
|
33
|
+
# Initialize a new connection pool to remotehost.local via a gateway host named gateway.local
|
|
34
|
+
connection = Remotus.connect("remotehost.local", gateway_host: "gateway.local")
|
|
35
|
+
|
|
36
|
+
# Initialize a new connection pool to remotehost.local via a gateway host named gateway.local with a defined protocol and port
|
|
37
|
+
connection = Remotus.connect("remotehost.local", proto: :ssh, port: 2222, gateway_host: "gateway.local", gateway_port: 2222)
|
|
38
|
+
|
|
39
|
+
# Initialize a new connection pool to remotehost.local via a gateway host named gateway.local with arbitrary metadata
|
|
40
|
+
connection = Remotus.connect("remotehost.local", company: "Test Corp", gateway_host: "gateway.local", gateway_metadata: { company: "Other Corp" })
|
|
41
|
+
|
|
33
42
|
# Create a credential for the new connection pool
|
|
34
43
|
connection.credential = Remotus::Auth::Credential.new("username", "password")
|
|
35
44
|
|
data/docker/Dockerfile
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
FROM alpine:latest
|
|
2
|
+
|
|
3
|
+
COPY entrypoint.sh /
|
|
4
|
+
|
|
5
|
+
RUN apk add --update --no-cache openssh && \
|
|
6
|
+
sed -i '/GatewayPorts.*/d' /etc/ssh/sshd_config && \
|
|
7
|
+
echo 'GatewayPorts yes' >> /etc/ssh/sshd_config && \
|
|
8
|
+
sed -i '/AllowTcpForwarding.*/d' /etc/ssh/sshd_config && \
|
|
9
|
+
echo 'AllowTcpForwarding yes' >> /etc/ssh/sshd_config && \
|
|
10
|
+
echo 'PasswordAuthentication yes' >> /etc/ssh/sshd_config && \
|
|
11
|
+
adduser -h /home/testuser -s /bin/sh -D testuser && \
|
|
12
|
+
echo 'testuser:testuser' | chpasswd
|
|
13
|
+
|
|
14
|
+
ENTRYPOINT ["/entrypoint.sh"]
|
|
15
|
+
|
|
16
|
+
EXPOSE 22
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Assumes docker-compose is available
|
|
4
|
+
|
|
5
|
+
RSpec.describe "Remotus::SshConnection Integration Tests" do
|
|
6
|
+
before(:all) do
|
|
7
|
+
# docker-compose startup
|
|
8
|
+
`docker-compose -f "docker-compose.yml" up -d --build`
|
|
9
|
+
|
|
10
|
+
# Set up Remotus credentials based on Dockerfile
|
|
11
|
+
Remotus::Auth.cache["localhost"] = Remotus::Auth::Credential.new("testuser", "testuser")
|
|
12
|
+
Remotus::Auth.cache["target"] = Remotus::Auth::Credential.new("testuser", "testuser")
|
|
13
|
+
|
|
14
|
+
# Allow time for sshd to start up
|
|
15
|
+
sleep 1
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
after(:all) do
|
|
19
|
+
# docker-compose cleanup
|
|
20
|
+
`docker-compose -f "docker-compose.yml" down -v`
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
let(:test_script) { ::File.join(__dir__, "ssh_integration_script.sh") }
|
|
24
|
+
let(:test_script_dest) { ::File.join("/home/testuser", ::File.basename(test_script)) }
|
|
25
|
+
|
|
26
|
+
context "when a gateway and inaccessible target host exist" do
|
|
27
|
+
let(:gateway_hostname) { `docker ps | grep remotus_gateway`.split.first }
|
|
28
|
+
let(:target_hostname) { `docker ps | grep remotus_target`.split.first }
|
|
29
|
+
let(:gateway_connection) { Remotus.connect("localhost", proto: :ssh, port: 2222) }
|
|
30
|
+
let(:target_connection) { Remotus.connect("target", proto: :ssh, port: 22, gateway_host: "localhost", gateway_port: 2222) }
|
|
31
|
+
|
|
32
|
+
it "Connects to the gateway host successfully" do
|
|
33
|
+
expect(gateway_connection.run("hostname").stdout.chomp).to eq(gateway_hostname)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "Can run a script against the gateway host successfully" do
|
|
37
|
+
result = gateway_connection.run_script(test_script, test_script_dest)
|
|
38
|
+
expect(result.stdout).to eq("success")
|
|
39
|
+
expect(result.success?).to eq(true)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "Can upload a file to the gateway host" do
|
|
43
|
+
result = gateway_connection.upload(test_script, "/home/testuser/upload_test")
|
|
44
|
+
expect(result).to eq("/home/testuser/upload_test")
|
|
45
|
+
expect(gateway_connection.file_exist?("/home/testuser/upload_test")).to eq(true)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "Can download a file from the gateway host" do
|
|
49
|
+
gateway_connection.run('echo -n "test" > /home/testuser/download_test')
|
|
50
|
+
result = gateway_connection.download("/home/testuser/download_test")
|
|
51
|
+
expect(result).to eq("test")
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "Can check if a file exists on the gateway host" do
|
|
55
|
+
expect(gateway_connection.file_exist?("/home/testuser")).to eq(true)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "Connects to the target host successfully" do
|
|
59
|
+
expect(target_connection.run("hostname").stdout.chomp).to eq(target_hostname)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "Can run a script against the target host successfully" do
|
|
63
|
+
result = target_connection.run_script(test_script, test_script_dest)
|
|
64
|
+
expect(result.stdout).to eq("success")
|
|
65
|
+
expect(result.success?).to eq(true)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "Can upload a file to the target host" do
|
|
69
|
+
result = target_connection.upload(test_script, "/home/testuser/upload_test")
|
|
70
|
+
expect(result).to eq("/home/testuser/upload_test")
|
|
71
|
+
expect(target_connection.file_exist?("/home/testuser/upload_test")).to eq(true)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "Can download a file from the target host" do
|
|
75
|
+
target_connection.run('echo -n "test" > /home/testuser/download_test')
|
|
76
|
+
result = target_connection.download("/home/testuser/download_test")
|
|
77
|
+
expect(result).to eq("test")
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "Can check if a file exists on the target host" do
|
|
81
|
+
expect(target_connection.file_exist?("/home/testuser")).to eq(true)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
data/docker-compose.yml
ADDED
data/lib/remotus/host_pool.rb
CHANGED
|
@@ -42,6 +42,13 @@ module Remotus
|
|
|
42
42
|
# @param [Hash] metadata metadata for this connection. Useful for providing additional information to various authentication stores
|
|
43
43
|
# should be specified using snake_case symbol keys. If keys are not snake_case, they will be converted.
|
|
44
44
|
#
|
|
45
|
+
# To configure a connection gateway, the following metadata entries can be provided to the host pool:
|
|
46
|
+
# :gateway_host
|
|
47
|
+
# :gateway_port
|
|
48
|
+
# :gateway_metadata
|
|
49
|
+
#
|
|
50
|
+
# These function similarly to the host, port, and host_pool metadata fields.
|
|
51
|
+
#
|
|
45
52
|
def initialize(host, size: DEFAULT_POOL_SIZE, timeout: DEFAULT_EXPIRATION_SECONDS, port: nil, proto: nil, **metadata)
|
|
46
53
|
Remotus.logger.debug { "Creating host pool for #{host}" }
|
|
47
54
|
|
data/lib/remotus/result.rb
CHANGED
|
@@ -65,7 +65,7 @@ module Remotus
|
|
|
65
65
|
def error!(accepted_exit_codes = [0])
|
|
66
66
|
return unless error?(accepted_exit_codes)
|
|
67
67
|
|
|
68
|
-
raise Remotus::ResultError, "Error encountered executing #{@command}! Exit code #{@exit_code} was returned "\
|
|
68
|
+
raise Remotus::ResultError, "Error encountered executing #{@command}! Exit code #{@exit_code} was returned " \
|
|
69
69
|
"while a value in #{accepted_exit_codes} was expected.\n#{output}"
|
|
70
70
|
end
|
|
71
71
|
|
|
@@ -6,6 +6,7 @@ require "remotus/result"
|
|
|
6
6
|
require "remotus/auth"
|
|
7
7
|
require "net/scp"
|
|
8
8
|
require "net/ssh"
|
|
9
|
+
require "net/ssh/gateway"
|
|
9
10
|
|
|
10
11
|
module Remotus
|
|
11
12
|
# Class representing an SSH connection to a host
|
|
@@ -21,6 +22,9 @@ module Remotus
|
|
|
21
22
|
# Number of default retries
|
|
22
23
|
DEFAULT_RETRIES = 2
|
|
23
24
|
|
|
25
|
+
# Base options for new SSH connections
|
|
26
|
+
BASE_CONNECT_OPTIONS = { non_interactive: true, keepalive: true, keepalive_interval: KEEPALIVE_INTERVAL }.freeze
|
|
27
|
+
|
|
24
28
|
# @return [Integer] Remote port
|
|
25
29
|
attr_reader :port
|
|
26
30
|
|
|
@@ -33,12 +37,50 @@ module Remotus
|
|
|
33
37
|
# Delegate metadata methods to associated host pool
|
|
34
38
|
def_delegators :@host_pool, :[], :[]=
|
|
35
39
|
|
|
40
|
+
# Internal gateway connection class to allow for the host and metadata to be pulled for the gateway
|
|
41
|
+
# by authentication credentials
|
|
42
|
+
class GatewayConnection
|
|
43
|
+
extend Forwardable
|
|
44
|
+
|
|
45
|
+
# @return [String] host gateway hostname
|
|
46
|
+
attr_reader :host
|
|
47
|
+
|
|
48
|
+
# @return [Integer] Remote port
|
|
49
|
+
attr_reader :port
|
|
50
|
+
|
|
51
|
+
# @return [Net::SSH::Gateway] connection gateway connection
|
|
52
|
+
attr_accessor :connection
|
|
53
|
+
|
|
54
|
+
# Delegate metadata methods to associated hash
|
|
55
|
+
def_delegators :@metadata, :[], :[]=
|
|
56
|
+
|
|
57
|
+
#
|
|
58
|
+
# Creates a GatewayConnection
|
|
59
|
+
#
|
|
60
|
+
# @param [String] host hostname
|
|
61
|
+
# @param [Integer] port remote port
|
|
62
|
+
# @param [Hash] metadata associated metadata for this gateway
|
|
63
|
+
#
|
|
64
|
+
def initialize(host, port = REMOTE_PORT, metadata = {})
|
|
65
|
+
@host = host
|
|
66
|
+
@port = port
|
|
67
|
+
@metadata = metadata
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
36
71
|
#
|
|
37
72
|
# Creates an SshConnection
|
|
38
73
|
#
|
|
39
74
|
# @param [String] host hostname
|
|
40
75
|
# @param [Integer] port remote port
|
|
41
76
|
# @param [Remotus::HostPool] host_pool associated host pool
|
|
77
|
+
# To configure the gateway, the following metadata
|
|
78
|
+
# entries can be provided to the host pool:
|
|
79
|
+
# :gateway_host
|
|
80
|
+
# :gateway_port
|
|
81
|
+
# :gateway_metadata
|
|
82
|
+
#
|
|
83
|
+
# These function similarly to the host, port, and host_pool metadata fields.
|
|
42
84
|
#
|
|
43
85
|
def initialize(host, port = REMOTE_PORT, host_pool: nil)
|
|
44
86
|
Remotus.logger.debug { "Creating SshConnection #{object_id} for #{host}" }
|
|
@@ -77,23 +119,32 @@ module Remotus
|
|
|
77
119
|
def connection
|
|
78
120
|
return @connection unless restart_connection?
|
|
79
121
|
|
|
80
|
-
|
|
122
|
+
target_cred = Remotus::Auth.credential(self)
|
|
123
|
+
|
|
124
|
+
Remotus.logger.debug { "Initializing SSH connection to #{target_cred.user}@#{@host}:#{@port}" }
|
|
81
125
|
|
|
82
|
-
|
|
126
|
+
target_options = BASE_CONNECT_OPTIONS.dup
|
|
127
|
+
target_options[:password] = target_cred.password if target_cred.password
|
|
128
|
+
target_options[:keys] = [target_cred.private_key] if target_cred.private_key
|
|
129
|
+
target_options[:key_data] = [target_cred.private_key_data] if target_cred.private_key_data
|
|
130
|
+
target_options[:port] = @port || REMOTE_PORT
|
|
83
131
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
132
|
+
if via_gateway?
|
|
133
|
+
@gateway = GatewayConnection.new(@host_pool[:gateway_host], @host_pool[:gateway_port], @host_pool[:gateway_metadata])
|
|
134
|
+
gateway_cred = Remotus::Auth.credential(@gateway)
|
|
135
|
+
gateway_options = BASE_CONNECT_OPTIONS.dup
|
|
136
|
+
gateway_options[:port] = @gateway.port || REMOTE_PORT
|
|
137
|
+
gateway_options[:password] = gateway_cred.password if gateway_cred.password
|
|
138
|
+
gateway_options[:keys] = [gateway_cred.private_key] if gateway_cred.private_key
|
|
139
|
+
gateway_options[:key_data] = [gateway_cred.private_key_data] if gateway_cred.private_key_data
|
|
87
140
|
|
|
88
|
-
|
|
89
|
-
options[:keys] = [private_key_path] if private_key_path
|
|
90
|
-
options[:key_data] = [private_key_data] if private_key_data
|
|
141
|
+
Remotus.logger.debug { "Initializing SSH gateway connection to #{gateway_cred.user}@#{@gateway.host}:#{gateway_options[:port]}" }
|
|
91
142
|
|
|
92
|
-
|
|
93
|
-
@host,
|
|
94
|
-
|
|
95
|
-
**
|
|
96
|
-
|
|
143
|
+
@gateway.connection = Net::SSH::Gateway.new(@gateway.host, gateway_cred.user, **gateway_options)
|
|
144
|
+
@gateway.connection.ssh(@host, target_cred.user, **target_options)
|
|
145
|
+
else
|
|
146
|
+
@connection = Net::SSH.start(@host, target_cred.user, **target_options)
|
|
147
|
+
end
|
|
97
148
|
end
|
|
98
149
|
|
|
99
150
|
#
|
|
@@ -392,10 +443,30 @@ module Remotus
|
|
|
392
443
|
return true unless @connection
|
|
393
444
|
return true if @connection.closed?
|
|
394
445
|
return true if @host != @connection.host
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
return true if
|
|
446
|
+
|
|
447
|
+
target_cred = Remotus::Auth.credential(self)
|
|
448
|
+
|
|
449
|
+
return true if target_cred.user != @connection.options[:user]
|
|
450
|
+
return true if target_cred.password != @connection.options[:password]
|
|
451
|
+
return true if Array(target_cred.private_key) != Array(@connection.options[:keys])
|
|
452
|
+
return true if Array(target_cred.private_key_data) != Array(@connection.options[:key_data])
|
|
453
|
+
|
|
454
|
+
# Perform gateway checks
|
|
455
|
+
if via_gateway?
|
|
456
|
+
return true unless @gateway&.connection&.active?
|
|
457
|
+
|
|
458
|
+
gateway_session = @gateway.connection.instance_variable_get(:@session)
|
|
459
|
+
|
|
460
|
+
return true if gateway_session.closed?
|
|
461
|
+
return true if @host_pool[:gateway_host] != gateway_session.host
|
|
462
|
+
|
|
463
|
+
gateway_cred = Remotus::Auth.credential(@gateway)
|
|
464
|
+
|
|
465
|
+
return true if gateway_cred.user != @connection.options[:user]
|
|
466
|
+
return true if gateway_cred.password != @connection.options[:password]
|
|
467
|
+
return true if Array(gateway_cred.private_key) != Array(@connection.options[:keys])
|
|
468
|
+
return true if Array(gateway_cred.private_key_data) != Array(@connection.options[:key_data])
|
|
469
|
+
end
|
|
399
470
|
|
|
400
471
|
false
|
|
401
472
|
end
|
|
@@ -469,5 +540,14 @@ module Remotus
|
|
|
469
540
|
Remotus.logger.debug { "Generated permission commands #{cmds}" }
|
|
470
541
|
cmds
|
|
471
542
|
end
|
|
543
|
+
|
|
544
|
+
#
|
|
545
|
+
# Whether connecting via an SSH gateway
|
|
546
|
+
#
|
|
547
|
+
# @return [Boolean] true if using a gateway, false otherwise
|
|
548
|
+
#
|
|
549
|
+
def via_gateway?
|
|
550
|
+
host_pool && host_pool[:gateway_host]
|
|
551
|
+
end
|
|
472
552
|
end
|
|
473
553
|
end
|
data/lib/remotus/version.rb
CHANGED
data/remotus.gemspec
CHANGED
|
@@ -32,6 +32,7 @@ Gem::Specification.new do |spec|
|
|
|
32
32
|
spec.add_dependency "connection_pool", "~> 2.2"
|
|
33
33
|
spec.add_dependency "net-scp", "~> 3.0"
|
|
34
34
|
spec.add_dependency "net-ssh", "~> 6.1"
|
|
35
|
+
spec.add_dependency "net-ssh-gateway", "~> 2.0"
|
|
35
36
|
spec.add_dependency "winrm", "~> 2.3"
|
|
36
37
|
spec.add_dependency "winrm-elevated", "~> 1.2"
|
|
37
38
|
spec.add_dependency "winrm-fs", "~> 1.3"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: remotus
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Matthew Newell
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2022-
|
|
11
|
+
date: 2022-09-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: connection_pool
|
|
@@ -52,6 +52,20 @@ dependencies:
|
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: '6.1'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: net-ssh-gateway
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '2.0'
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '2.0'
|
|
55
69
|
- !ruby/object:Gem::Dependency
|
|
56
70
|
name: winrm
|
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -189,6 +203,7 @@ files:
|
|
|
189
203
|
- ".gitignore"
|
|
190
204
|
- ".rspec"
|
|
191
205
|
- ".rubocop.yml"
|
|
206
|
+
- ".ruby-version"
|
|
192
207
|
- CHANGELOG.md
|
|
193
208
|
- Gemfile
|
|
194
209
|
- Gemfile.lock
|
|
@@ -197,6 +212,11 @@ files:
|
|
|
197
212
|
- Rakefile
|
|
198
213
|
- bin/console
|
|
199
214
|
- bin/setup
|
|
215
|
+
- docker-compose.yml
|
|
216
|
+
- docker/Dockerfile
|
|
217
|
+
- docker/entrypoint.sh
|
|
218
|
+
- docker/ssh_integration_script.sh
|
|
219
|
+
- docker/ssh_integration_spec.rb
|
|
200
220
|
- lib/remotus.rb
|
|
201
221
|
- lib/remotus/auth.rb
|
|
202
222
|
- lib/remotus/auth/credential.rb
|
|
@@ -235,7 +255,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
235
255
|
- !ruby/object:Gem::Version
|
|
236
256
|
version: '0'
|
|
237
257
|
requirements: []
|
|
238
|
-
rubygems_version: 3.
|
|
258
|
+
rubygems_version: 3.2.33
|
|
239
259
|
signing_key:
|
|
240
260
|
specification_version: 4
|
|
241
261
|
summary: Ruby gem for connecting to remote systems seamlessly via WinRM or SSH.
|