Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I need to automate a way to distribute files to many servers. The problem of course is I need to use a secure protocol (SSH or SCP) and the username / password on each server is different.

The scenario is we have a master server a, with user a_prod and we need to send updated scripts / configs, etc. to servers b, c, d, ... and on these servers the usernames are say b_dev, c_test, d_prod with each having unique passwords.

The usernames need to be unique across environments for a few reasons, dealing with DB2 and corporate security.

Shared keys will not work in this scenario, so I need to pass the usernames and passwords via a script. It is an AIX environment, and I do not have the ability to install expect.

Any ideas?

Shared keys are mentioned in multiple responses below: I have tried a few ways to do this, I think the main issue is the remote user ID's do not exist on any other host, so I can not do an ssh-keygen for them on the host I want to ssh from to do a shared key implementation with the main user (a_prod) having multiple identities depending upon the target host (b_dev, c_test_d_prod). The private key for these users needs to be generated on host a for the remote users, and then their public keys need to be copied to the target hosts.

share|improve this question
1  
One problem with this is that your script will have to contain all of the username/password combinations and therefore be a corporate security risk in itself? –  Stefan Thyberg Jul 23 '09 at 12:33
    
The passwords are combinations of two different parts, that would be scripted for half, and in a secure location viewable only to this user (and of course root). –  Kevin K Jul 23 '09 at 15:11
    
You need to make sure that you are calling ssh with the user name it should use ssh user@server or ssh -l user server –  Brad Gilbert Jul 23 '09 at 20:12
    
I don't understand why a single private key isn't going to work. You can configure each of the accounts to accept ssh login using that same private key. –  reinierpost Jul 24 '09 at 13:00
    
@reinierpost: The key has the username built into it - cat a keyfile, they are unique per user. –  Kevin K Jul 24 '09 at 13:37

9 Answers 9

"Corporate S(tupidity)" :-)

SSH / SCP generally lives with the realm of UNIX philosophy I think. It is very rare that the designers of Unix applications intentionally make it so the administrator can't easily do something stupid. There will be generally be a warning like: "You probably don't want to do this because ... but, if you really want to, fine!".

In the case of passing a password to ssh in a script, they intentionally make this difficult, because it just such a bad idea.

At this point, I wouldn't even bother with SSH. You really need to talk with the corporate security people and come up with a real solution for the scenario. If they don't want to use keys, ask them what you should do. If that doesn't work, tell your managers what they want can't be done due to corporate security restrictions. If the managers do insist that you do this, get it in writing, or it is your ass on the line

share|improve this answer
    
I could use keys, but I believe they are user specific and live in an individual user's ~/.ssh2 sub dir, and the authorization file in that same dir. To have a different user use those files is not working. There is no way I am going to set this up for all users on the host, that would be a major mistake. –  Kevin K Jul 23 '09 at 18:03
3  
You appear to be confused about ssh keys. The files in ~/.ssh are only read by the user they belong to. The user connecting has the private key, usually in ~/.ssh/id_{d,r}sa.pub but that could be anywhere and specified to ssh via -i, and the user it connects as has the corresponding public key in ~/.ssh/authorized_keys –  niXar Jul 24 '09 at 8:11

Insert standard disclaimer about corporate policy and why it's bad to put user/pass in scripts here.

But we all work in the real world where sometimes it doesn't make sense. Soo.. There are many tools that will let you do this. Shell does not have a built-in way to get this working. My weapon of choice for very quick and dirty scripts of this nature is Expect. It is rediculously easy to get running.

#!/usr/bin/expect

set nodename "hostname"
set username "user"
set password "pass"
set prompt "your prompt on the remote system"

eval spawn ssh -x $user@$nodeaddy

set timeout 15

expect "password:" { send "$password\r" }
expect "$prompt" { send "script\r" }
exit 0

Obviously this may or may not work for you, but you can see from the syntax just how simple it is to get working.

share|improve this answer
2  
"and I do not have the ability to install expect." –  Kyle Brandt Jul 23 '09 at 12:54

First a warning: be careful that you don't create a security issue in the name of expediency. Kevin and Kyle bring up good points. Storing a bunch of username/password combinations in a file (even an encrypted database) is probably a very bad idea and may violate corporate policy.

