New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

have net-ssh request a pty #60

Closed
srenatus opened this Issue Jan 28, 2016 · 15 comments

Comments

Projects
None yet
8 participants
@srenatus
Copy link
Contributor

srenatus commented Jan 28, 2016

The issue we face is basically described here: net-ssh/net-ssh#103: when train tries to execute a command using sudo, and the target system's sudoers config contains requiretty, the call will fail with something like

$lib/train/extras/command_wrapper.rb:131:in `load': Sudo failed:  sudo: sorry, you must have a tty to run sudo (Train::UserError)

The way forward would be to request a pty, with example code here.

@chris-rock @arlimus What do you think about that?

@arlimus

This comment has been minimized.

Copy link
Contributor

arlimus commented Jan 28, 2016

Requesting a PTY is an incredibly tricky thing, as it eats up STDERR. There is a way to get around that with explicit pipes for each output... feel free to confirm.

We might offer an explicit mode for that, which then defaults to PTY for now. But making it the default has led to failures in our test suite in the past (SSH-connectivity tests which test commands; unless this is no longer true ofc ;) ).

@srenatus

This comment has been minimized.

Copy link
Contributor

srenatus commented Jan 28, 2016

Trying to approach this with #30.

@srenatus

This comment has been minimized.

Copy link
Contributor

srenatus commented Jan 28, 2016

A quick (and hopefully not-too-intrusive) workaround would be adding a sudoers config for the user used for logging into the machine, e.g. /etc/sudoers.d/chef:

chef ALL=(root) NOPASSWD: ALL
Defaults!ALL !requiretty
@srenatus

This comment has been minimized.

Copy link
Contributor

srenatus commented Jan 29, 2016

I've been looking into this a little more:

So if you request a PTY, the server will no longer separate stderr from stdout. This is true regardless of the fact if we use a forked ssh client or request the PTY using Net::SSH, so both variants need the same workaround.[1]

Just for this issue, I suggest we try using the workaround with the existing net-ssh, instead of implementing something to "fork and supervise that process, feeding it input and capturing its output". From my investigations, there's no real go-to solution out there. Mixlib-Shellout does not support feeding the command something on standard input, so we'd be limited to spawn one ssh process for every run_command(cmd), which is terrible. (And using expect et al. on a shell session is terrible, too.)

[1]: The obvious workaround being that when we run_command(cmd), we rewrite it to #{cmd} 2>#{unique_temp_name}, and send a second command that cat && rms that file.

@whiteadam

This comment has been minimized.

Copy link

whiteadam commented Apr 21, 2016

If it helps, having this same issue when running kitchen test on the aws cookbook using Amazon linux default-amazon-201509 and chef-12.9.38-1.el6

@padgyx

This comment has been minimized.

Copy link

padgyx commented May 4, 2016

Is this bug fixed yet? I got the same problem when I run kitchen test:

-----Exception-------
Class: Kitchen::ActionFailed Message: Failed to complete #verify action: [Sudo failed: Sudo requires a TTY. Please see the README on how to configure sudo to allow for non-interactive usage.]

I am using CentOS 7 on AWS. Meanwhile, what README file is this message talking about?

@grdnrio

This comment has been minimized.

Copy link

grdnrio commented Jun 9, 2016

I bootstrap nodes on AWS using knife and use the cis-el7-l1-hardening::enable_sudo_no_tty recipe in the run list to allow me to later add the nodes to Compliance. Here's the cookbook containing the recipe: https://supermarket.chef.io/cookbooks/cis-el7-l1-hardening

@chris-rock

This comment has been minimized.

Copy link
Member

chris-rock commented Jun 16, 2016

This is now fixed by #112 and is available in version 0.13+ If the problem still occurs, please reopen the ticket.

@chris-rock chris-rock closed this Jun 16, 2016

@marcparadise

This comment has been minimized.

Copy link
Contributor

marcparadise commented Jun 28, 2016

Unfortunately this did not resolve the issue specific to being unable to sudo in absence of a tty. With the latest verison from master, using train to ssh into a node with Default: requiretty set still results in the following:

`load': Sudo failed: Sudo requires a TTY. Please see the README on how to configure sudo to allow for non-interactive usage. (Train::UserError)

