# unset some environment variables that could screw things up
GREP_OPTIONS=
+# default return code
+ERR=0
+
########################################################################
# FUNCTIONS
########################################################################
MonkeySphere server admin tool.
subcommands:
- update-users (s) [USER]... update users authorized_keys files
+ update-users (u) [USER]... update users authorized_keys files
gen-key (g) [HOSTNAME] generate gpg key for the server
- publish-key (p) publish server key to keyserver
- trust-keys (t) KEYID... mark keyids as trusted
- update-user-userids (u) USER UID... add/update user IDs for a user
- remove-user-userids (r) USER UID... remove user IDs for a user
+ show-fingerprint (f) show server's host key fingerprint
+ publish-key (p) publish server's host key to keyserver
+ trust-key (t) KEYID [LEVEL] set owner trust for keyid
help (h,?) this help
EOF
local hostName
hostName=${1:-$(hostname --fqdn)}
+ service=${SERVICE:-"ssh"}
+ userID="${service}://${hostName}"
+
+ if gpg --list-key ="$userID" > /dev/null 2>&1 ; then
+ failure "Key for '$userID' already exists"
+ fi
# set key defaults
KEY_TYPE=${KEY_TYPE:-"RSA"}
KEY_LENGTH=${KEY_LENGTH:-"2048"}
KEY_USAGE=${KEY_USAGE:-"auth"}
+ KEY_EXPIRE=${KEY_EXPIRE:-"0"}
cat <<EOF
Please specify how long the key should be valid.
0 = key does not expire
<n>m = key expires in n months
<n>y = key expires in n years
EOF
- read -p "Key is valid for? ($EXPIRE) " EXPIRE; EXPIRE=${EXPIRE:-"0"}
-
- SERVICE=${SERVICE:-"ssh"}
- USERID=${USERID:-"$SERVICE"://"$hostName"}
+ read -p "Key is valid for? ($KEY_EXPIRE) " KEY_EXPIRE; KEY_EXPIRE=${KEY_EXPIRE:-"0"}
# set key parameters
keyParameters=$(cat <<EOF
Key-Type: $KEY_TYPE
Key-Length: $KEY_LENGTH
Key-Usage: $KEY_USAGE
-Name-Real: $USERID
-Expire-Date: $EXPIRE
+Name-Real: $userID
+Expire-Date: $KEY_EXPIRE
EOF
)
# add the revoker field if requested
-# FIXME: the 1: below assumes that $REVOKER's key is an RSA key. why?
-# FIXME: why is this marked "sensitive"? how will this signature ever
-# be transmitted to the expected revoker?
+ # FIXME: the "1:" below assumes that $REVOKER's key is an RSA key. why?
+ # FIXME: why is this marked "sensitive"? how will this signature ever
+ # be transmitted to the expected revoker?
if [ "$REVOKER" ] ; then
keyParameters="${keyParameters}"$(cat <<EOF
echo "The following key parameters will be used:"
echo "$keyParameters"
- read -p "generate key? [Y|n]: " OK; OK=${OK:=Y}
+ read -p "Generate key? [Y|n]: " OK; OK=${OK:=Y}
if [ ${OK/y/Y} != 'Y' ] ; then
failure "aborting."
fi
- if gpg --list-key ="$USERID" > /dev/null 2>&1 ; then
- failure "key for '$USERID' already exists"
- fi
-
# add commit command
keyParameters="${keyParameters}"$(cat <<EOF
EOF
)
- log -n "generating server key... "
+ log "generating server key... "
echo "$keyParameters" | gpg --batch --gen-key
- log "done."
- fingerprint_server_key
+
+ # output the server fingerprint
+ fingerprint_server_key "=${userID}"
+
+ # find the key fingerprint of the server primary key
+ keyID=$(gpg --list-key --with-colons --with-fingerprint "=${userID}" | \
+ grep '^fpr:' | head -1 | cut -d: -f10)
+
+ # write the key to the file
+ # NOTE: assumes that the primary key is the proper key to use
+ (umask 077 && gpgsecret2ssh "$keyID" > "${MS_HOME}/ssh_host_rsa_key")
+ log "Private SSH host key output to file: ${MS_HOME}/ssh_host_rsa_key"
}
+# gpg output key fingerprint
fingerprint_server_key() {
- gpg --fingerprint --list-secret-keys =ssh://$(hostname --fqdn)
+ local ID
+
+ if [ -z "$1" ] ; then
+ ID="$1"
+ else
+ ID="=ssh://$(hostname --fqdn)"
+ fi
+
+ gpg --fingerprint --list-secret-keys "$ID"
}
########################################################################
KEYSERVER=${KEYSERVER:-"subkeys.pgp.net"}
CHECK_KEYSERVER=${CHECK_KEYSERVER:="true"}
REQUIRED_USER_KEY_CAPABILITY=${REQUIRED_USER_KEY_CAPABILITY:-"a"}
+AUTHORIZED_USER_IDS=${AUTHORIZED_USER_IDS:-"%h/.config/monkeysphere/authorized_user_ids"}
USER_CONTROLLED_AUTHORIZED_KEYS=${USER_CONTROLLED_AUTHORIZED_KEYS:-"%h/.ssh/authorized_keys"}
export GNUPGHOME
mkdir -p "${CACHE}/authorized_keys"
case $COMMAND in
- 'update-users'|'update-user'|'s')
+ 'update-users'|'update-user'|'u')
if [ "$1" ] ; then
+ # get users from command line
unames="$@"
else
- unames=$(ls -1 "${MS_HOME}/authorized_user_ids")
+ # or just look at all users if none specified
+ unames=$(getent passwd | cut -d: -f1)
fi
+ # loop over users
for uname in $unames ; do
MODE="authorized_keys"
+ # check all specified users exist
+ if ! getent passwd "$uname" >/dev/null ; then
+ error "----- unknown user '$uname' -----"
+ continue
+ fi
+
+ # set authorized_user_ids variable,
+ # translate ssh-style path variables
+ authorizedUserIDs=$(translate_ssh_variables "$uname" "$AUTHORIZED_USER_IDS")
+
+ # skip user if authorized_user_ids file does not exist
+ if [ ! -f "$authorizedUserIDs" ] ; then
+ #FIXME: what about a user with no authorized_user_ids
+ # file, but with an authorized_keys file when
+ # USER_CONTROLLED_AUTHORIZED_KEYS is set?
+ continue
+ fi
+
log "----- user: $uname -----"
- # set variables for the user
- AUTHORIZED_USER_IDS="${MS_HOME}/authorized_user_ids/${uname}"
# temporary authorized_keys file
- AUTHORIZED_KEYS="${CACHE}/authorized_keys/${uname}.tmp"
-
- # make sure user's authorized_user_ids file exists
- touch "$AUTHORIZED_USER_IDS"
- # make sure the authorized_keys file exists and is clear
- > "$AUTHORIZED_KEYS"
+ AUTHORIZED_KEYS=$(mktemp)
# skip if the user's authorized_user_ids file is empty
- if [ ! -s "$AUTHORIZED_USER_IDS" ] ; then
- log "authorized_user_ids file for '$uname' is empty."
+ if [ ! -s "$authorizedUserIDs" ] ; then
+ log "authorized_user_ids file '$authorizedUserIDs' is empty."
+ #FIXME: what about a user with an empty
+ # authorized_user_ids file, but with an
+ # authorized_keys file when
+ # USER_CONTROLLED_AUTHORIZED_KEYS is set?
continue
fi
# process authorized_user_ids file
log "processing authorized_user_ids file..."
- process_authorized_user_ids
+ process_authorized_user_ids "$authorizedUserIDs"
# add user-controlled authorized_keys file path if specified
if [ "$USER_CONTROLLED_AUTHORIZED_KEYS" != '-' ] ; then
- userHome=$(getent passwd "$uname" | cut -d: -f6)
- userAuthorizedKeys=${USER_CONTROLLED_AUTHORIZED_KEYS/\%h/"$userHome"}
- log -n "adding user's authorized_keys file... "
- cat "$userAuthorizedKeys" >> "$AUTHORIZED_KEYS"
- loge "done."
+ userAuthorizedKeys=$(translate_ssh_variables "$uname" "$USER_CONTROLLED_AUTHORIZED_KEYS")
+ if [ -f "$userAuthorizedKeys" ] ; then
+ log -n "adding user's authorized_keys file... "
+ cat "$userAuthorizedKeys" >> "$AUTHORIZED_KEYS"
+ loge "done."
+ fi
fi
+ # openssh appears to check the contents of the
+ # authorized_keys file as the user in question, so the file
+ # must be readable by that user at least.
+ # FIXME: is there a better way to do this?
+ chgrp $(getent passwd "$uname" | cut -f4 -d:) "$AUTHORIZED_KEYS"
+ chmod g+r "$AUTHORIZED_KEYS"
+
# move the temp authorized_keys file into place
- mv -f "${CACHE}/authorized_keys/${uname}.tmp" "${CACHE}/authorized_keys/${uname}"
+ mv -f "$AUTHORIZED_KEYS" "${CACHE}/authorized_keys/${uname}"
log "authorized_keys file updated."
done
-
- log "----- done. -----"
;;
'gen-key'|'g')
;;
'show-fingerprint'|'f')
- fingerprint_server_key
+ fingerprint_server_key "$@"
;;
'publish-key'|'p')
publish_server_key
;;
- 'trust-keys'|'trust-key'|'t')
- if [ -z "$1" ] ; then
- failure "You must specify at least one key to trust."
- fi
-
- # process key IDs
- for keyID ; do
- trust_key "$keyID"
- done
- ;;
-
- 'update-user-userids'|'update-user-userid'|'u')
- uname="$1"
- shift
- if [ -z "$uname" ] ; then
- failure "You must specify user."
- fi
- if [ -z "$1" ] ; then
- failure "You must specify at least one user ID."
- fi
-
- # set variables for the user
- AUTHORIZED_USER_IDS="$MS_HOME"/authorized_user_ids/"$uname"
-
- # make sure user's authorized_user_ids file exists
- touch "$AUTHORIZED_USER_IDS"
-
- # process the user IDs
- for userID ; do
- update_userid "$userID"
- done
-
- log "Run the following to update user's authorized_keys file:"
- log "$PGRM update-users $uname"
- ;;
-
- 'remove-user-userids'|'remove-user-userid'|'r')
- uname="$1"
- shift
- if [ -z "$uname" ] ; then
- failure "You must specify user."
- fi
- if [ -z "$1" ] ; then
- failure "You must specify at least one user ID."
- fi
-
- # set variables for the user
- AUTHORIZED_USER_IDS="$MS_HOME"/authorized_user_ids/"$uname"
-
- # make sure user's authorized_user_ids file exists
- touch "$AUTHORIZED_USER_IDS"
-
- # process the user IDs
- for userID ; do
- remove_userid "$userID"
- done
-
- log "Run the following to update user's authorized_keys file:"
- log "$PGRM update-users $uname"
+ 'trust-key'|'trust-key'|'t')
+ trust_key "$@"
;;
'help'|'h'|'?')
Type '$PGRM help' for usage."
;;
esac
+
+exit "$ERR"