Commit 2454ff70 authored by Nikos Skalkotos's avatar Nikos Skalkotos

Add a new auth_keys OS parameter

This parameter can be used to inject authorization keys to the VM for
the same users for whom a password change will be performed.

Prior to this commit, the same functionality could be achieved by
using the img_personality parameter to append the needed authorized_keys
files to the instance, but this is not the correct way to do it. Only
snf-image which does the deployment may know the actual path to the
authorized keys files.
parent a16d880b
......@@ -15,6 +15,8 @@ following OS Parameters:
(:ref:`details <image-passwd>`)
* **img_passwd_hash** (optional): the hash of the password to be injected into
the image (:ref:`details <image-passwd-hash>`)
* **auth_keys** (optional): keys to be injected into the instance for remote
log in (:ref:`details <authorized-keys>`)
* **img_properties** (optional): additional image properties used to customize
the image (:ref:`details <image-properties>`)
* **img_personality** (optional): files to be injected into the image's file
......@@ -95,8 +97,8 @@ Image Password (img_passwd)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
The value of this parameter is the password to be injected into the image. If
this parameter is not set at all and **img_passwd_hash** is missing too, then
the *ChangePassword* task (see
this parameter is not set at all and **img_passwd_hash** and **auth_keys** are
missing too, then the *ChangePassword* task (see
:ref:`Image Configuration Tasks <image-configuration-tasks>`) will not run.
This parameter cannot be defined in conjunction with **img_passwd_hash**.
......@@ -106,12 +108,27 @@ Image Password Hash (img_passwd_hash)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The value of this parameter is the hash of the password to be injected into the
image. If this parameter is not set at all and **img_passwd** is missing too,
then the *ChangePassword* task (see
image. If this parameter is not set at all and **img_passwd** and **auth_keys**
are missing too, then the *ChangePassword* task (see
:ref:`Image Configuration Tasks <image-configuration-tasks>`) will not run.
This parameter is not applicable on Windows images and cannot be defined in
conjunction with **img_passwd**.
.. _authorized-keys:
Authorized Keys (auth_keys)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
The value of this parameter is a list of keys to be injected into the instance,
to allow password-less SSH log in. The supported format is the
*authorized_keys* file format of OpenSSH. The affected users are the ones
defined in the *USERS* image property (see
:ref:`Image Properties <image-properties>`). If this parameter is not set or is
empty and **img_passwd** and **img_passwd_hash** are missing too, then the
*ChangePassword* task (see
:ref:`Image Configuration Tasks <image-configuration-tasks>`) will not run.
This parameter is not applicable on Windows images.
.. _image-properties:
Image Properties (img_properties)
......
......@@ -147,42 +147,75 @@ windows_password() {
done
}
unix_password() {
local flavor target password encrypted users tmp_shadow method default_method
flavor="$1"
target="$2"
password="$3"
shadow="${flavor}_shadow"
if [ ! -e "$target${!shadow}" ]; then
log_error "No ${!shadow} found!"
unix_auth() {
local flavor target password encrypted users usr tmp_shadow method home opt
local default_method keys entry keys_file keys_file_tmpl new_entry uid guid
while getopts 'f:k:m:p:t:' opt; do
case $opt in
f) flavor="$OPTARG"
;;
k) keys="$OPTARG"
;;
m) method="$OPTARG"
;;
p) password="$OPTARG"
;;
t) target="$OPTARG"
;;
*) log_error "Invalid option -$OPTARGS in unix_auth"
;;
esac
done
if [ -z "${flavor+dummy}" ]; then
log_error "unix_auth: flavor (-f) parameter needed but missing"
fi
if [ -z "${target+dummy}" ]; then
log_error "unix_auth: target (-t) parameter needed but missing"
fi
if [ -n "${password+dummy}" ]; then
shadow="${flavor}_shadow"
if [ ! -e "$target${!shadow}" ]; then
log_error "No ${!shadow} found!"
fi
case "$flavor" in
linux|freebsd)
default_method=sha512
;;
openbsd)
default_method=blowfish
;;
netbsd)
default_method=sha1
;;
*)
log_error "Unknown unix flavor: \`$flavor'"
;;
esac
method="${SNF_IMAGE_PROPERTY_PASSWD_HASHING_METHOD:-$default_method}"
if [ "$method" != "none" ]; then
echo -n "Encrypting password with \`$method' method ... "
encrypted=$("@scriptsdir@/hashpwd.py" -m "$method" "$password")
echo "done"
else
encrypted="$password"
case "$flavor" in
linux|freebsd)
default_method=sha512
;;
openbsd)
default_method=blowfish
;;
netbsd)
default_method=sha1
;;
*)
log_error "Unknown unix flavor: \`$flavor'"
;;
esac
method="${method:-$default_method}"
if [ "$method" != "none" ]; then
echo -n "Encrypting password with \`$method' method ... "
encrypted=$("@scriptsdir@/hashpwd.py" -m "$method" "$password")
echo "done"
else
encrypted="$password"
fi
fi
if [ -n "${keys}" ]; then
# Find the value of the AuthorizedKeysFile keyword if present in
# sshd_config. For more info check:
# https://www.freebsd.org/cgi/man.cgi?sshd_config(5)
keys_file_tmpl=$(cut -d'#' -f1 |
{ egrep '\<AuthorizedKeysFile' "${target}/etc/ssh/sshd_config" || true; } |
awk '{print $NF}')
keys_file_tmpl="$(printf "%q" "${keys_file_tmpl:-%h/.ssh/authorized_keys}")"
fi
users=()
declare -a users
if [ -n "$SNF_IMAGE_PROPERTY_USERS" ]; then
for usr in $SNF_IMAGE_PROPERTY_USERS; do
......@@ -190,33 +223,65 @@ unix_password() {
done
else
warn "Image property \`USERS' is missing or empty. " \
"Changing the password for default user: \`root'."
"Using default user: \`root'."
users+=("root")
fi
for i in $(seq 0 1 $((${#users[@]}-1))); do
tmp_shadow="$(mktemp)"
add_cleanup rm "$tmp_shadow"
for usr in "${users[@]}"; do
if [ -n "${password+dummy}" ]; then
echo -n "Setting ${usr} password ... "
tmp_shadow="$(mktemp)"
add_cleanup rm "$tmp_shadow"
echo -n "Setting ${users[$i]} password ... "
entry=$(grep "^${users[$i]}:" "$target${!shadow}") || true
if [ -z "$entry" ]; then
log_error "User: \`${users[$i]}' does not exist."
entry=$(grep "^${usr}:" "$target${!shadow}") || true
if [ -z "$entry" ]; then
log_error "User: \`${usr}' does not exist" \
"(not present in ${!shadow})."
fi
new_entry="$(${flavor}_change_shadow_entry "$entry" "$encrypted")"
grep -v "^${usr}:" "$target${!shadow}" > "$tmp_shadow"
echo "$new_entry" >> "$tmp_shadow"
cat "$tmp_shadow" > "$target${!shadow}"
echo "done"
fi
new_entry="$(${flavor}_change_shadow_entry "$entry" "$encrypted")"
grep -v "^${users[$i]}:" "$target${!shadow}" > "$tmp_shadow"
echo "$new_entry" >> "$tmp_shadow"
cat "$tmp_shadow" > "$target${!shadow}"
echo "done"
if [ -n "${keys+dummy}" ]; then
echo -n "Adding authorization keys for user: \`${usr}' ... "
IFS=':' read -ra entry <<<"$(grep "^${usr}:" "${target}/etc/passwd" || true)"
if [ "${entry[0]}" != "${usr}" ]; then
log_error "User: \`${usr}' does not exist" \
"(not present in /etc/passwd)"
fi
uid=${entry[2]}
guid=${entry[3]}
home=${entry[5]}
keys_file="${keys_file_tmpl//%%/\$\\'%\'}"
keys_file="${keys_file//%h/\$\{home\}}"
keys_file="${keys_file//%u/\$\{usr\}}"
eval keys_file=\"$keys_file\"
if [ -z "$keys_file" ]; then
log_error "Error while evaluating AuthorizedKeysFile: \`$keys_file'"
fi
mkdir -p "$(dirname "${target}${keys_file}")"
chown "${uid}:${guid}" "$(dirname "${target}${keys_file}")"
chmod 700 "$(dirname "${target}${keys_file}")"
echo "$keys" >> "${target}${keys_file}"
chown "${uid}:${guid}" "${target}${keys_file}"
chmod 600 "${target}${keys_file}"
echo "done"
fi
done
}
if [ -z "${SNF_IMAGE_PASSWD+dummy}" -a -z "${SNF_IMAGE_PASSWD_HASH+dummy}" ]; then
warn "Task ${PROGNAME:2} will not run. Password is not set"
exit 0
fi
#trim users var
SNF_IMAGE_PROPERTY_USERS=$(echo $SNF_IMAGE_PROPERTY_USERS)
......@@ -225,13 +290,46 @@ if [[ "$SNF_IMAGE_PROPERTY_OSFAMILY" =~ ^windows ]]; then
log_error "On Windows images password hash is not applicable."
fi
if [ -n "${SNF_IMAGE_AUTH_KEYS+dummy}" ]; then
warn "Injecting authorization keys is not supported for Windows"
fi
if [ -z "${SNF_IMAGE_PASSWD+dummy}" ]; then
warn "Task ${PROGNAME:2} will not run. Password is not set"
exit 0
fi
windows_password "$SNF_IMAGE_TARGET" "$SNF_IMAGE_PASSWD"
else
ARGS=("-f" "$SNF_IMAGE_PROPERTY_OSFAMILY" "-t" "$SNF_IMAGE_TARGET")
if [ -n "${SNF_IMAGE_PASSWD_HASH+dummy}" ]; then
SNF_IMAGE_PROPERTY_PASSWD_HASHING_METHOD=none
SNF_IMAGE_PASSWD="$SNF_IMAGE_PASSWD_HASH"
fi
unix_password "$SNF_IMAGE_PROPERTY_OSFAMILY" "$SNF_IMAGE_TARGET" "$SNF_IMAGE_PASSWD"
if [ -n "${SNF_IMAGE_PASSWD+dummy}" ]; then
ARGS+=("-p" "$SNF_IMAGE_PASSWD")
fi
if [ -n "${SNF_IMAGE_PROPERTY_PASSWD_HASHING_METHOD}" ]; then
ARGS+=("-m" "${SNF_IMAGE_PROPERTY_PASSWD_HASHING_METHOD}")
fi
if [ -n "${SNF_IMAGE_AUTH_KEYS+dummy}" ]; then
if [ -n "${SNF_IMAGE_AUTH_KEYS}" ]; then
ARGS+=("-k" "$SNF_IMAGE_AUTH_KEYS")
else
warn "Ignoring empty AUTH_KEYS parameter"
fi
fi
if [ -z "${SNF_IMAGE_PASSWD+dummy}" -a -z "${SNF_IMAGE_AUTH_KEYS}" ]; then
warn "Task: \`${PROGNAME:2} will not run. No password or key is set"
exit 0
fi
unix_auth "${ARGS[@]}"
fi
# For FreeBSD, OpenBSD and NetBSD we need to recreate the password databases
......
......@@ -137,7 +137,8 @@ get_api20_arguments() {
local osparams osp
osparams=(IMG_ID IMG_FORMAT IMG_PASSWD IMG_PASSWD_HASH IMG_PROPERTIES
IMG_PERSONALITY CONFIG_URL OS_PRODUCT_KEY OS_ANSWER_FILE)
IMG_PERSONALITY CONFIG_URL OS_PRODUCT_KEY OS_ANSWER_FILE
AUTH_KEYS)
# Store OSP_VAR in VAR
for param in "${osparams[@]}"; do
......
......@@ -205,6 +205,10 @@ if [ -n "${OS_PRODUCT_KEY+dummy}" ]; then
snf_export_OS_PRODUCT_KEY="$OS_PRODUCT_KEY"
fi
if [ -n "${AUTH_KEYS+dummy}" ]; then
snf_export_AUTH_KEYS="$AUTH_KEYS"
fi
assign_disk_devices_to snf_export_DEV
create_floppy "$floppy"
......
......@@ -4,6 +4,7 @@ img_passwd The password to be assigned to the user accounts
img_passwd_hash Hashed version of the password to be assigned to the user accounts (conflicts with img_passwd)
img_properties The image properties that are used to customize the image (json.dumps format)
img_personality The files to be injected into the image (base64 encoded in a json.dumps format)
auth_keys Keys to append to the users' authorized keys files for remote log in
os_product_key A product key to be used to license a Windows deployment (windows-only)
os_answer_file An answer file used by Windows to automate the setup process (windows-only)
config_url The URL to download configuration data from
......@@ -24,7 +24,7 @@ set -e
check_required() {
local required_params="IMG_ID IMG_FORMAT"
local osparams="$required_params IMG_PASSWD IMG_PROPERTIES IMG_PERSONALITY CONFIG_URL OS_PRODUCT_KEY OS_ANSWER_FILE"
local osparams="$required_params IMG_PASSWD IMG_PROPERTIES IMG_PERSONALITY CONFIG_URL OS_PRODUCT_KEY OS_ANSWER_FILE AUTH_KEYS"
local osp
source_variant
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment