File: //sbin/ifup-local
#!/bin/bash
# Script to set guest password, ssh key credentials
# CentOS/RHEL: /sbin/ifup-local
# Ubuntu/Debian: /etc/network/if-up.d/cloudstack-set-guest-credentials
# Set all possible dhcp leases files here:
DHCP_FILES="/var/lib/dhclient/*.lease /var/lib/dhclient/*.leases /var/lib/dhcp3/*.leases /var/lib/dhcp/*.leases /var/db/dhclient.leases.* /var/lib/NetworkManager/*.lease*"
# Set user to operate on here:
user=root
isValidIP() {
echo "$1" | grep -Eq '^(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])'
}
function get_sshkey() {
logger -t "cloudstack-sshkey" "Sending request to ssh key server at $SERVER_IP"
publickey=$(wget -q -t 3 -T 20 -O - http://$SERVER_IP/latest/public-keys 2>/dev/null)
local keycheck=0
until [ $? -ne 4 ]; do
[ "$keycheck" -eq "$maxcheck" ] && break
sleep 3
logger -t "cloudstack-sshkey" "wget exited with exit code $?, retrying"
publickey=$(wget -q -t 3 -T 20 -O - http://$SERVER_IP/latest/public-keys 2>/dev/null)
keycheck=$((keycheck+1))
done
if [ $? -eq 0 ]; then
len=${#publickey}
if [ "$len" -lt 60 ]; then
# An extremely small key is likely an empty key / no keys registered in Cloudstack
logger -t "cloudstack-sshkey" "No keys registered at $SERVER_IP"
return
fi
# Success
keys_received=1
return
else
logger -t "cloudstack-sshkey" "Failed to send request to ssh key server at $SERVER_IP"
fi
}
function set_sshkey() {
# Set ssh public key
homedir=$(grep ^$user /etc/passwd|awk -F ":" '{print $6}')
sshdir=$homedir/.ssh
authorized=$sshdir/authorized_keys
if [ ! -e "$sshdir" ]; then
mkdir "$sshdir"
fi
if [ ! -e "$authorized" ]; then
touch "$authorized"
fi
# Append found ssh key unless already present
if [ $(grep -c "$publickey" "$authorized") == 0 ]; then
echo "$publickey" >> "$authorized"
logger -t "cloudstack-sshkey" "Received new ssh public key and added to $authorized"
else
logger -t "cloudstack-sshkey" "Received ssh public key which matches existing key"
fi
}
function get_passwd() {
logger -t "cloudstack-passwd" "Sending request to password server at \"${SERVER_IP}\""
password=$(wget -q -t 3 -T 20 -O - --header "DomU_Request: send_my_password" ${SERVER_IP}:8080 2>/dev/null)
local passcheck=0
until [ $? -ne 4 ]; do
[ "$passcheck" -eq "$maxcheck" ] && break
sleep 3
logger -t "cloudstack-passwd" "wget exited with exit code $?, retrying"
password=$(wget -q -t 3 -T 20 -O - --header "DomU_Request: send_my_password" {$SERVER_IP}:8080 2>/dev/null)
passcheck=$((passcheck+1))
done
password=$(echo "$password" | tr -d '\r')
if [ $? -eq 0 ]; then
case $password in
"")
logger -t "cloudstack-passwd" "Password server at $SERVER_IP did not have any password for the VM"
;;
"bad_request")
logger -t "cloudstack-passwd" "VM sent an invalid request to password server at $SERVER_IP"
error_count=$((error_count+1))
;;
"saved_password")
logger -t "cloudstack-passwd" "VM has already saved a password from the password server at $SERVER_IP"
;;
*)
logger -t "cloudstack-passwd" "VM got a valid password from server at $SERVER_IP"
password_received=1
;;
esac
else
logger -t "cloudstack-passwd" "Failed to send request to password server at $SERVER_IP"
error_count=$((error_count+1))
fi
if [ "$password_received" == "0" ]; then
if [ "$error_count" == "$file_count" ]; then
logger -t "cloudstack-passwd" "Failed to get password from any server"
fi
fi
}
function set_passwd() {
# Set password using chpasswd, if available, passwd if that fails, and usermod as a last resort
logger -t "cloudstack-passwd" "Changing password ..."
if [ -x /usr/sbin/chpasswd ]; then
echo "${user}:${password}" | chpasswd
elif [ -x /usr/sbin/pw ]; then
echo "$password" | pw mod user $user -h 0
else
echo "$password" | passwd --stdin $user 2>/dev/null
if [ $? -gt 0 ]; then
usermod -p "$(mkpasswd -m SHA-512 "$password")" $user
if [ $? -gt 0 ]; then
logger -t "cloudstack-passwd" "Failed to change password for user $user"
else
logger -t "cloudstack-passwd" "Successfully changed password for user $user"
fi
fi
fi
# Plesk password change if the /etc/psa folder is an existing directory
[ -d /etc/psa/ ] && sleep 5 && PSA_PASSWORD=$password /usr/local/psa/admin/bin/ch_admin_passwd &>/dev/null &
logger -t "cloudstack-passwd" "Sending acknowledgment to password server at ${SERVER_IP}"
wget -t 3 -T 20 -q -O /dev/null --header "DomU_Request: saved_password" ${SERVER_IP}:8080
}
function obtain_server_ip() {
local file_count=0
local error_count=0
# Iterate through all available dhcp lease files and search for the dhcp server address (Virtual Router)
for DHCP_FILE in $DHCP_FILES; do
if [ -s "$DHCP_FILE" ]; then
file_count=$((file_count+1))
local maxcheck=15
local ip="$(awk -F ' |;' '/dhcp-server-identifier/ { print $5 }' "${DHCP_FILE}" | tail -1)"
local ipcheck=0
until isValidIP "${ip}"
do
[ $ipcheck -eq $maxcheck ] && continue 2
logger -t "cloudstack" "No valid IP \"${ip}\" found in ${DHCP_FILE}"
ip="$(awk -F ' |;' '/dhcp-server-identifier/ { print $5 }' "${DHCP_FILE}" | tail -1)"
ipcheck=$((ipcheck+1))
sleep 3
done
SERVER_IP=$ip
if [ -n "${SERVER_IP}" ]; then
keys_received=0
password_received=0
get_passwd
get_sshkey
if [ "$password_received" == "1" ] || [ "$keys_received" == "1" ]; then
break
fi
else
logger -t "cloudstack" "Could not find server IP in $DHCP_FILE"
error_count=$((error_count+1))
fi
fi
done
if [ "$password_received" == "1" ]; then
set_passwd
fi
if [ "$keys_received" == "1" ]; then
set_sshkey
fi
}
obtain_server_ip
exit 0