summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklós Fazekas <mfazekas@szemafor.com>2020-03-16 18:33:55 +0100
committerGitHub <noreply@github.com>2020-03-16 18:33:55 +0100
commit7d241bb8d93e745d0ace459ef8854a7db3316ada (patch)
tree14ce5abdde9f7541fa09e1a14dd4cb505824d23f
parentfc91300d7ee6299ba2fe4039cc8085aec9edb7f3 (diff)
parentaea5223eea51c2b60e6373dc8175d49f7520f4e6 (diff)
downloadnet-ssh-7d241bb8d93e745d0ace459ef8854a7db3316ada.tar.gz
Merge pull request #745 from uzxmx/master
Add set_env option
-rw-r--r--.rubocop_todo.yml3
-rw-r--r--lib/net/ssh.rb5
-rw-r--r--lib/net/ssh/config.rb2
-rw-r--r--lib/net/ssh/connection/channel.rb12
-rw-r--r--test/configs/set_env2
-rw-r--r--test/integration/common.rb1
-rw-r--r--test/integration/playbook.yml6
-rw-r--r--test/integration/test_channel.rb40
-rw-r--r--test/integration/test_forward.rb12
-rw-r--r--test/start/test_options.rb7
-rw-r--r--test/test_config.rb8
11 files changed, 76 insertions, 22 deletions
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index bc4efd8..a1b7067 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -274,6 +274,8 @@ Metrics/ClassLength:
# Offense count: 38
Metrics/CyclomaticComplexity:
Max: 27
+ Exclude:
+ - 'lib/net/ssh/config.rb'
# Offense count: 211
# Configuration parameters: CountComments, ExcludedMethods.
@@ -299,6 +301,7 @@ Naming/AccessorMethodName:
Exclude:
- 'lib/net/ssh/authentication/methods/password.rb'
- 'lib/net/ssh/authentication/pageant.rb'
+ - 'lib/net/ssh/connection/channel.rb'
- 'lib/net/ssh/connection/session.rb'
- 'lib/net/ssh/transport/kex/abstract5656.rb'
- 'lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb'
diff --git a/lib/net/ssh.rb b/lib/net/ssh.rb
index 542c757..9df01f0 100644
--- a/lib/net/ssh.rb
+++ b/lib/net/ssh.rb
@@ -4,6 +4,7 @@ ENV['HOME'] ||= ENV['HOMEPATH'] ? "#{ENV['HOMEDRIVE']}#{ENV['HOMEPATH']}" : Dir.
require 'logger'
require 'etc'
+require 'shellwords'
require 'net/ssh/config'
require 'net/ssh/errors'
@@ -70,7 +71,7 @@ module Net
rekey_blocks_limit rekey_limit rekey_packet_limit timeout verbose
known_hosts global_known_hosts_file user_known_hosts_file host_key_alias
host_name user properties passphrase keys_only max_pkt_size
- max_win_size send_env use_agent number_of_password_prompts
+ max_win_size send_env set_env use_agent number_of_password_prompts
append_all_supported_algorithms non_interactive password_prompt
agent_socket_factory minimum_dh_bits verify_host_key
fingerprint_hash check_host_ip
@@ -175,6 +176,8 @@ module Net
# * :rekey_packet_limit => the max number of packets to process before rekeying
# * :send_env => an array of local environment variable names to export to the
# remote environment. Names may be given as String or Regexp.
+ # * :set_env => a hash of environment variable names and values to set to the
+ # remote environment. Override the ones if specified in +send_env+.
# * :timeout => how long to wait for the initial connection to be made
# * :user => the user name to log in as; this overrides the +user+
# parameter, and is primarily only useful when provided via an SSH
diff --git a/lib/net/ssh/config.rb b/lib/net/ssh/config.rb
index 5c81e61..a40262e 100644
--- a/lib/net/ssh/config.rb
+++ b/lib/net/ssh/config.rb
@@ -276,6 +276,8 @@ module Net
when :sendenv
multi_send_env = value.to_s.split(/\s+/)
hash[:send_env] = multi_send_env.map { |e| Regexp.new pattern2regex(e).source, false }
+ when :setenv
+ hash[:set_env] = Shellwords.split(value.to_s).map { |e| e.split '=', 2 }.to_h
when :numberofpasswordprompts
hash[:number_of_password_prompts] = value.to_i
when *TRANSLATE_CONFIG_KEY_RENAME_MAP.keys
diff --git a/lib/net/ssh/connection/channel.rb b/lib/net/ssh/connection/channel.rb
index a47d77d..7bfee72 100644
--- a/lib/net/ssh/connection/channel.rb
+++ b/lib/net/ssh/connection/channel.rb
@@ -2,8 +2,8 @@ require 'net/ssh/loggable'
require 'net/ssh/connection/constants'
require 'net/ssh/connection/term'
-module Net
- module SSH
+module Net
+ module SSH
module Connection
# The channel abstraction. Multiple "channels" can be multiplexed onto a
@@ -530,6 +530,7 @@ module Net
@remote_maximum_packet_size = max_packet
connection.forward.agent(self) if connection.options[:forward_agent] && type == "session"
forward_local_env(connection.options[:send_env]) if connection.options[:send_env]
+ set_remote_env(connection.options[:set_env]) if connection.options[:set_env]
@on_confirm_open.call(self) if @on_confirm_open
end
@@ -677,6 +678,13 @@ module Net
end
end
end
+
+ # Set a +Hash+ of environment variables in the remote process' environment.
+ #
+ # channel.set_remote_env foo: 'bar', baz: 'whale'
+ def set_remote_env(env)
+ env.each { |key, value| self.env(key, value) }
+ end
end
end
diff --git a/test/configs/set_env b/test/configs/set_env
new file mode 100644
index 0000000..35df6c0
--- /dev/null
+++ b/test/configs/set_env
@@ -0,0 +1,2 @@
+Host 1234
+ SetEnv foo="bar" baz=whale cat="black hole"
diff --git a/test/integration/common.rb b/test/integration/common.rb
index ef99b04..6295ada 100644
--- a/test/integration/common.rb
+++ b/test/integration/common.rb
@@ -94,6 +94,7 @@ module IntegrationTestHelpers
# @yield [pid, port]
def start_sshd_7_or_later(port = '2200', config: nil)
+ pid = nil
if config
with_lines_as_tempfile(config) do |path|
pid = spawn('sudo', '/opt/net-ssh-openssh/sbin/sshd', '-D', '-f', path, '-p', port)
diff --git a/test/integration/playbook.yml b/test/integration/playbook.yml
index e2268c6..dd9d078 100644
--- a/test/integration/playbook.yml
+++ b/test/integration/playbook.yml
@@ -41,14 +41,14 @@
- lineinfile: dest=/etc/sudoers.d/net_ssh_1 mode=0440 state=present create=yes
line='net_ssh_2 ALL=(ALL) NOPASSWD:ALL' regexp=net_ssh_2
- unarchive:
- src: https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-7.4p1.tar.gz
+ src: https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-7.9p1.tar.gz
dest: /tmp
remote_src: True
validate_certs: False
- - name: building and installing openssh 7.4 (used in forward test)
+ - name: building and installing openssh 7.9 (used in forward test)
command: sh -c "./configure --prefix=/opt/net-ssh-openssh && make && sudo make install"
args:
- chdir: /tmp/openssh-7.4p1/
+ chdir: /tmp/openssh-7.9p1/
- name: drop installed openssh etc/ in favor of symlink
file:
state: absent
diff --git a/test/integration/test_channel.rb b/test/integration/test_channel.rb
index 2b424b4..d07e0a1 100644
--- a/test/integration/test_channel.rb
+++ b/test/integration/test_channel.rb
@@ -51,11 +51,11 @@ class TestChannel < NetSSHTest
proxy = Net::SSH::Proxy::Command.new("/bin/nc localhost 22")
res = nil
Net::SSH.start(*ssh_start_params(proxy: proxy)) do |ssh|
- chanell_success_handler = lambda do
+ channel_success_handler = lambda do
sleep(0.1)
system("killall /bin/nc")
end
- channel = ssh_exec(ssh, "echo Begin ; sleep 100 ; echo End", chanell_success_handler) do |ch, _type, data|
+ channel = ssh_exec(ssh, "echo Begin ; sleep 100 ; echo End", channel_success_handler) do |ch, _type, data|
ch[:result] ||= ""
ch[:result] << data
end
@@ -72,11 +72,11 @@ class TestChannel < NetSSHTest
proxy = Net::SSH::Proxy::Command.new("/bin/nc localhost 22")
res = nil
Net::SSH.start(*ssh_start_params(proxy: proxy)) do |ssh|
- chanell_success_handler = lambda do
+ channel_success_handler = lambda do
sleep(0.1)
system("killall /bin/nc")
end
- channel = ssh_exec(ssh, "echo Hello!", chanell_success_handler) do |ch, _type, data|
+ channel = ssh_exec(ssh, "echo Hello!", channel_success_handler) do |ch, _type, data|
ch[:result] ||= ""
ch[:result] << data
end
@@ -104,4 +104,36 @@ class TestChannel < NetSSHTest
end
end
end
+
+ def test_channel_should_set_environment_variables_on_remote
+ setup_ssh_env do
+ start_sshd_7_or_later(config: 'AcceptEnv *') do |_pid, port|
+ Timeout.timeout(4) do
+ begin
+ # We have our own sshd, give it a chance to come up before
+ # listening.
+ proxy = Net::SSH::Proxy::Command.new("/bin/nc localhost #{port}")
+ res = nil
+ Net::SSH.start(*ssh_start_params(port: port, proxy: proxy, set_env: { foo: 'bar', baz: 'whale will' })) do |ssh|
+ channel_success_handler = lambda do
+ sleep(0.1)
+ system("killall /bin/nc")
+ end
+ channel = ssh_exec(ssh, "echo $foo; echo $baz", channel_success_handler) do |ch, _type, data|
+ ch[:result] ||= ""
+ ch[:result] << data
+ end
+ channel.wait
+ res = channel[:result]
+ assert_equal(res, "bar\nwhale will\n")
+ end
+ assert_equal(res, "bar\nwhale will\n")
+ rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Net::SSH::Proxy::ConnectError
+ sleep 0.25
+ retry
+ end
+ end
+ end
+ end
+ end
end
diff --git a/test/integration/test_forward.rb b/test/integration/test_forward.rb
index 9cd8e64..3ff76cd 100644
--- a/test/integration/test_forward.rb
+++ b/test/integration/test_forward.rb
@@ -24,18 +24,6 @@ require 'tempfile'
class ForwardTestBase < NetSSHTest
include IntegrationTestHelpers
- # @yield [pid, port]
- def start_sshd_7_or_later(port = '2200')
- pid = spawn('sudo', '/opt/net-ssh-openssh/sbin/sshd', '-D', '-p', port)
- yield pid, port
- ensure
- # Our pid is sudo, -9 (KILL) on sudo will not clean up its children
- # properly, so we just have to hope that -15 (TERM) will manage to bring
- # down sshd.
- system('sudo', 'kill', '-15', pid.to_s)
- Process.wait(pid)
- end
-
def localhost
'localhost'
end
diff --git a/test/start/test_options.rb b/test/start/test_options.rb
index 26c2a14..43a88a7 100644
--- a/test/start/test_options.rb
+++ b/test/start/test_options.rb
@@ -32,6 +32,13 @@ module NetSSH
end
end
+ def test_start_should_accept_set_env_option
+ assert_nothing_raised do
+ options = { set_env: { foo: 'bar', baz: 'whale will' } }
+ Net::SSH.start('localhost', 'testuser', options)
+ end
+ end
+
def test_start_should_accept_number_of_password_prompts_option
assert_nothing_raised do
options = { number_of_password_prompts: 2 }
diff --git a/test/test_config.rb b/test/test_config.rb
index eab6d7f..f71a952 100644
--- a/test/test_config.rb
+++ b/test/test_config.rb
@@ -138,6 +138,7 @@ class TestConfig < NetSSHTest
'pubkeyauthentication' => true,
'rekeylimit' => 1024,
'sendenv' => "LC_*",
+ 'setenv' => 'foo="bar" baz=whale cat="black hole"',
'numberofpasswordprompts' => '123',
'serveraliveinterval' => '2',
'serveralivecountmax' => '4',
@@ -162,6 +163,7 @@ class TestConfig < NetSSHTest
assert_equal 1024, net_ssh[:rekey_limit]
assert_equal "127.0.0.1", net_ssh[:bind_address]
assert_equal [/^LC_.*$/], net_ssh[:send_env]
+ assert_equal Hash['foo' => 'bar', 'baz' => 'whale', 'cat' => 'black hole'], net_ssh[:set_env]
assert_equal 123, net_ssh[:number_of_password_prompts]
assert_equal 4, net_ssh[:keepalive_maxcount]
assert_equal 2, net_ssh[:keepalive_interval]
@@ -285,6 +287,12 @@ class TestConfig < NetSSHTest
assert_equal [/^GIT_.*$/, /^LANG$/, /^LC_.*$/], net_ssh[:send_env]
end
+ def test_load_with_set_env
+ config = Net::SSH::Config.load(config(:set_env), '1234')
+ net_ssh = Net::SSH::Config.translate(config)
+ assert_equal Hash['foo' => 'bar', 'baz' => 'whale', 'cat' => 'black hole'], net_ssh[:set_env]
+ end
+
def test_load_with_remote_user
config = Net::SSH::Config.load(config(:proxy_remote_user), "behind-proxy")
net_ssh = Net::SSH::Config.translate(config)