From 17736285e753f1e10e1dcc78a159e62714452ac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Maillard?= Date: Wed, 30 Aug 2017 13:02:24 +0800 Subject: [PATCH 1/2] Ensure odoo user owns volumes only if they're not readonly Also delete unused historical folders /opt/odoo/{bin,var} --- Dockerfile | 4 +--- bin/boot | 33 +++++++++++++++++++++++---------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/Dockerfile b/Dockerfile index 19689f9d..5ef126e2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -79,8 +79,7 @@ USER odoo # If the folders are created with "RUN mkdir" command, they will belong to root # instead of odoo! Hence the "RUN /bin/bash -c" trick. -RUN /bin/bash -c "mkdir -p /opt/odoo/{bin,etc,sources/odoo,additional_addons,data,ssh}" -RUN /bin/bash -c "mkdir -p /opt/odoo/var/{run,log,egg-cache}" +RUN /bin/bash -c "mkdir -p /opt/odoo/{etc,sources/odoo,additional_addons,data,ssh}" # Add Odoo OCB sources and remove .git folder in order to reduce image size WORKDIR /opt/odoo/sources @@ -98,7 +97,6 @@ User 0 RUN chmod -R 775 /opt/odoo && chown -R odoo:odoo /opt/odoo VOLUME [ \ - "/opt/odoo/var", \ "/opt/odoo/etc", \ "/opt/odoo/additional_addons", \ "/opt/odoo/data", \ diff --git a/bin/boot b/bin/boot index 9b25992a..d295ebad 100755 --- a/bin/boot +++ b/bin/boot @@ -20,12 +20,31 @@ function man { set -e } -function _ensure_odoo_user_owns_folder_if_exists { +function _ensure_odoo_user_owns_volume { + # Make sure the folder exists if [ -d $1 ]; then - chown $odoo_user:$odoo_user $1 + # Check if the volume has been mounted read-only + mount_type=$( cat /proc/mounts | grep "\s$1\s" | \ + awk '{print tolower(substr($4,0,3))}' ) + + if [ $mount_type != "ro" ]; then + chown $odoo_user:$odoo_user $1 + else + echo $log_src[`date +%F.%H:%M:%S`]' Read-only volume:' $1 + fi fi } +function _ensure_odoo_user_owns_volumes { + _ensure_odoo_user_owns_volume /opt/odoo/etc + _ensure_odoo_user_owns_volume /opt/odoo/additional_addons + _ensure_odoo_user_owns_volume /opt/odoo/data + _ensure_odoo_user_owns_volume /opt/odoo/data/filestore + _ensure_odoo_user_owns_volume /opt/odoo/data/sessions + _ensure_odoo_user_owns_volume /opt/odoo/data/addons + _ensure_odoo_user_owns_volume /opt/odoo/ssh +} + function _update_odoo_conf_params { # Loop over all the "ODOO_" ENV variables (see `<<<` after `done`) while read -r env_var; do @@ -106,13 +125,7 @@ function start { # If the folders mapped to the volumes didn't exist, Docker has created # them with root instead of the target Odoo user. Making sure to give back # the ownership to the corresponding host user. - chown $odoo_user:$odoo_user /opt/odoo/{etc,additional_addons,data,var} \ - /opt/odoo/var/{run,log,egg-cache} - - # The following folders might not exist - _ensure_odoo_user_owns_folder_if_exists /opt/odoo/data/filestore - _ensure_odoo_user_owns_folder_if_exists /opt/odoo/data/sessions - _ensure_odoo_user_owns_folder_if_exists /opt/odoo/data/addons + _ensure_odoo_user_owns_volumes echo $log_src[`date +%F.%H:%M:%S`]' Checking special requirements...' bash /opt/scripts/startup.sh @@ -127,7 +140,7 @@ function start { echo $log_src[`date +%F.%H:%M:%S`]' Running odoo...' set +e if [ ! -e $1 ]; then - echo $log_src[`date +%F.%H:%M:%S`]' ...with additional args: ' $* + echo $log_src[`date +%F.%H:%M:%S`]' ...with additional args:' $* fi sudo -i -u $odoo_user /usr/bin/python \ /opt/odoo/sources/odoo/$BINARY_NAME \ From c33e64bdb74ba4b242ea30bfd2939041f1a48c24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Maillard?= Date: Wed, 30 Aug 2017 14:53:53 +0800 Subject: [PATCH 2/2] Protect variables with `"` Others: - move no_addons.sh to bin folder since it's a FIXME script - allow boot if target user has already been created (e.g. restart) --- bin/boot | 57 +++++++++++++++++-------------- {auto_addons => bin}/no_addons.sh | 15 +++++--- bin/target_user.sh | 34 +++++++++++------- bin/update_odoo_param.sh | 23 +++++++------ 4 files changed, 75 insertions(+), 54 deletions(-) rename {auto_addons => bin}/no_addons.sh (54%) diff --git a/bin/boot b/bin/boot index d295ebad..e6367072 100755 --- a/bin/boot +++ b/bin/boot @@ -22,15 +22,16 @@ function man { function _ensure_odoo_user_owns_volume { # Make sure the folder exists - if [ -d $1 ]; then + if [ -d "$1" ]; then # Check if the volume has been mounted read-only mount_type=$( cat /proc/mounts | grep "\s$1\s" | \ awk '{print tolower(substr($4,0,3))}' ) - if [ $mount_type != "ro" ]; then - chown $odoo_user:$odoo_user $1 + if [ "$mount_type" != 'ro' ]; then + # Set target user as owner + chown "$odoo_user":"$odoo_user" "$1" else - echo $log_src[`date +%F.%H:%M:%S`]' Read-only volume:' $1 + echo $log_src[`date +%F.%H:%M:%S`]' Read-only volume:' "$1" fi fi } @@ -54,38 +55,39 @@ function _update_odoo_conf_params { # Get the value of the corresponding ENV variable and escape slashes val=${!env_var} - val=$( echo $val | sed 's/\//\\\//g') + val=$( echo "$val" | sed 's/\//\\\//g') # FIXME Should not be an external script (see reason in script header) - bash /app/bin/update_odoo_param.sh $odoo_user $odoo_conf_file $odoo_param $val + bash /app/bin/update_odoo_param.sh "$odoo_user" "$odoo_conf_file" \ + "$odoo_param" "$val" # Unset the environment variable for security purpose - unset $env_var + unset "$env_var" done <<< "$( printenv | grep '^ODOO_' | sed 's/=.*//g' )" } function _setup_ssh_key { # Create SSH config folder in $HOME folder of Odoo target user - ssh_folder=$( getent passwd $odoo_user | cut -d: -f6 )/.ssh - sudo -i -u $odoo_user mkdir $ssh_folder + ssh_folder=$( getent passwd "$odoo_user" | cut -d: -f6 )/.ssh + sudo -i -u "$odoo_user" mkdir "$ssh_folder" # Copy SSH private key from /opt/odoo/ssh - sudo -i -u $odoo_user cp /opt/odoo/ssh/id_rsa $ssh_folder + sudo -i -u "$odoo_user" cp /opt/odoo/ssh/id_rsa "$ssh_folder" echo $log_src[`date +%F.%H:%M:%S`]' Scanning GitHub key...' # Hide ssh-keyscan stderr output since it's actually log message ssh-keyscan github.com 2> /dev/null | \ - sudo -i -u $odoo_user tee $ssh_folder/known_hosts > /dev/null + sudo -i -u "$odoo_user" tee "$ssh_folder/known_hosts" > /dev/null # Bind SSH key to GitHub host echo "host github.com HostName github.com User git IdentityFile $ssh_folder/id_rsa" | \ - sudo -i -u $odoo_user tee $ssh_folder/config > /dev/null + sudo -i -u "$odoo_user" tee "$ssh_folder/config" > /dev/null # Secure SSH key - chmod 400 $ssh_folder/id_rsa + chmod 400 "$ssh_folder/id_rsa" } function _download_addons { @@ -94,8 +96,8 @@ function _download_addons { # 2) There's a file called `oca_dependencies.txt` at the root of extra addons folder if [ "$ADDONS_REPO" -o -a /opt/odoo/additional_addons/oca_dependencies.txt ]; then # Git config for target user - sudo -i -u $odoo_user git config --global user.email "webmaster@elico-corp.com" - sudo -i -u $odoo_user git config --global user.name "Elico Corp - Odoo Docker" + sudo -i -u "$odoo_user" git config --global user.email "webmaster@elico-corp.com" + sudo -i -u "$odoo_user" git config --global user.name "Elico Corp - Odoo Docker" # Setup SSH key if [ -a /opt/odoo/ssh/id_rsa ]; then @@ -108,10 +110,12 @@ function _download_addons { fi echo $log_src[`date +%F.%H:%M:%S`]' Downloading additional addons...' - sudo -i -u $odoo_user python /opt/odoo/auto_addons/addons.py $FETCH_OCA_DEPENDENCIES $ADDONS_REPO + sudo -i -u "$odoo_user" python /opt/odoo/auto_addons/addons.py \ + "$FETCH_OCA_DEPENDENCIES" "$ADDONS_REPO" else # No additional addons to download - sudo -i -u $odoo_user bash /opt/odoo/auto_addons/no_addons.sh $odoo_conf_file + # FIXME Should not be an external script (see reason in script header) + bash /app/bin/no_addons.sh "$odoo_user" "$odoo_conf_file" fi } @@ -139,22 +143,22 @@ function start { echo $log_src[`date +%F.%H:%M:%S`]' Running odoo...' set +e - if [ ! -e $1 ]; then - echo $log_src[`date +%F.%H:%M:%S`]' ...with additional args:' $* + if [ ! -e "$1" ]; then + echo $log_src[`date +%F.%H:%M:%S`]' ...with additional args:' "$*" fi - sudo -i -u $odoo_user /usr/bin/python \ - /opt/odoo/sources/odoo/$BINARY_NAME \ - -c $odoo_conf_file \ - $* + sudo -i -u "$odoo_user" /usr/bin/python \ + "/opt/odoo/sources/odoo/$BINARY_NAME" \ + -c "$odoo_conf_file" \ + $* - SERVICE_PID=$! + SERVICE_PID="$!" set -e } # smart shutdown on SIGINT and SIGTERM function on_exit() { - kill -TERM $SERVICE_PID - wait $SERVICE_PID 2> /dev/null + kill -TERM "$SERVICE_PID" + wait "$SERVICE_PID" 2> /dev/null exit 0 } trap on_exit INT TERM @@ -162,6 +166,7 @@ trap on_exit INT TERM echo $log_src[`date +%F.%H:%M:%S`]' Running command...' for arg in "$*" do + # Not protected with `"` in order to pass the arguments $arg done diff --git a/auto_addons/no_addons.sh b/bin/no_addons.sh similarity index 54% rename from auto_addons/no_addons.sh rename to bin/no_addons.sh index 8a4ca07a..ca16885b 100644 --- a/auto_addons/no_addons.sh +++ b/bin/no_addons.sh @@ -9,7 +9,14 @@ # log_src='['${0##*/}']' -grep -P "^addons_path\s*=" $1 -if [ $? -ne 0 ]; then - echo "addons_path = /opt/odoo/sources/odoo/addons" >> $1 -fi \ No newline at end of file +odoo_user="$1" +odoo_conf_file="$2" + +grep -q '^addons_path\s*=' "$odoo_conf_file" +found="$?" + +if [ "$found" -ne 0 ]; then + # Append the parameter (hide tee output to stdout) + echo 'addons_path = /opt/odoo/sources/odoo/addons' | \ + sudo -i -u "$odoo_user" tee -a "$odoo_conf_file" > /dev/null +fi diff --git a/bin/target_user.sh b/bin/target_user.sh index 364ab205..b8706820 100644 --- a/bin/target_user.sh +++ b/bin/target_user.sh @@ -12,31 +12,39 @@ odoo_user='odoo' # Check if there's a target user to run Odoo if [ "$TARGET_UID" ]; then + # Name of the target Odoo user + TARGET_USER_NAME='target-odoo-user' + # Check whether target user exists or not - exists=$( getent passwd $TARGET_UID | wc -l ) + exists=$( getent passwd "$TARGET_UID" | wc -l ) # Create target user - if [ $exists == "0" ]; then + if [ "$exists" == "0" ]; then echo $log_src[`date +%F.%H:%M:%S`]' Creating target Odoo user...' - odoo_user='target-odoo-user' - adduser --uid $TARGET_UID --disabled-login --gecos "" --quiet $odoo_user + odoo_user="$TARGET_USER_NAME" + adduser --uid "$TARGET_UID" --disabled-login --gecos "" --quiet \ + "$odoo_user" # Add target user to odoo group so that he can read/write the content # of /opt/odoo - usermod -a -G odoo $odoo_user + usermod -a -G odoo "$odoo_user" else - # Target user already exists, make sure it's odoo - odoo_user_id=$( id -u $odoo_user ) + # Target user already exists in the following cases: + # 1) Mapping with the same UID as odoo, OK + # 2) Target user has already been created (e.g. container has been + # restarted), OK + # 3) Mapping with another existing user (e.g. root, etc.), not OK + odoo_user_id=$( id -u "$odoo_user" ) + target_uid_name=$( getent passwd "$TARGET_UID" | cut -d: -f1 ) - # If the user already exists, check if it's the same as odoo - if [ $TARGET_UID -ne $odoo_user_id ]; then - echo $log_src[`date +%F.%H:%M:%S`]' ERROR: The UID of the target' \ - 'user already exists but it is not the same as the ID of' \ - '`odoo` user' + if [ "$TARGET_UID" -ne "$odoo_user_id" ] && \ + [ "$TARGET_USER_NAME" != "$target_uid_name" ]; then + echo $log_src[`date +%F.%H:%M:%S`]' ERROR: Cannot create target' \ + 'user as target UID already exists.' exit 1 fi fi fi # Return target Odoo user to boot script -echo $odoo_user > /tmp/odoo_user +echo "$odoo_user" > /tmp/odoo_user diff --git a/bin/update_odoo_param.sh b/bin/update_odoo_param.sh index d1a5037e..9bf21573 100644 --- a/bin/update_odoo_param.sh +++ b/bin/update_odoo_param.sh @@ -1,27 +1,28 @@ #!/bin/bash # # FIXME the below code should be in boot but for an unknown reason, the -# instruction `grep -q "^$param\s*=" $odoo_conf_file` fails to run in boot, when it -# works fine here. +# instruction `grep` fails to run in boot, when it works fine here. # Both are bash scripts, but: # - boot is run by Docker as an entrypoint # - target_user.sh is run using bash command # log_src='['${0##*/}']' -odoo_user=$1 -odoo_conf_file=$2 -odoo_param=$3 -val=$4 +odoo_user="$1" +odoo_conf_file="$2" +odoo_param="$3" +val="$4" # Check if the conf already contains that parameter -grep -q "^$odoo_param\s*=" $odoo_conf_file -found=$? +grep -q "^$odoo_param\s*=" "$odoo_conf_file" +found="$?" -if [ $found -eq 0 ]; then +if [ "$found" -eq 0 ]; then # Substitute the value - sudo -i -u $odoo_user sed -i "s/^$odoo_param\s*=.*/$odoo_param = $val/g" $odoo_conf_file + sudo -i -u "$odoo_user" sed -i \ + "s/^$odoo_param\s*=.*/$odoo_param = $val/g" "$odoo_conf_file" else # Append the parameter (hide tee output to stdout) - echo "$odoo_param = $val" | sudo -i -u $odoo_user tee -a $odoo_conf_file > /dev/null + echo "$odoo_param = $val" | \ + sudo -i -u "$odoo_user" tee -a "$odoo_conf_file" > /dev/null fi