From 44f8af4a501e77f8f1b3fb857a009724dea7e2c5 Mon Sep 17 00:00:00 2001 From: David Coppit Date: Thu, 25 Jun 2015 23:41:40 -0400 Subject: [PATCH] Split up the mapping of IDs from "runas". Also have config files specify their user/group IDs for the commands. --- Dockerfile | 5 +-- mapids.sh | 80 ++++++++++++++++++++++++++++++++++++++++++++++ monitor.sh | 15 ++++++++- runas.sh | 91 ++++++++++------------------------------------------- sample.conf | 5 +++ 5 files changed, 118 insertions(+), 78 deletions(-) create mode 100755 mapids.sh diff --git a/Dockerfile b/Dockerfile index bb5d419..d775525 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,6 @@ VOLUME ["/config", \ "/dir1", "/dir2", "/dir3", "/dir4", "/dir5", "/dir6", "/dir7", "/dir8", "/dir9", "/dir10", \ "/dir11", "/dir12", "/dir13", "/dir14", "/dir15", "/dir16", "/dir17", "/dir18", "/dir19", "/dir20"] -ENV UGID 0:0 ENV UMAP "" ENV GMAP "" @@ -37,5 +36,7 @@ ADD monitor.sh /files/monitor.sh RUN chmod a+x /files/monitor.sh ADD runas.sh /files/runas.sh RUN chmod +x /files/runas.sh +ADD mapids.sh /files/mapids.sh +RUN chmod +x /files/mapids.sh -CMD /files/runas.sh "$UMAP" "$GMAP" "$UGID" /files/start.sh +CMD /files/mapids.sh "$UMAP" "$GMAP" && /files/start.sh diff --git a/mapids.sh b/mapids.sh new file mode 100755 index 0000000..a250f27 --- /dev/null +++ b/mapids.sh @@ -0,0 +1,80 @@ +#!/bin/bash + +#----------------------------------------------------------------------------------------------------------------------- + +function ts { + echo [`date '+%b %d %X'`] +} + +#----------------------------------------------------------------------------------------------------------------------- + +function process_args { + # These are meant to be globals. + UMAP=$1 + GMAP=$2 + + for NAME_UID_GID in $UMAP + do + if [[ ! "$NAME_UID_GID" =~ ^[A-Za-z0-9._][-A-Za-z0-9._]*:[0-9]{1,}:[0-9]{1,}$ ]] + then + echo "UMAP value $NAME_UID_GID is not valid. It should be of the form ::" + exit 1 + fi + done + + for NAME_GID in $GMAP + do + if [[ ! "$NAME_GID" =~ ^[A-Za-z0-9._][-A-Za-z0-9._]*:[0-9]{1,}$ ]] + then + echo "GMAP value $NAME_GID is not valid. It should be of the form :" + exit 1 + fi + done +} + +#----------------------------------------------------------------------------------------------------------------------- + +function update_users { + local UMAP=$1 + + if [[ "$UMAP" == "" ]]; then return; fi + + echo "$(ts) Updating existing users..." + + for NAME_UID_GID in $UMAP + do + local NAME=${NAME_UID_GID%:*:*} + local USER_ID=${NAME_UID_GID#*:} + USER_ID=${USER_ID%:*} + local GROUP_ID=${NAME_UID_GID#*:*:} + + echo "$(ts) Setting user \"$NAME\" to user ID=\"$USER_ID\" and default group ID=\"$GROUP_ID\"" + usermod -o -u $USER_ID -g $GROUP_ID $NAME + done +} + +#----------------------------------------------------------------------------------------------------------------------- + +function update_groups { + local GMAP=$1 + + if [[ "$GMAP" == "" ]]; then return; fi + + echo "$(ts) Updating existing groups..." + + for NAME_GID in $GMAP + do + local NAME=${NAME_GID%:*} + local GROUP_ID=${NAME_GID#*:} + + echo "$(ts) Setting group \"$NAME\" to ID=\"$GROUP_ID\"" + groupmod -o -g $GROUP_ID $NAME + done +} + +#----------------------------------------------------------------------------------------------------------------------- + +process_args "$@" + +update_users "$UMAP" +update_groups "$GMAP" diff --git a/monitor.sh b/monitor.sh index 7f77856..48cffa5 100755 --- a/monitor.sh +++ b/monitor.sh @@ -80,6 +80,16 @@ function check_config { exit 1 fi + if [[ ! "$USER_ID" =~ ^[0-9]{1,}$ ]]; then + echo "$(ts) USER_ID must be defined in $CONFIG_FILE as a whole number." + exit 1 + fi + + if [[ ! "$GROUP_ID" =~ ^[0-9]{1,}$ ]]; then + echo "$(ts) GROUP_ID must be defined in $CONFIG_FILE as a whole number." + exit 1 + fi + if [ -z "$COMMAND" ]; then echo "$(ts) COMMAND must be defined in $CONFIG_FILE" exit 1 @@ -209,8 +219,11 @@ do # Wait until it's okay to run the command again, monstering up events as we do so wait_for_minimum_period $last_run_time + # Generate a user from the MD5 of the config file + USER=$(md5sum $CONFIG_FILE | awk '{print $1}') + echo "$(ts) Running command" - $COMMAND & + /files/runas.sh $USER:$USER_ID:$GROUP_ID $COMMAND & PID=$! last_run_time=$(date +"%s") diff --git a/runas.sh b/runas.sh index 7e853ec..70a1bae 100755 --- a/runas.sh +++ b/runas.sh @@ -1,6 +1,5 @@ #!/bin/bash -USER=docker GROUP=docker #----------------------------------------------------------------------------------------------------------------------- @@ -12,88 +11,32 @@ function ts { #----------------------------------------------------------------------------------------------------------------------- function process_args { - # These are meant to be globals. - UMAP=$1 - GMAP=$2 - UGID=$3 + local USER_UID_GID=$1 - for NAME_UID_GID in $UMAP - do - if [[ ! "$NAME_UID_GID" =~ ^[A-Za-z0-9._][-A-Za-z0-9._]*:[0-9]{1,}:[0-9]{1,}$ ]] - then - echo "UMAP value $NAME_UID_GID is not valid. It should be of the form ::" - exit 1 - fi - done - - for NAME_GID in $GMAP - do - if [[ ! "$NAME_GID" =~ ^[A-Za-z0-9._][-A-Za-z0-9._]*:[0-9]{1,}$ ]] - then - echo "GMAP value $NAME_GID is not valid. It should be of the form :" - exit 1 - fi - done - - if [[ ! "$UGID" =~ ^[0-9]{1,}:[0-9]{1,}$ ]] + if [[ ! "$USER_UID_GID" =~ ^[A-Za-z0-9._][-A-Za-z0-9._]*:[0-9]{1,}:[0-9]{1,}$ ]] then - echo "UGID value $UGID is not valid. It should be of the form :" + echo "USER_UID_GID value $USER_UID_GID is not valid. It should be of the form ::" exit 1 fi -} -#----------------------------------------------------------------------------------------------------------------------- - -function update_users { - local UMAP=$1 - - if [[ "$UMAP" == "" ]]; then return; fi - - echo "$(ts) Updating existing users..." - - for NAME_UID_GID in $UMAP - do - local NAME=${NAME_UID_GID%:*:*} - local USER_ID=${NAME_UID_GID#*:} - USER_ID=${USER_ID%:*} - local GROUP_ID=${NAME_UID_GID#*:*:} - - echo "$(ts) Setting user \"$NAME\" to user ID=\"$USER_ID\" and default group ID=\"$GROUP_ID\"" - usermod -o -u $USER_ID -g $GROUP_ID $NAME - done -} - -#----------------------------------------------------------------------------------------------------------------------- - -function update_groups { - local GMAP=$1 - - if [[ "$GMAP" == "" ]]; then return; fi - - echo "$(ts) Updating existing groups..." - - for NAME_GID in $GMAP - do - local NAME=${NAME_GID%:*} - local GROUP_ID=${NAME_GID#*:} - - echo "$(ts) Setting group \"$NAME\" to ID=\"$GROUP_ID\"" - groupmod -o -g $GROUP_ID $NAME - done + # These are meant to be global. + USER=${USER_UID_GID%:*:*} + USER_ID=${USER_UID_GID#*:} + USER_ID=${USER_ID%:*} + GROUP_ID=${USER_UID_GID#*:*:} } #----------------------------------------------------------------------------------------------------------------------- function create_user { - local UGID=$1 - - # Create a new user with the proper user and group ID. - local USER_ID=${UGID%:*} - local GROUP_ID=${UGID#*:} + local USER=$1 + local USER_ID=$2 + local GROUP=$3 + local GROUP_ID=$4 echo "$(ts) Creating user \"$USER\" (ID $USER_ID) and group \"$GROUP\" (ID $GROUP_ID) to run the command..." - # We could be aliasing this new user to some existing user. Let's assume that's harmless. + # We could be aliasing this new user to some existing user. I assume that's harmless. groupadd -o -g $GROUP_ID $GROUP useradd -o -u $USER_ID -r -g $GROUP -d /home/$USER -s /sbin/nologin -c "Docker image user" $USER @@ -105,12 +48,10 @@ function create_user { process_args "$@" -# Shift off the args so that we can exec $@ below -shift; shift; shift +# Shift off the arg so that we can exec $@ below +shift -update_users "$UMAP" -update_groups "$GMAP" -create_user "$UGID" +create_user $USER $USER_ID $GROUP $GROUP_ID echo "$(ts) Running command as user \"$USER\"..." exec /sbin/setuser $USER "$@" diff --git a/sample.conf b/sample.conf index eb58788..77ac6a2 100644 --- a/sample.conf +++ b/sample.conf @@ -27,6 +27,11 @@ MIN_PERIOD=10:00 # that we've installed the plugin called "sagex-services - SageTV Remote API Services". COMMAND="wget -nv -O /dev/null --auth-no-challenge http://sage:frey@192.168.1.102:8080/sagex/api?c=RunLibraryImportScan&1=" +# Set the user and group ID that you want to run the command as. The user will be randomly generated. This is mostly so +# that files written by the command in any directory shared with the host will have the right IDs. +USER_ID=0 +GROUP_ID=0 + # This is a very good idea if your command modifies the WATCH_DIR in any way. You can easily trigger yourself because # most programs don't worry about checking the current state before making a change. e.g. chmod will set the mode of a # file even if it already has that mode.