The change to supply keyboard-interactive to list of auth methods only affects the ssh protocol negotiation of supported auth methods. It doesn't subsequently change any attributes of the session itself after ssh authentication is completed.

@marcparadise marcparadise reopened this Jun 28, 2016

@chris-rock

This comment has been minimized.

Copy link
Member

chris-rock commented Jun 29, 2016

@marcparadise Would it be possible to provide a reproducible use case, so that we can follow that error?

@marcparadise

This comment has been minimized.

Copy link
Contributor

marcparadise commented Jun 29, 2016

Time allowing, I'll try to package something up that requires less typing - but I'm not sure I'll have a chance today. In case I'm not able, here are the steps that should do it:

  1. uncomment/added 'Default: requiretty' to the /etc/sudoers of a linux vm (or even your dev system if you want to skip the vm setup), flavor shouldn't matter.
  2. verify that it's working as expected via direct ssh as: ssh vagrant@127.0.0.1 -t -i path-to-key -p port-no -C 'sudo ls /'
    • private key and port info can be obtained through vagrant ssh-config.
    • If defaulttty is set, this should give an error about tty required for sudo.
  3. Once that's confirmed, create a sudo-enabled train connection and use run_command:
t = Train.create('ssh', ... host, port, user, maybe-password, maybe-key... 
                  sudo: true, sudo_password: a-password)
t.connection.run_command("ls -l /") 
@chefsalim

This comment has been minimized.

Copy link

chefsalim commented Jun 30, 2016

@sr could we add a way to just force train to use a TTY - then we could use that flag when we create the connection?

@srenatus

This comment has been minimized.

Copy link
Contributor

srenatus commented Jul 1, 2016

Side note @chefsalim: @sr != me on GitHub. ;)

@srenatus

This comment has been minimized.

Copy link
Contributor

srenatus commented Jul 1, 2016

Reproducing the issue, this is running this test script:

require 'train'

t = Train.create('ssh', host: '127.0.0.1', port: '2200', user: 'vagrant', password: 'vagrant', sudo: true, pty: true);
puts t.connection.run_command("ls /")

against builder1, where I've enabled the Defaults: requiretty setting in /etc/sudoers

