views:

464

answers:

1

Hello,

I am trying to run a script in several machines I have at work, to gather some information about them, such as which OS they're running, what services run on them, some configurations, etc. I have a machine on which I log before ssh-ing to any of the other machines, because of the public key setup it has. From there, I can ssh into all of the other machines without being asked for my password.

What I want to do is to automate logging onto all of these machines from that one, but the script is running on my local machine. So I just learned about ruby-ssh-gateway and am trying that, but I can't seem to get pubkey authentication to work.

I do something like this:

gateway = Net::SSH::Gateway.new('gatewaymachine', 'username', :password => 'password')
all_machines.each do |machine|
  gateway.ssh(machine, 'username') do |ssh|
    uname = ssh.exec!('uname -a')
    puts "machine: #{machine}; OS: #{uname}"
  end
end

But I get a Net::SSH::AuthenticationFailed exception.

If, instead, I provide the password, like so:

gateway.ssh(machine, 'username', :password => 'password')

it does work, but that's not viable, since passwords are not the same across machines.

Does anyone know how I can make this work?

Thanks.

A: 

Are the machines you are talking to behind a NAT firewall? If not, you don't need ruby-ssh-gateway.

Have you created a public key on the origin box, for the user which runs the program, and given that key to the target user on each target box?

$ ssh-keygen -t dsa    # Only do this once
$ ssh-copy-id -i ~/.ssh/id_dsa.pub user@machine
(enter the password)

and to make sure the key is working:

$ ssh user@machine      # should not ask for a password

Once you've done that, it's as simple as using system or backtick to shell out to ssh:

system('ssh machine "ls -l"')
Wayne Conrad
That's exactly the problem:Suppose I have several boxes: Origin, Gateway and many Targets.I do have the private/public key setup from Gateway to all the Targets. I do not have that (and can't, for the moment) setup for Origin->Targets.That's why I supposed I should use net-ssh-gateway, so I could run the code on Origin and connect to Targets THROUGH Gateway. Not sure this is possible, though.
malvim
I don't see how a gateway would obviate the need to exchange keys.Can you at least give origin's public key to gateway? Then you could do something as simple and cheesy as: $ ssh gateway "ssh target 'ls -l' "
Wayne Conrad
Yeah, I think I was failing to see exactly how a gateway would work in this case. I supposed I could issue commands via net-ssh that would be seen by my Target machines as coming from Gateway, thus eliminating the need for me to give credentials to each Target, since the public key setup is done for Gateway->Targets. I already had a version with "ssh target1 'ls -l'". Only problem is that, in this case, I don't get pretty exceptions from net-ssh, I get linux output telling me what went wrong, and I have to parse that. :/
malvim
Since the gateway's key is already on all of the targets, you're just one more key away from being there: origin->gateway. As far as a pretty stack trace: command = "ssh gateway..."; system(command); raise "Failed: #{command}" if $? != 0
Wayne Conrad
Yeah, I'll use either one of these approaches. Thanks for your help!
malvim