One way of doing this is to:
Create a text file(*) containing the hostnames and the plaintext root passwords. Use whatever field separator you like - tabs are good.
Ideally, you'd use a program like makepasswd
or pwgen
to generate passwords of sufficient length and complexity. IMO, 16 characters are the absolute minimum to consider using these days, and the longer the better.
e.g. if you have a list of the hostnames (one per line) in hosts.txt
, using something like the following:
#!/bin/bash
rm -f passwords.txt
while read -r host ; do
printf "%s\t%s\n" "$host" "$(pwgen -r \''`$' -y -c -n 32 1)" >> passwords.txt
done < hosts.txt
(this uses -r
to prevent single-quotes, backticks, and $ from being used in the password, because dealing with them in the single-quoted-string-inside-double-quotes ssh
command shown below would be a PITA).
Example run:
$ ./generate-passwords.sh
$ cat passwords.txt
host1 >?Mg^un=-Ipd8ZkY^TUC,_Gf/PAs%=9t
host2 XS4?oZ@[+U\,(XeYOBcp{E^Q;!]2]ex<
host3 SfupD}=a\J;}TJqqX.r}Kj;ab>Z|\=S2
You're going to need this list because otherwise you'll have no way of what the passwords are on the remote machines.
ssh
into each host and use chpasswd
to set the password. To avoid having the password appear in plain text in the remote machine's process list, pre-encrypt the passwords on your local machine with openssl passwd
and use chpasswd
's -e
option (this is only "safe" if you're the only user of your machine....and for quite limited definitions of the word "safe"). In this example, I'm using the -6
option for SHA-512
hashing.
#!/bin/bash
while IFS=$'\t' read -r host pass; do
enc=$(printf "%s" "$pass" | openssl passwd -6 stdin)
ssh "$host" "echo 'root:$enc' | chpasswd -e"
done < passwords.txt
This is really simple and primitive. There's no error checking. Or logging. But it does show the basic idea of how to use existing tools like pwgen
, openssl
, and chpasswd
to automate password changes.
I used to use scripts similar to these every semester at a university where I worked to generate passwords for new students in particular courses where shell access to specific machines (which were isolated from the main network) was required. The list was printed and cut into strips, and each user was given their password on showing their ID....this was far from perfect, but much better than having a default "password" that everyone knew.
Obviously, most of the time you'll be logging in to the remote machines with an authorised ssh key and not using a password at all...but root passwords are still useful for logins at the console (or with a BMC or other remote-management facilities) in case of emergencies.
(*) Because this passwords.txt
file is plain text, you need to be very careful about permissions and who has access to it, but that's mostly outside of the scope of this Q&A.
I suggest chmod 600
and encrypting the file with gpg - only decrypt it when you need to use it. I'd also suggest keeping the encrypted version in git
or some other revision control system so that you don't lose your history of old passwords to try if the password update failed on some particular hosts for some reason (e.g. it was offline at the time)
Or use pass to combine both gpg
and git
.