diff --git a/jobs/cc_deployment_updater/templates/post-start.sh.erb b/jobs/cc_deployment_updater/templates/post-start.sh.erb index 62a4228d5b..277e3b5c55 100644 --- a/jobs/cc_deployment_updater/templates/post-start.sh.erb +++ b/jobs/cc_deployment_updater/templates/post-start.sh.erb @@ -2,13 +2,15 @@ set -ex +source /var/vcap/packages/capi_utils/privdrop_utils.sh + function fix_bundler_home_permissions { BUNDLER_DIR1=/tmp/bundler BUNDLER_DIR2=/var/vcap/data/cc_deployment_updater/tmp/bundler - chpst -u vcap:vcap mkdir -p $BUNDLER_DIR1 $BUNDLER_DIR2 + run_as_vcap mkdir -p $BUNDLER_DIR1 $BUNDLER_DIR2 chown vcap:vcap -R $BUNDLER_DIR1 $BUNDLER_DIR2 - chpst -u vcap:vcap chmod -R go-w $BUNDLER_DIR1 $BUNDLER_DIR2 - chpst -u vcap:vcap chmod -R +t $BUNDLER_DIR1 $BUNDLER_DIR2 + run_as_vcap chmod -R go-w $BUNDLER_DIR1 $BUNDLER_DIR2 + run_as_vcap chmod -R +t $BUNDLER_DIR1 $BUNDLER_DIR2 } fix_bundler_home_permissions diff --git a/jobs/cc_deployment_updater/templates/pre-start.sh.erb b/jobs/cc_deployment_updater/templates/pre-start.sh.erb index 0718c0623b..7f235b40ab 100644 --- a/jobs/cc_deployment_updater/templates/pre-start.sh.erb +++ b/jobs/cc_deployment_updater/templates/pre-start.sh.erb @@ -3,6 +3,7 @@ set -ex source /var/vcap/packages/capi_utils/output_utils.sh +source /var/vcap/packages/capi_utils/privdrop_utils.sh write_output_with_datetime SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")" @@ -19,8 +20,8 @@ function setup_directories { chown -R vcap:vcap "$LOG_DIR" BUNDLER_DIR=/var/vcap/data/cc_deployment_updater/tmp/bundler - chpst -u vcap:vcap bash -c "mkdir -p $BUNDLER_DIR" - chpst -u vcap:vcap bash -c "chmod -R go-w $BUNDLER_DIR" + run_as_vcap bash -c "mkdir -p $BUNDLER_DIR" + run_as_vcap bash -c "chmod -R go-w $BUNDLER_DIR" } function main { diff --git a/jobs/cloud_controller_clock/templates/post-start.sh.erb b/jobs/cloud_controller_clock/templates/post-start.sh.erb index 13e21d744e..ebf44cf680 100644 --- a/jobs/cloud_controller_clock/templates/post-start.sh.erb +++ b/jobs/cloud_controller_clock/templates/post-start.sh.erb @@ -2,13 +2,15 @@ set -ex +source /var/vcap/packages/capi_utils/privdrop_utils.sh + function fix_bundler_home_permissions { BUNDLER_DIR1=/tmp/bundler BUNDLER_DIR2=/var/vcap/data/cloud_controller_clock/tmp/bundler - chpst -u vcap:vcap mkdir -p $BUNDLER_DIR1 $BUNDLER_DIR2 + run_as_vcap mkdir -p $BUNDLER_DIR1 $BUNDLER_DIR2 chown vcap:vcap -R $BUNDLER_DIR1 $BUNDLER_DIR2 - chpst -u vcap:vcap chmod -R go-w $BUNDLER_DIR1 $BUNDLER_DIR2 - chpst -u vcap:vcap chmod -R +t $BUNDLER_DIR1 $BUNDLER_DIR2 + run_as_vcap chmod -R go-w $BUNDLER_DIR1 $BUNDLER_DIR2 + run_as_vcap chmod -R +t $BUNDLER_DIR1 $BUNDLER_DIR2 } fix_bundler_home_permissions diff --git a/jobs/cloud_controller_clock/templates/pre-start.sh.erb b/jobs/cloud_controller_clock/templates/pre-start.sh.erb index d905457740..79c9f530fe 100644 --- a/jobs/cloud_controller_clock/templates/pre-start.sh.erb +++ b/jobs/cloud_controller_clock/templates/pre-start.sh.erb @@ -2,12 +2,14 @@ set -ex +source /var/vcap/packages/capi_utils/privdrop_utils.sh + mkdir -p "/var/vcap/data/cloud_controller_clock/tmp" chown vcap:vcap "/var/vcap/data/cloud_controller_clock/tmp" BUNDLER_DIR=/var/vcap/data/cloud_controller_clock/tmp/bundler -chpst -u vcap:vcap mkdir -p $BUNDLER_DIR -chpst -u vcap:vcap chmod -R go-w $BUNDLER_DIR +run_as_vcap mkdir -p $BUNDLER_DIR +run_as_vcap chmod -R go-w $BUNDLER_DIR SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")" source "${SCRIPT_DIR}/ruby_version.sh" diff --git a/jobs/cloud_controller_ng/templates/perform_blobstore_benchmarks.erb b/jobs/cloud_controller_ng/templates/perform_blobstore_benchmarks.erb index 3e3f91408b..0c49e7b347 100644 --- a/jobs/cloud_controller_ng/templates/perform_blobstore_benchmarks.erb +++ b/jobs/cloud_controller_ng/templates/perform_blobstore_benchmarks.erb @@ -2,6 +2,7 @@ set -e source /var/vcap/jobs/cloud_controller_ng/bin/ruby_version.sh +source /var/vcap/packages/capi_utils/privdrop_utils.sh CC_JOB_DIR="/var/vcap/jobs/cloud_controller_ng" CC_PACKAGE_DIR="/var/vcap/packages/cloud_controller_ng" @@ -12,7 +13,7 @@ export BUNDLE_GEMFILE="${CC_PACKAGE_DIR}/cloud_controller_ng/Gemfile" function perform_blobstore_benchmarks { echo "Performing blobstore benchmarks" pushd "${CC_PACKAGE_DIR}/cloud_controller_ng" > /dev/null - chpst -u vcap:vcap bundle exec rake benchmarks:perform_blobstore_benchmark + run_as_vcap bundle exec rake benchmarks:perform_blobstore_benchmark popd > /dev/null } diff --git a/jobs/cloud_controller_ng/templates/post-start.sh.erb b/jobs/cloud_controller_ng/templates/post-start.sh.erb index c7d64367a4..1e514bf0a1 100644 --- a/jobs/cloud_controller_ng/templates/post-start.sh.erb +++ b/jobs/cloud_controller_ng/templates/post-start.sh.erb @@ -33,22 +33,23 @@ export BUNDLE_GEMFILE="${CC_PACKAGE_DIR}/cloud_controller_ng/Gemfile" source "${CC_JOB_DIR}/bin/ruby_version.sh" source /var/vcap/packages/capi_utils/output_utils.sh source /var/vcap/packages/capi_utils/monit_utils.sh +source /var/vcap/packages/capi_utils/privdrop_utils.sh write_output_with_datetime function fix_bundler_home_permissions { BUNDLER_DIR1=/tmp/bundler BUNDLER_DIR2=/var/vcap/data/cloud_controller_ng/tmp/bundler - chpst -u vcap:vcap mkdir -p $BUNDLER_DIR1 $BUNDLER_DIR2 + run_as_vcap mkdir -p $BUNDLER_DIR1 $BUNDLER_DIR2 chown vcap:vcap -R $BUNDLER_DIR1 $BUNDLER_DIR2 - chpst -u vcap:vcap chmod -R go-w $BUNDLER_DIR1 $BUNDLER_DIR2 - chpst -u vcap:vcap chmod -R +t $BUNDLER_DIR1 $BUNDLER_DIR2 + run_as_vcap chmod -R go-w $BUNDLER_DIR1 $BUNDLER_DIR2 + run_as_vcap chmod -R +t $BUNDLER_DIR1 $BUNDLER_DIR2 } function install_buildpacks { <% if spec.bootstrap %> pushd "${CC_PACKAGE_DIR}/cloud_controller_ng" > /dev/null - chpst -u vcap:vcap bundle exec rake buildpacks:install + run_as_vcap bundle exec rake buildpacks:install if [[ $? -ne 0 ]]; then echo "Buildpacks installation failed" diff --git a/jobs/cloud_controller_ng/templates/pre-start.sh.erb b/jobs/cloud_controller_ng/templates/pre-start.sh.erb index b87fddc00b..446f195450 100644 --- a/jobs/cloud_controller_ng/templates/pre-start.sh.erb +++ b/jobs/cloud_controller_ng/templates/pre-start.sh.erb @@ -4,6 +4,7 @@ set -ex export LANG="en_US.UTF-8" source /var/vcap/packages/capi_utils/output_utils.sh +source /var/vcap/packages/capi_utils/privdrop_utils.sh write_output_with_datetime CC_JOB_DIR="/var/vcap/jobs/cloud_controller_ng" @@ -14,8 +15,8 @@ export CLOUD_CONTROLLER_NG_CONFIG="${CONFIG_DIR}/cloud_controller_ng.yml" # DB migrations, seeding and encryption-key validation run here in pre-start # (outside bpm) and open a ccdb connection. Disable MySQL TLS peer # verification when no ccdb.ca_cert is set. See the config/bpm.yml template - # for the rationale. chpst preserves this exported env for the migrate/seed/ - # validate scripts. + # for the rationale. run_as_vcap preserves this exported env for the + # migrate/seed/validate scripts. ca_cert_configured = false if_p("ccdb.ca_cert") { |ca_cert| ca_cert_configured = !ca_cert.to_s.strip.empty? } if p("ccdb.db_scheme") == "mysql" && !ca_cert_configured @@ -74,8 +75,8 @@ function setup_api_directories { BUNDLER_DIR1=/tmp/bundler BUNDLER_DIR2=/var/vcap/data/cloud_controller_ng/tmp/bundler - chpst -u vcap:vcap mkdir -p $BUNDLER_DIR1 $BUNDLER_DIR2 - chpst -u vcap:vcap chmod -R go-w $BUNDLER_DIR1 $BUNDLER_DIR2 + run_as_vcap mkdir -p $BUNDLER_DIR1 $BUNDLER_DIR2 + run_as_vcap chmod -R go-w $BUNDLER_DIR1 $BUNDLER_DIR2 # Configure the core file location <% if p("cc.core_file_pattern") %> @@ -97,19 +98,19 @@ function setup_directories { function perform_migration { pushd "${CC_PACKAGE_DIR}/cloud_controller_ng" > /dev/null - chpst -u vcap:vcap "${SCRIPT_DIR}/migrate_db" + run_as_vcap "${SCRIPT_DIR}/migrate_db" popd > /dev/null } function seed_db { pushd "${CC_PACKAGE_DIR}/cloud_controller_ng" > /dev/null - chpst -u vcap:vcap "${SCRIPT_DIR}/seed_db" + run_as_vcap "${SCRIPT_DIR}/seed_db" popd > /dev/null } function validate_encryption_keys { pushd "${CC_PACKAGE_DIR}/cloud_controller_ng" > /dev/null - chpst -u vcap:vcap "${SCRIPT_DIR}/validate_encryption_keys" + run_as_vcap "${SCRIPT_DIR}/validate_encryption_keys" popd > /dev/null } @@ -130,7 +131,7 @@ function start_bosh_dns_or_consul { function stack_check() { pushd "${CC_PACKAGE_DIR}/cloud_controller_ng" > /dev/null - chpst -u vcap:vcap "${SCRIPT_DIR}/stack_check" + run_as_vcap "${SCRIPT_DIR}/stack_check" popd > /dev/null } @@ -140,7 +141,7 @@ function start_consul_agent { # If consul is already running, start exits 1 set +e /var/vcap/jobs/consul_agent/bin/pre-start - chpst -u vcap:vcap /var/vcap/jobs/consul_agent/bin/agent_ctl start &> /dev/null + run_as_vcap /var/vcap/jobs/consul_agent/bin/agent_ctl start &> /dev/null set -e fi } diff --git a/jobs/cloud_controller_worker/templates/post-start.sh.erb b/jobs/cloud_controller_worker/templates/post-start.sh.erb index 3905980e3d..3c11f6aeb4 100644 --- a/jobs/cloud_controller_worker/templates/post-start.sh.erb +++ b/jobs/cloud_controller_worker/templates/post-start.sh.erb @@ -2,13 +2,15 @@ set -ex +source /var/vcap/packages/capi_utils/privdrop_utils.sh + function fix_bundler_home_permissions { BUNDLER_DIR1=/tmp/bundler BUNDLER_DIR2="<%= p("cc.directories.tmpdir") %>/bundler" - chpst -u vcap:vcap mkdir -p $BUNDLER_DIR1 $BUNDLER_DIR2 + run_as_vcap mkdir -p $BUNDLER_DIR1 $BUNDLER_DIR2 chown vcap:vcap -R $BUNDLER_DIR1 $BUNDLER_DIR2 - chpst -u vcap:vcap chmod -R go-w $BUNDLER_DIR1 $BUNDLER_DIR2 - chpst -u vcap:vcap chmod -R +t $BUNDLER_DIR1 $BUNDLER_DIR2 + run_as_vcap chmod -R go-w $BUNDLER_DIR1 $BUNDLER_DIR2 + run_as_vcap chmod -R +t $BUNDLER_DIR1 $BUNDLER_DIR2 } fix_bundler_home_permissions diff --git a/jobs/cloud_controller_worker/templates/pre-start.sh.erb b/jobs/cloud_controller_worker/templates/pre-start.sh.erb index 5ccb36d9f4..06a5ff663b 100644 --- a/jobs/cloud_controller_worker/templates/pre-start.sh.erb +++ b/jobs/cloud_controller_worker/templates/pre-start.sh.erb @@ -3,6 +3,7 @@ set -ex source /var/vcap/packages/capi_utils/output_utils.sh +source /var/vcap/packages/capi_utils/privdrop_utils.sh write_output_with_datetime @@ -21,8 +22,8 @@ function setup_directories { chown vcap:vcap "<%= p("cc.directories.tmpdir") %>" BUNDLER_DIR="<%= p("cc.directories.tmpdir") %>/bundler" - chpst -u vcap:vcap mkdir -p $BUNDLER_DIR - chpst -u vcap:vcap chmod -R go-w $BUNDLER_DIR + run_as_vcap mkdir -p $BUNDLER_DIR + run_as_vcap chmod -R go-w $BUNDLER_DIR } function main { diff --git a/packages/capi_utils/spec b/packages/capi_utils/spec index c1a8e4ee43..3d50388473 100644 --- a/packages/capi_utils/spec +++ b/packages/capi_utils/spec @@ -6,3 +6,4 @@ files: - capi_utils/pid_utils.sh - capi_utils/output_utils.sh - capi_utils/monit_utils.sh +- capi_utils/privdrop_utils.sh diff --git a/src/capi_utils/privdrop_utils.sh b/src/capi_utils/privdrop_utils.sh new file mode 100644 index 0000000000..41ceca556f --- /dev/null +++ b/src/capi_utils/privdrop_utils.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +# run_as_vcap +# +# Exec-style replacement for `chpst -u vcap:vcap "$@"`. +function run_as_vcap() { + setpriv --reuid=vcap --regid=vcap --clear-groups --no-new-privs -- "$@" +} diff --git a/src/capi_utils/privdrop_utils_test.bats b/src/capi_utils/privdrop_utils_test.bats new file mode 100644 index 0000000000..6451149ec9 --- /dev/null +++ b/src/capi_utils/privdrop_utils_test.bats @@ -0,0 +1,30 @@ +#!/usr/bin/env bats + +setup() { + source ./privdrop_utils.sh +} + +@test "run_as_vcap runs the given command as the vcap user" { + run run_as_vcap id -un + [ "$status" -eq 0 ] + [ "$output" = "vcap" ] +} + +@test "run_as_vcap runs the given command as the vcap group" { + run run_as_vcap id -gn + [ "$status" -eq 0 ] + [ "$output" = "vcap" ] +} + +@test "run_as_vcap preserves multiple arguments without re-quoting" { + run run_as_vcap echo one two three + [ "$status" -eq 0 ] + [ "$output" = "one two three" ] +} + +@test "run_as_vcap preserves exported environment variables" { + export PRIVDROP_TEST_VAR="some_value" + run run_as_vcap sh -c 'echo "$PRIVDROP_TEST_VAR"' + [ "$status" -eq 0 ] + [ "$output" = "some_value" ] +}