From 505d6566d88ab873b2304792b7e99943a0c48f24 Mon Sep 17 00:00:00 2001 From: Alexander Lutay Date: Fri, 23 Nov 2018 12:27:21 +0100 Subject: [PATCH] TT#47373 Ensure 'restore-permissions' always executed at the end of ngcpcfg Unfortunately git doesn't track POSIX file permissions, which cause perms drop on some git commands like 'git stash/pull/reset', etc. We must be sure 'restore-permissions' always executed at the end of 'ngcpcfg'. Also we must be sure we update .ngcpcfg_perms whenever we start 'ngcpcfg', otherwise we might loose not-yet committed changes in .ngcpcfg_perms. Example during the upgrade mr7.0->mr7.1: 1) JFYI, ngcpcfg mr7.1+ copies perms from source tt2 file to the destination config 2) on mr7.0->mr7.1, ngcp-upgrade installs new package ngcp-templates-pro package with new perms on tt2 files (which are not committed by apt as /etc/ngcp-config is not covered by 'etckeeper', it is by design). 3) later ngcp-upgrade executes 'ngcpcfg build' to build some config. 4) on PRO/Carrier 'ngcpcfg build' executes 'ngcpcfg pull' first to ensure there is no outstanding changes on shared git repo (has been done on Ops request in MT#15803). 5) 'ngcpcfg pull' does 'git stash/pop' before pulling which effectively reset new perms which came from package in step 1 (as git doesn't track perms on files, by design). Summary/fix: whenever we stash something we should ensure perms are stored as well, which means we need to generate new .ngcpcfg_perms and store it in stash together with all the rest local changes. Change-Id: I5292d4433a39ff2751874d63083f093f19b9cfe2 --- functions/main | 4 +-- sbin/ngcpcfg | 90 ++++++++++++++++++++++++++++++++++---------------- 2 files changed, 63 insertions(+), 31 deletions(-) diff --git a/functions/main b/functions/main index cbddd314..1bdc085d 100644 --- a/functions/main +++ b/functions/main @@ -65,8 +65,8 @@ hook_setup() { fi if ! [ -d "$target_directory" ] ; then - log_error "Hook target directory $target_directory not a directory. Exiting." - exit 1 + log_error "Hook target directory $target_directory not a directory. Creating it." + mkdir -p "$target_directory" fi for hook in "${HOOKS}"/* ; do diff --git a/sbin/ngcpcfg b/sbin/ngcpcfg index cd794cda..115beee2 100755 --- a/sbin/ngcpcfg +++ b/sbin/ngcpcfg @@ -5,37 +5,32 @@ set -e set -u -if [ "$UID" -ne 0 ] ; then - printf "Error: ngcpcfg requires root permissions. Exiting.\n" >&2 - exit 1 -fi - -# Notify subprocesses we are running. -export NGCPCFG_RUNNING=1 - -# support for testsuite -FUNCTIONS="${FUNCTIONS:-/usr/share/ngcp-ngcpcfg/functions/}" -SCRIPTS="${SCRIPTS:-/usr/share/ngcp-ngcpcfg/scripts/}" - -if ! [ -r "${FUNCTIONS}/main" ] ; then - printf "Error: %s/main could not be read. Exiting.\n" "${FUNCTIONS}" >&2 - exit 1 -fi +# helper functions -if [[ "${1:-}" == "decrypt" ]] ; then - # do NOT source ${FUNCTIONS}/main but just provide - # the part we need for executing ngcpcfg itself - log_debug() { - if [ -n "${DEBUG:-}" ] ; then - logger -t ngcpcfg -- "Debug: $*" - echo ; echo "DEBUG: $*" ; echo # newlines to avoid messup with cmdline output - fi - } -else - . "${FUNCTIONS}"/main -fi +ngcpcfg_update_perms() { + # Ensure that existing hooks are up2date. + hook_setup "${NGCPCTL_MAIN}/.git/hooks" + + # Must be the first command in every 'ngcpcfg' call as git resets POSIX permissions! + log_debug 'Generate new .ngcpcfg_perms' + if [ -x "${NGCPCTL_MAIN}/.git/hooks/pre-commit" ] ; then + "${NGCPCTL_MAIN}/.git/hooks/pre-commit" + else + log_error "Missing pre-commit hook in '${NGCPCTL_MAIN}/.git/hooks/pre-commit', cannot store permissions, aborting to prevent damage" + exit 1 + fi +} -# helper functions +ngcpcfg_restore_perms() { + # Must be the last command in every 'ngcpcfg' call as git resets POSIX permissions! + trap '' ERR EXIT + log_debug "Restore permissions from .ngcpcfg_perms as git might reset them" + if [ ! -x "${HELPER}"/restore-permissions ]; then + log_error "Missing helper to restore permissions '${HELPER}/restore-permissions'. Exiting." + exit 1 + fi + "${HELPER}"/restore-permissions "${NGCPCTL_MAIN}" +} action() { ACTION="$1" @@ -103,6 +98,43 @@ version() { printf "ngcpcfg, version %s\n" "${versinfo}" } +# Main code + +if [ "$UID" -ne 0 ] ; then + printf "Error: ngcpcfg requires root permissions. Exiting.\n" >&2 + exit 1 +fi + +# Notify subprocesses we are running. +export NGCPCFG_RUNNING=1 + +# support for testsuite +FUNCTIONS="${FUNCTIONS:-/usr/share/ngcp-ngcpcfg/functions/}" +SCRIPTS="${SCRIPTS:-/usr/share/ngcp-ngcpcfg/scripts/}" +HELPER="${HELPER:-/usr/share/ngcp-ngcpcfg/helper/}" +HOOKS="${HOOKS:-/usr/share/ngcp-ngcpcfg/hooks/}" + +if ! [ -r "${FUNCTIONS}/main" ] ; then + printf "Error: %s/main could not be read. Exiting.\n" "${FUNCTIONS}" >&2 + exit 1 +fi + +if [[ "${1:-}" == "decrypt" ]] ; then + # do NOT source ${FUNCTIONS}/main but just provide + # the part we need for executing ngcpcfg itself + log_debug() { + if [ -n "${DEBUG:-}" ] ; then + logger -t ngcpcfg -- "Debug: $*" + echo ; echo "DEBUG: $*" ; echo # newlines to avoid messup with cmdline output + fi + } +else + . "${FUNCTIONS}"/main +fi + +ngcpcfg_update_perms +trap 'ngcpcfg_restore_perms;' ERR EXIT + case ${1:-} in apply|\ build|\