diff --git a/Dockerfile b/Dockerfile index 27df589..31f2f75 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,11 @@ -FROM ruby:2.6.5-buster AS development +FROM ruby:2.6.5-alpine AS development WORKDIR /usr/src ENV HOME=/usr/src PATH=/usr/src/bin:$PATH +RUN apk add --no-cache su-exec alpine-sdk + COPY Gemfile Gemfile.lock on_container.gemspec /usr/src/ COPY lib/on_container/version.rb /usr/src/lib/on_container/ @@ -15,7 +17,7 @@ ARG DEVELOPER_USERNAME=you ENV DEVELOPER_UID=${DEVELOPER_UID} -RUN useradd -r -M -u ${DEVELOPER_UID} -d /usr/src -c "Developer User,,," ${DEVELOPER_USERNAME} +RUN adduser -D -H -u ${DEVELOPER_UID} -h /usr/src -g "Developer User,,," ${DEVELOPER_USERNAME} FROM development AS testing diff --git a/Gemfile b/Gemfile index c02d70d..0608195 100644 --- a/Gemfile +++ b/Gemfile @@ -5,3 +5,6 @@ gemspec gem "rake", "~> 12.0" gem "rspec", "~> 3.0" + +gem 'byebug' +gem 'pry-byebug' \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock index 695f479..ede15b3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,7 +6,16 @@ PATH GEM remote: https://rubygems.org/ specs: + byebug (11.1.1) + coderay (1.1.2) diff-lcs (1.3) + method_source (0.9.2) + pry (0.12.2) + coderay (~> 1.1.0) + method_source (~> 0.9.0) + pry-byebug (3.8.0) + byebug (~> 11.0) + pry (~> 0.10) rake (12.3.3) rspec (3.9.0) rspec-core (~> 3.9.0) @@ -27,7 +36,9 @@ PLATFORMS DEPENDENCIES bundler (~> 1.17) + byebug on_container! + pry-byebug rake (~> 12.0) rspec (~> 3.0) diff --git a/lib/on_container/step_down_from_root.rb b/lib/on_container/step_down_from_root.rb index 96ad73c..4f88512 100644 --- a/lib/on_container/step_down_from_root.rb +++ b/lib/on_container/step_down_from_root.rb @@ -26,11 +26,11 @@ def root_user? end def developer_uid? - developer_uid_as_integer > 0 + developer_uid > 0 end def developer_uid - @developer_uid ||= ENV['DEVELOPER_UID'].to_i + @developer_uid ||= ENV.fetch('DEVELOPER_UID', '').to_i end protected @@ -38,7 +38,7 @@ def developer_uid def switch_to_developer_user target_user_name = target_user.name puts "Switching from 'root' user to '#{target_user_name}'..." - exec 'su-exec', target_user_name, $0, *$* + Kernel.exec 'su-exec', target_user_name, $0, *$* end def warn_no_developer_uid diff --git a/spec/step_down_from_root_spec.rb b/spec/step_down_from_root_spec.rb new file mode 100644 index 0000000..adf8814 --- /dev/null +++ b/spec/step_down_from_root_spec.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +require 'on_container/step_down_from_root' + +RSpec.describe OnContainer::StepDownFromRoot do + let(:root_user) do + instance_double "struct Etc::Passwd", + name: 'root', + passwd: 'x', + uid: 0, + gid: 0, + gecos: 'root', + dir: '/root', + shell: '/bin/bash' + end + + let(:developer_user) do + instance_double "struct Etc::Passwd", + name: 'developer', + passwd: 'x', + uid: 1000, + gid: 1000, + gecos: 'Developer User,,,', + dir: '/usr/src', + shell: '/bin/bash' + end + + let(:example_current_user) { root_user } + let(:example_target_user) { developer_user } + let(:example_developer_uid) { '1000' } + + before do + allow(ENV).to receive(:fetch).with('DEVELOPER_UID', '') { example_developer_uid } + allow(Etc).to receive(:getpwuid) { example_current_user } + allow(Etc).to receive(:getpwuid).with(example_target_user.uid) { example_target_user } + allow(Kernel).to receive(:exec).with('su-exec', example_target_user.name, any_args) + end + + describe '#perform' do + it 'changes to the target user' do + subject.perform + expect(Kernel).to have_received(:exec).with 'su-exec', example_target_user.name, any_args + end + + context 'without a developer uid' do + let(:example_developer_uid) { '' } + + example 'does not change the current user' do + subject.perform + expect(Kernel).not_to have_received(:exec) + end + end + + context 'when not as root' do + let(:example_current_user) { developer_user } + + example 'does not change the current user' do + subject.perform + expect(Kernel).not_to have_received(:exec) + end + end + end +end