omnibus (BP-221/ignore-spurious-validation-keys)* (0)$ bundle exec ruby test.rb
D, [2016-07-01T12:41:46.537099 #19208] DEBUG -- : [SSH] vagrant@127.0.0.1<{:user_known_hosts_file=>"/dev/null", :paranoid=>false, :port=>"2200", :compression=>false, :compres
sion_level=>0, :keepalive=>true, :keepalive_interval=>60, :timeout=>15, :auth_methods=>["none", "password", "keyboard-interactive"], :keys_only=>nil, :keys=>nil, :password=>"
<hidden>", :forward_agent=>nil}> (/usr/bin/sw_vers)
D, [2016-07-01T12:41:46.537199 #19208] DEBUG -- : [SSH] opening connection to vagrant@127.0.0.1<{:user_known_hosts_file=>"/dev/null", :paranoid=>false, :port=>"2200", :compre
ssion=>false, :compression_level=>0, :keepalive=>true, :keepalive_interval=>60, :timeout=>15, :auth_methods=>["none", "password", "keyboard-interactive"], :keys_only=>nil, :k
eys=>nil, :password=>"<hidden>", :forward_agent=>nil}>
D, [2016-07-01T12:41:46.667378 #19208] DEBUG -- : [SSH] vagrant@127.0.0.1<{:user_known_hosts_file=>"/dev/null", :paranoid=>false, :port=>"2200", :compression=>false, :compres
sion_level=>0, :keepalive=>true, :keepalive_interval=>60, :timeout=>15, :auth_methods=>["none", "password", "keyboard-interactive"], :keys_only=>nil, :keys=>nil, :password=>"
<hidden>", :forward_agent=>nil, :user=>"vagrant"}> (uname -s)
D, [2016-07-01T12:41:46.676656 #19208] DEBUG -- : [SSH] vagrant@127.0.0.1<{:user_known_hosts_file=>"/dev/null", :paranoid=>false, :port=>"2200", :compression=>false, :compres
sion_level=>0, :keepalive=>true, :keepalive_interval=>60, :timeout=>15, :auth_methods=>["none", "password", "keyboard-interactive"], :keys_only=>nil, :keys=>nil, :password=>"
<hidden>", :forward_agent=>nil, :user=>"vagrant"}> (uname -r)
D, [2016-07-01T12:41:46.686189 #19208] DEBUG -- : [SSH] vagrant@127.0.0.1<{:user_known_hosts_file=>"/dev/null", :paranoid=>false, :port=>"2200", :compression=>false, :compres
sion_level=>0, :keepalive=>true, :keepalive_interval=>60, :timeout=>15, :auth_methods=>["none", "password", "keyboard-interactive"], :keys_only=>nil, :keys=>nil, :password=>"
<hidden>", :forward_agent=>nil, :user=>"vagrant"}> (test -f oracle-release && cat oracle-release)
D, [2016-07-01T12:41:46.695327 #19208] DEBUG -- : [SSH] vagrant@127.0.0.1<{:user_known_hosts_file=>"/dev/null", :paranoid=>false, :port=>"2200", :compression=>false, :compres
sion_level=>0, :keepalive=>true, :keepalive_interval=>60, :timeout=>15, :auth_methods=>["none", "password", "keyboard-interactive"], :keys_only=>nil, :keys=>nil, :password=>"
<hidden>", :forward_agent=>nil, :user=>"vagrant"}> (test -f /etc/enterprise-release && cat /etc/enterprise-release)
D, [2016-07-01T12:41:46.705075 #19208] DEBUG -- : [SSH] vagrant@127.0.0.1<{:user_known_hosts_file=>"/dev/null", :paranoid=>false, :port=>"2200", :compression=>false, :compres
sion_level=>0, :keepalive=>true, :keepalive_interval=>60, :timeout=>15, :auth_methods=>["none", "password", "keyboard-interactive"], :keys_only=>nil, :keys=>nil, :password=>"
<hidden>", :forward_agent=>nil, :user=>"vagrant"}> (test -f /etc/debian_version && cat /etc/debian_version)
D, [2016-07-01T12:41:46.714207 #19208] DEBUG -- : [SSH] vagrant@127.0.0.1<{:user_known_hosts_file=>"/dev/null", :paranoid=>false, :port=>"2200", :compression=>false, :compres
sion_level=>0, :keepalive=>true, :keepalive_interval=>60, :timeout=>15, :auth_methods=>["none", "password", "keyboard-interactive"], :keys_only=>nil, :keys=>nil, :password=>"
<hidden>", :forward_agent=>nil, :user=>"vagrant"}> (test -f /etc/parallels-release && cat /etc/parallels-release)
D, [2016-07-01T12:41:46.724162 #19208] DEBUG -- : [SSH] vagrant@127.0.0.1<{:user_known_hosts_file=>"/dev/null", :paranoid=>false, :port=>"2200", :compression=>false, :compres
sion_level=>0, :keepalive=>true, :keepalive_interval=>60, :timeout=>15, :auth_methods=>["none", "password", "keyboard-interactive"], :keys_only=>nil, :keys=>nil, :password=>"
<hidden>", :forward_agent=>nil, :user=>"vagrant"}> (test -f /etc/redhat-release && cat /etc/redhat-release)
D, [2016-07-01T12:41:46.733460 #19208] DEBUG -- : [SSH] vagrant@127.0.0.1<{:user_known_hosts_file=>"/dev/null", :paranoid=>false, :port=>"2200", :compression=>false, :compres
sion_level=>0, :keepalive=>true, :keepalive_interval=>60, :timeout=>15, :auth_methods=>["none", "password", "keyboard-interactive"], :keys_only=>nil, :keys=>nil, :password=>"
<hidden>", :forward_agent=>nil, :user=>"vagrant"}> (test -f /etc/os-release && cat /etc/os-release)
D, [2016-07-01T12:41:46.743713 #19208] DEBUG -- : [SSH] vagrant@127.0.0.1<{:user_known_hosts_file=>"/dev/null", :paranoid=>false, :port=>"2200", :compression=>false, :compres
sion_level=>0, :keepalive=>true, :keepalive_interval=>60, :timeout=>15, :auth_methods=>["none", "password", "keyboard-interactive"], :keys_only=>nil, :keys=>nil, :password=>"
<hidden>", :forward_agent=>nil, :user=>"vagrant"}> (sudo echo)
/Users/stephan/Src/chef/train/lib/train/extras/command_wrapper.rb:139:in `load': Sudo failed: Sudo requires a TTY. Please see the README on how to configure sudo to allow for
 non-interactive usage. (Train::UserError)
        from /Users/stephan/Src/chef/train/lib/train/transports/ssh_connection.rb:44:in `initialize'
        from /Users/stephan/Src/chef/train/lib/train/transports/ssh.rb:149:in `new'
        from /Users/stephan/Src/chef/train/lib/train/transports/ssh.rb:149:in `create_new_connection'
        from /Users/stephan/Src/chef/train/lib/train/transports/ssh.rb:73:in `connection'
        from test.rb:4:in `<main>'

running with the branch of #121:

$ bundle exec ruby test.rb
W, [2016-07-01T12:44:23.420787 #19317]  WARN -- : [SSH] PTY requested: stderr will be merged into stdout
D, [2016-07-01T12:44:23.424289 #19317] DEBUG -- : [SSH] vagrant@127.0.0.1<{:user_known_hosts_file=>"/dev/null", :paranoid=>false, :port=>"2200", :compression=>false, :compres
sion_level=>0, :keepalive=>true, :keepalive_interval=>60, :timeout=>15, :auth_methods=>["none", "password", "keyboard-interactive"], :keys_only=>nil, :keys=>nil, :password=>"
<hidden>", :forward_agent=>nil}> (/usr/bin/sw_vers)
D, [2016-07-01T12:44:23.424357 #19317] DEBUG -- : [SSH] opening connection to vagrant@127.0.0.1<{:user_known_hosts_file=>"/dev/null", :paranoid=>false, :port=>"2200", :compre
ssion=>false, :compression_level=>0, :keepalive=>true, :keepalive_interval=>60, :timeout=>15, :auth_methods=>["none", "password", "keyboard-interactive"], :keys_only=>nil, :k
eys=>nil, :password=>"<hidden>", :forward_agent=>nil}>
D, [2016-07-01T12:44:23.552807 #19317] DEBUG -- : [SSH] vagrant@127.0.0.1<{:user_known_hosts_file=>"/dev/null", :paranoid=>false, :port=>"2200", :compression=>false, :compres
sion_level=>0, :keepalive=>true, :keepalive_interval=>60, :timeout=>15, :auth_methods=>["none", "password", "keyboard-interactive"], :keys_only=>nil, :keys=>nil, :password=>"
<hidden>", :forward_agent=>nil, :user=>"vagrant"}> (uname -s)
D, [2016-07-01T12:44:23.563305 #19317] DEBUG -- : [SSH] vagrant@127.0.0.1<{:user_known_hosts_file=>"/dev/null", :paranoid=>false, :port=>"2200", :compression=>false, :compres
sion_level=>0, :keepalive=>true, :keepalive_interval=>60, :timeout=>15, :auth_methods=>["none", "password", "keyboard-interactive"], :keys_only=>nil, :keys=>nil, :password=>"
<hidden>", :forward_agent=>nil, :user=>"vagrant"}> (uname -r)
D, [2016-07-01T12:44:23.574042 #19317] DEBUG -- : [SSH] vagrant@127.0.0.1<{:user_known_hosts_file=>"/dev/null", :paranoid=>false, :port=>"2200", :compression=>false, :compres
sion_level=>0, :keepalive=>true, :keepalive_interval=>60, :timeout=>15, :auth_methods=>["none", "password", "keyboard-interactive"], :keys_only=>nil, :keys=>nil, :password=>"
<hidden>", :forward_agent=>nil, :user=>"vagrant"}> (test -f oracle-release && cat oracle-release)
D, [2016-07-01T12:44:23.582849 #19317] DEBUG -- : [SSH] vagrant@127.0.0.1<{:user_known_hosts_file=>"/dev/null", :paranoid=>false, :port=>"2200", :compression=>false, :compres
sion_level=>0, :keepalive=>true, :keepalive_interval=>60, :timeout=>15, :auth_methods=>["none", "password", "keyboard-interactive"], :keys_only=>nil, :keys=>nil, :password=>"
<hidden>", :forward_agent=>nil, :user=>"vagrant"}> (test -f /etc/enterprise-release && cat /etc/enterprise-release)
D, [2016-07-01T12:44:23.593597 #19317] DEBUG -- : [SSH] vagrant@127.0.0.1<{:user_known_hosts_file=>"/dev/null", :paranoid=>false, :port=>"2200", :compression=>false, :compres
sion_level=>0, :keepalive=>true, :keepalive_interval=>60, :timeout=>15, :auth_methods=>["none", "password", "keyboard-interactive"], :keys_only=>nil, :keys=>nil, :password=>"
<hidden>", :forward_agent=>nil, :user=>"vagrant"}> (test -f /etc/debian_version && cat /etc/debian_version)
D, [2016-07-01T12:44:23.603236 #19317] DEBUG -- : [SSH] vagrant@127.0.0.1<{:user_known_hosts_file=>"/dev/null", :paranoid=>false, :port=>"2200", :compression=>false, :compres
sion_level=>0, :keepalive=>true, :keepalive_interval=>60, :timeout=>15, :auth_methods=>["none", "password", "keyboard-interactive"], :keys_only=>nil, :keys=>nil, :password=>"
<hidden>", :forward_agent=>nil, :user=>"vagrant"}> (test -f /etc/parallels-release && cat /etc/parallels-release)
D, [2016-07-01T12:44:23.612180 #19317] DEBUG -- : [SSH] vagrant@127.0.0.1<{:user_known_hosts_file=>"/dev/null", :paranoid=>false, :port=>"2200", :compression=>false, :compres
sion_level=>0, :keepalive=>true, :keepalive_interval=>60, :timeout=>15, :auth_methods=>["none", "password", "keyboard-interactive"], :keys_only=>nil, :keys=>nil, :password=>"
<hidden>", :forward_agent=>nil, :user=>"vagrant"}> (test -f /etc/redhat-release && cat /etc/redhat-release)
D, [2016-07-01T12:44:23.623362 #19317] DEBUG -- : [SSH] vagrant@127.0.0.1<{:user_known_hosts_file=>"/dev/null", :paranoid=>false, :port=>"2200", :compression=>false, :compres
sion_level=>0, :keepalive=>true, :keepalive_interval=>60, :timeout=>15, :auth_methods=>["none", "password", "keyboard-interactive"], :keys_only=>nil, :keys=>nil, :password=>"
<hidden>", :forward_agent=>nil, :user=>"vagrant"}> (test -f /etc/os-release && cat /etc/os-release)
D, [2016-07-01T12:44:23.635252 #19317] DEBUG -- : [SSH] vagrant@127.0.0.1<{:user_known_hosts_file=>"/dev/null", :paranoid=>false, :port=>"2200", :compression=>false, :compres
sion_level=>0, :keepalive=>true, :keepalive_interval=>60, :timeout=>15, :auth_methods=>["none", "password", "keyboard-interactive"], :keys_only=>nil, :keys=>nil, :password=>"
<hidden>", :forward_agent=>nil, :user=>"vagrant"}> (sudo echo)
D, [2016-07-01T12:44:23.652958 #19317] DEBUG -- : [SSH] vagrant@127.0.0.1<{:user_known_hosts_file=>"/dev/null", :paranoid=>false, :port=>"2200", :compression=>false, :compres
sion_level=>0, :keepalive=>true, :keepalive_interval=>60, :timeout=>15, :auth_methods=>["none", "password", "keyboard-interactive"], :keys_only=>nil, :keys=>nil, :password=>"
<hidden>", :forward_agent=>nil, :user=>"vagrant"}> (ls /)
#<struct Train::Extras::CommandResult stdout="/etc/profile.d/lang.sh: line 19: warning: setlocale: LC_CTYPE: cannot change locale (UTF-8): No such file or directory\r\nbin
dev  home  lib64\tmnt  proc  run\t shared  sys  usr      var\r\nboot  etc  lib\t media\topt  root  sbin  srv\t tmp  vagrant\r\n", stderr="", exit_status=0>
@arlimus

This comment has been minimized.

Copy link
Contributor

arlimus commented Jul 1, 2016

Thank you @srenatus for the log!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment