diff --git a/functions b/functions index 5bc8456281..4dc20e7f23 100644 --- a/functions +++ b/functions @@ -15,6 +15,7 @@ FUNC_DIR=$(cd $(dirname "${BASH_SOURCE:-$0}") && pwd) source ${FUNC_DIR}/functions-common source ${FUNC_DIR}/inc/ini-config source ${FUNC_DIR}/inc/python +source ${FUNC_DIR}/inc/rootwrap # Save trace setting XTRACE=$(set +o | grep xtrace) diff --git a/inc/rootwrap b/inc/rootwrap new file mode 100644 index 0000000000..bac8e1e86c --- /dev/null +++ b/inc/rootwrap @@ -0,0 +1,77 @@ +#!/bin/bash +# +# **inc/rootwrap** - Rootwrap functions +# +# Handle rootwrap's foibles + +# Uses: ``STACK_USER`` +# Defines: ``SUDO_SECURE_PATH_FILE`` + +# Save trace setting +INC_ROOT_TRACE=$(set +o | grep xtrace) +set +o xtrace + +# Accumulate all additions to sudo's ``secure_path`` in one file read last +# so they all work in a venv configuration +SUDO_SECURE_PATH_FILE=${SUDO_SECURE_PATH_FILE:-/etc/sudoers.d/zz-secure-path} + +# Add a directory to the common sudo ``secure_path`` +# add_sudo_secure_path dir +function add_sudo_secure_path { + local dir=$1 + local line + + # This is pretty simplistic for now - assume only the first line is used + if [[ -r SUDO_SECURE_PATH_FILE ]]; then + line=$(head -1 $SUDO_SECURE_PATH_FILE) + else + line="Defaults:$STACK_USER secure_path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/sbin:/usr/bin:/bin" + fi + + # Only add ``dir`` if it is not already present + if [[ $line =~ $dir ]]; then + echo "${line}:$dir" | sudo tee $SUDO_SECURE_PATH_FILE + sudo chmod 400 $SUDO_SECURE_PATH_FILE + sudo chown root:root $SUDO_SECURE_PATH_FILE + fi +} + +# Configure rootwrap +# Make a load of assumptions otherwise we'll have 6 arguments +# configure_rootwrap project bin conf-src-dir +function configure_rootwrap { + local project=$1 # xx + local rootwrap_bin=$2 # /opt/stack/xx.venv/bin/xx-rootwrap + local rootwrap_conf_src_dir=$3 # /opt/stack/xx/etc/xx + + # Start fresh with rootwrap filters + sudo rm -rf /etc/${project}/rootwrap.d + sudo install -d -o root -g root -m 755 /etc/${project}/rootwrap.d + sudo install -o root -g root -m 644 $rootwrap_conf_src_dir/rootwrap.d/*.filters /etc/${project}/rootwrap.d + + # Set up rootwrap.conf, pointing to /etc/*/rootwrap.d + sudo install -o root -g root -m 644 $rootwrap_conf_src_dir/rootwrap.conf /etc/${project}/rootwrap.conf + sudo sed -e "s:^filters_path=.*$:filters_path=/etc/${project}/rootwrap.d:" -i /etc/${project}/rootwrap.conf + + # Specify rootwrap.conf as first parameter to rootwrap + rootwrap_sudo_cmd="$rootwrap_bin /etc/${project}/rootwrap.conf *" + + # Set up the rootwrap sudoers + local tempfile=$(mktemp) + echo "$STACK_USER ALL=(root) NOPASSWD: $rootwrap_sudo_cmd" >$tempfile + chmod 0440 $tempfile + sudo chown root:root $tempfile + sudo mv $tempfile /etc/sudoers.d/${project}-rootwrap + + # Add bin dir to sudo's secure_path because rootwrap is being called + # without a path because BROKEN. + add_sudo_secure_path $(dirname $rootwrap_bin) +} + + +# Restore xtrace +$INC_ROOT_TRACE + +# Local variables: +# mode: shell-script +# End: diff --git a/lib/cinder b/lib/cinder index 27fd692292..de41bc5f79 100644 --- a/lib/cinder +++ b/lib/cinder @@ -171,42 +171,6 @@ function cleanup_cinder { fi } -# Deploy new rootwrap filters files and configure sudo -# configure_cinder_rootwrap() - configure Cinder's rootwrap -function configure_cinder_rootwrap { - local cinder_rootwrap=$CINDER_BIN_DIR/cinder-rootwrap - - # Wipe any existing rootwrap.d files first - if [[ -d $CINDER_CONF_DIR/rootwrap.d ]]; then - sudo rm -rf $CINDER_CONF_DIR/rootwrap.d - fi - - # Deploy filters to /etc/cinder/rootwrap.d - sudo install -d -o root -g root -m 755 $CINDER_CONF_DIR/rootwrap.d - sudo install -o root -g root -m 644 $CINDER_DIR/etc/cinder/rootwrap.d/*.filters $CINDER_CONF_DIR/rootwrap.d - - # Set up rootwrap.conf, pointing to /etc/cinder/rootwrap.d - sudo install -o root -g root -m 644 $CINDER_DIR/etc/cinder/rootwrap.conf $CINDER_CONF_DIR - sudo sed -e "s:^filters_path=.*$:filters_path=$CINDER_CONF_DIR/rootwrap.d:" -i $CINDER_CONF_DIR/rootwrap.conf - - # Specify rootwrap.conf as first parameter to rootwrap - ROOTWRAP_CSUDOER_CMD="$cinder_rootwrap $CINDER_CONF_DIR/rootwrap.conf *" - - # Set up the rootwrap sudoers for cinder - local tempfile=`mktemp` - echo "Defaults:$STACK_USER secure_path=$CINDER_BIN_DIR:/sbin:/usr/sbin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin" >$tempfile - echo "$STACK_USER ALL=(root) NOPASSWD: $ROOTWRAP_CSUDOER_CMD" >>$tempfile - chmod 0440 $tempfile - sudo chown root:root $tempfile - sudo mv $tempfile /etc/sudoers.d/cinder-rootwrap - - # So rootwrap and PATH are broken beyond belief. WTF relies on a SECURE operation - # to blindly follow PATH??? We learned that was a bad idea in the 80's! - # So to fix this in a venv, we must exploit the very hole we want to close by dropping - # a copy of the venv rootwrap binary into /usr/local/bin. - #sudo cp -p $cinder_rootwrap /usr/local/bin -} - # configure_cinder() - Set config files, create data dirs, etc function configure_cinder { sudo install -d -o $STACK_USER -m 755 $CINDER_CONF_DIR @@ -215,7 +179,7 @@ function configure_cinder { rm -f $CINDER_CONF - configure_cinder_rootwrap + configure_rootwrap cinder $CINDER_BIN_DIR/cinder-rootwrap $CINDER_DIR/etc/cinder cp $CINDER_DIR/etc/cinder/api-paste.ini $CINDER_API_PASTE_INI diff --git a/lib/nova b/lib/nova index 385da4e44b..807dfceeae 100644 --- a/lib/nova +++ b/lib/nova @@ -223,42 +223,6 @@ function cleanup_nova { #fi } -# Deploy new rootwrap filters files and configure sudo -# configure_nova_rootwrap() - configure Nova's rootwrap -function configure_nova_rootwrap { - nova_rootwrap=$NOVA_BIN_DIR/nova-rootwrap - - # Wipe any existing rootwrap.d files first - if [[ -d $NOVA_CONF_DIR/rootwrap.d ]]; then - sudo rm -rf $NOVA_CONF_DIR/rootwrap.d - fi - - # Deploy filters to /etc/nova/rootwrap.d - sudo install -d -o root -g root -m 755 $NOVA_CONF_DIR/rootwrap.d - sudo install -o root -g root -m 644 $NOVA_DIR/etc/nova/rootwrap.d/*.filters $NOVA_CONF_DIR/rootwrap.d - - # Set up rootwrap.conf, pointing to /etc/nova/rootwrap.d - sudo install -o root -g root -m 644 $NOVA_DIR/etc/nova/rootwrap.conf $NOVA_CONF_DIR - sudo sed -e "s:^filters_path=.*$:filters_path=$NOVA_CONF_DIR/rootwrap.d:" -i $NOVA_CONF_DIR/rootwrap.conf - - # Specify rootwrap.conf as first parameter to nova-rootwrap - local rootwrap_sudoer_cmd="$nova_rootwrap $NOVA_CONF_DIR/rootwrap.conf *" - - # Set up the rootwrap sudoers for nova - local tempfile=`mktemp` - echo "Defaults:$STACK_USER secure_path=$NOVA_BIN_DIR:/sbin:/usr/sbin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin" >$tempfile - echo "$STACK_USER ALL=(root) NOPASSWD: $rootwrap_sudoer_cmd" >>$tempfile - chmod 0440 $tempfile - sudo chown root:root $tempfile - sudo mv $tempfile /etc/sudoers.d/nova-rootwrap - - # So rootwrap and PATH are broken beyond belief. WTF relies on a SECURE operation - # to blindly follow PATH??? We learned that was a bad idea in the 80's! - # So to fix this in a venv, we must exploit the very hole we want to close by dropping - # a copy of the venv rootwrap binary into /usr/local/bin. - #sudo cp -p $nova_rootwrap /usr/local/bin -} - # configure_nova() - Set config files, create data dirs, etc function configure_nova { # Put config files in ``/etc/nova`` for everyone to find @@ -266,7 +230,7 @@ function configure_nova { install_default_policy nova - configure_nova_rootwrap + configure_rootwrap nova $NOVA_BIN_DIR/nova-rootwrap $NOVA_DIR/etc/nova if [[ "$ENABLED_SERVICES" =~ "n-api" ]]; then # Get the sample configuration file in place