The solution to your problem may be a client side certificate. See the below articles for more information:

share|improve this answer
    
I have done this before where the user ID is the same across all of the hosts, can it also work for user a on host prod_a to ssh to user b on host dev_b? –  Kevin K Jul 23 '09 at 15:14
    
@KevinK: you can login as a different user to the remote host. It's option -l (or "ssh username@hostname"). –  robcast Jul 23 '09 at 15:24
    
@robcast: I got that, but the keygen is user specific, unless I set it up for the entire host (not a chance) the files need to reside in the user's ~/.ssh2 directory, and exist in their authorization file. Can I just copy these between users and have it still work? I am trying, and it does not seem to work properly. –  Kevin K Jul 23 '09 at 18:00

Assuming that a public private key pair is allowed by the corporate policy this is not that hard to achieve. To get a username different from the user running ssh (the script) use username@host. The harder part is to get the proper private keys working. Assuming that because of some kind of false sense of security each host must use a different key pair (otherwise it is simpler) you should create a configuration file that tells the client which pair to use for which host (you can also actually specify the username in the file).

For openssh the file would look like

host a_prod
    user usera
    IdentityFile ~/.ssh/keyfora_prod

host b_dev
    user userb
    IdentityFile ~/.ssh/keyforb_prod

etc.

Just remember that this setup is not actually more secure. If someone can get access to this user on this computer he can read all private keys (that can't have a password if things must be secure, or you must hack around with ssh_agent) as well as hardcoded passwords. As there is no reason for the private key files to live anywhere else but in the ssh dir of this user (when lost, one can easilly create a new key) having four files is not different from having one from a security perspective.

share|improve this answer
up vote 1 down vote accepted

OK - I finally got this working as follows:

  1. Do the ssh-keygen on all of the servers.
  2. Setup the authorization file for each user with their public key.
  3. Setup the identification file for each user with the private key
  4. Copy the private keys for the destination servers to the server you want to ssh from as unique files (b_dev_id_dsa_2048_a, c_test_id_dsa_a, ...)
  5. Call ssh as follows on host a: ssh -i b_dev_id_dsa_2048_a b_dev@b

and viola, it finally works.

Thanks you everyone for the help, and finally niXar for that final Homer Simpson DUH moment as doing this is exactly backwards to what you do if the user is the same across all of the hosts.

share|improve this answer

Without private keys or Expect or something like it, I don't see how you can do this automagically. Something's got to give.

You do have something to work with, do you? I supposed you don't have Perl around since you could then use Expect.pm? Python? Anything? Just plain old ugly ksh? Tell us more.

If you're not allowed to use a programming language, then you need to enter the pass by hand. In that case you can use:

scp myfile b_dev@b_prod:/path/to/dest

If batches are involved, consider using SFTP instead. You could then use lftp, and not have to type the password, here straight from the manpage:

lftp [-d] [-e cmd] [-p port] [-u user[,pass]] [site]

But if you can't get Expect I doubt you can use lftp. Can you?

/ Oh I hate proprietary Unix crap

share|improve this answer

It's not a good idea, but if you really need to do it sshpass can help you: http://sourceforge.net/projects/sshpass/

share|improve this answer

I had to do something similar, only backwards. We're pulling files off of a bunch of servers, and this is the way we did it.

awk '{FS="|"; printf("rsync %s:%s %s &\n", $1, $2, $3)}' config | sh

Create a file called config and in it put the lines you want to run. (please note: you need to insert a blank line to start with).

The way it's setup right now, you would put username@server.com|(folder on remote server)|(folder on local server) into config, and it will rsync the two. You will want to switch the rsync command in the awk command to do the opposite.

This would work well with ssh-key auth, which is what we use.

share|improve this answer

I would as well suggest creating SSH-Keys for the authentication and use a tool like unison or lsyncd (depending on your need) to keep files in sync.

If the key based authenitication is not an option, you can use "expect" (http://linux.die.net/man/1/expect) to script it. Expect checks for a defined outupt (lets say the question for the password) and related to that enters a defined string (in that example the password).

But again as suggested, i would prefer the ssh-key solution.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.