Managing service passwords with Puppet
I'm quite pleased with my solution to this. It's a shell script called by generate() function from puppet manifest. Password for each host is generated and stored in simple file as needed.
#!/bin/bash
# /etc/puppet/helpers/bacula/getpwd
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <pwd_name>"
exit 1
fi
if [ ! -x /usr/bin/pwgen ]; then
echo "missing pwgen!" >&2
exit 1
fi
workdir="/etc/puppet/helpers/bacula/"
workfile="$workdir/passwd"
[ ! -r $workfile ] && exit 2
get_name="$1"
# get password from storage
pwd=$(awk -F: -v name="$get_name" '
BEGIN { r = "NOTFOUND" }
name == $1 { r = $2 }
END { printf "%s", r }
' "$workfile")
if [ "$pwd" = "NOTFOUND" ]; then
# generate new password & store it
len=$((60 + $RANDOM % 9 ))
pwd=$(/usr/bin/pwgen -s $len 1)
echo "${get_name}:${pwd}" >> $workfile
fi
# echo password (without new line)
echo -n "$pwd"
Install pwgen or another password generation tool, modify workdir variable for your system settings, check password lengths. In template file call it:
Password = <%= scope.function_generate("/etc/puppet/helpers/bacula/getpwd", bacula_dirname) %>
Puppet variable bacula_dirname should be based on hostname or set from extlookup() e.g.:
$bacula_dirname = "${hostname}-dir"
$secret = "super special complicated long secure random string"
$password = sha1("${fqdn}${secret}")
notify {$password:}
Import $secret
from another file (perhaps that one puppet class that you don't keep in version control) and there you have it. Magic password generation.
Passwords can be changed globally by changing $secret
or individually in each declaration by using something other than $fqdn
.