Skip to content

Commit ffe6b6a

Browse files
committed
Disallow Process and Task for 'root' user at runtime
* Allow 'root' user in droplet docker execution metadata via dockerfile for staging because user may be subsequently overridden on Process or Task model * Enforce that 'root' user is not used at runtime by task_action and desired_lrp builders
1 parent 3cb5850 commit ffe6b6a

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

lib/cloud_controller/diego/docker/lifecycle_protocol.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,18 @@ def staging_action_builder(config, staging_details)
2222
end
2323

2424
def task_action_builder(config, task)
25+
if task.run_action_user == 'root' && !Config.config.get(:allow_process_root_user)
26+
raise ::CloudController::Errors::ApiError.new_from_details('RunnerError', "'root' user not permitted.")
27+
end
28+
2529
TaskActionBuilder.new(config, task, { droplet_path: task.droplet.docker_receipt_image })
2630
end
2731

2832
def desired_lrp_builder(config, process)
33+
if process.run_action_user == 'root' && !Config.config.get(:allow_process_root_user)
34+
raise ::CloudController::Errors::ApiError.new_from_details('RunnerError', "'root' user not permitted.")
35+
end
36+
2937
DesiredLrpBuilder.new(config, builder_opts(process))
3038
end
3139

spec/unit/lib/cloud_controller/diego/docker/lifecycle_protocol_spec.rb

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,34 @@ module Docker
118118
end
119119
end
120120
end
121+
122+
context 'when root user not allowed' do
123+
before do
124+
TestConfig.override(allow_process_root_user: false)
125+
end
126+
127+
context 'and the process does not set a user' do
128+
let(:app) { AppModel.make(:docker, { droplet: }) }
129+
let(:process) { ProcessModel.make(:docker, { app: }) }
130+
131+
context 'and the droplet docker execution metadata sets the root user' do
132+
let(:droplet_execution_metadata) { '{"entrypoint":["/image-entrypoint.sh"],"user":"root"}' }
133+
let(:droplet) do
134+
DropletModel.make(:docker, {
135+
state: DropletModel::STAGED_STATE,
136+
docker_receipt_image: 'the-image',
137+
execution_metadata: droplet_execution_metadata
138+
})
139+
end
140+
141+
it 'raises an error' do
142+
expect do
143+
lifecycle_protocol.desired_lrp_builder(config, process)
144+
end.to raise_error(::CloudController::Errors::ApiError, /'root' user not permitted/)
145+
end
146+
end
147+
end
148+
end
121149
end
122150

123151
describe '#task_action_builder' do
@@ -138,6 +166,34 @@ module Docker
138166
)
139167
lifecycle_protocol.task_action_builder(config, task)
140168
end
169+
170+
context 'when root user not allowed' do
171+
before do
172+
TestConfig.override(allow_process_root_user: false)
173+
end
174+
175+
context 'and the task does not set a user' do
176+
let(:app) { AppModel.make(:docker, { droplet: }) }
177+
let(:task) { TaskModel.make(:docker, { droplet:, app: }) }
178+
179+
context 'and the droplet docker execution metadata sets the root user' do
180+
let(:droplet_execution_metadata) { '{"entrypoint":["/image-entrypoint.sh"],"user":"root"}' }
181+
let(:droplet) do
182+
DropletModel.make(:docker, {
183+
state: DropletModel::STAGED_STATE,
184+
docker_receipt_image: 'the-image',
185+
execution_metadata: droplet_execution_metadata
186+
})
187+
end
188+
189+
it 'raises an error' do
190+
expect do
191+
lifecycle_protocol.task_action_builder(config, task)
192+
end.to raise_error(::CloudController::Errors::ApiError, /'root' user not permitted/)
193+
end
194+
end
195+
end
196+
end
141197
end
142198
end
143199
end

0 commit comments

Comments
 (0)