diff --git a/History.md b/History.md index 8067a8e12e..d319d221b3 100644 --- a/History.md +++ b/History.md @@ -10,6 +10,7 @@ * Increases maximum URI path length from 2048 to 8196 bytes (#2167) * Force shutdown responses can be overridden by using the `lowlevel_error_handler` config (#2203) * Faster phased restart and worker timeout (#2121) + * New configuration option to set state file permissions (#2238) * Deprecations, Removals and Breaking API Changes * `Puma.stats` now returns a Hash instead of a JSON string (#2086) diff --git a/lib/puma/dsl.rb b/lib/puma/dsl.rb index 41e03a1a7e..7fb82ed7b3 100644 --- a/lib/puma/dsl.rb +++ b/lib/puma/dsl.rb @@ -399,6 +399,14 @@ def state_path(path) @options[:state] = path.to_s end + # Use +permission+ to restrict permissions for the state file. + # + # @example + # state_permission 0600 + def state_permission(permission) + @options[:state_permission] = permission + end + # How many worker processes to run. Typically this is set to # the number of available cores. # diff --git a/lib/puma/launcher.rb b/lib/puma/launcher.rb index 241546b36d..0c4e1dd304 100644 --- a/lib/puma/launcher.rb +++ b/lib/puma/launcher.rb @@ -102,6 +102,7 @@ def write_state write_pid path = @options[:state] + permission = @options[:state_permission] return unless path require 'puma/state_file' @@ -111,7 +112,7 @@ def write_state sf.control_url = @options[:control_url] sf.control_auth_token = @options[:control_auth_token] - sf.save path + sf.save path, permission end # Delete the configured pidfile diff --git a/lib/puma/state_file.rb b/lib/puma/state_file.rb index e49f7e5a74..6aa8fad4d6 100644 --- a/lib/puma/state_file.rb +++ b/lib/puma/state_file.rb @@ -8,8 +8,11 @@ def initialize @options = {} end - def save(path) - File.write path, YAML.dump(@options) + def save(path, permission = nil) + File.open(path, "w") do |file| + file.chmod(permission) if permission + file.write(YAML.dump(@options)) + end end def load(path) diff --git a/test/test_launcher.rb b/test/test_launcher.rb index 130ef847a3..53505c3100 100644 --- a/test/test_launcher.rb +++ b/test/test_launcher.rb @@ -79,6 +79,57 @@ def test_pid_file File.unlink tmp_path end + def test_state_permission_0640 + tmp_file = Tempfile.new("puma-test") + tmp_path = tmp_file.path + tmp_file.close! + tmp_permission = 0640 + + conf = Puma::Configuration.new do |c| + c.state_path tmp_path + c.state_permission tmp_permission + end + + launcher(conf).write_state + + assert File.stat(tmp_path).mode.to_s(8)[-4..-1], tmp_permission + ensure + File.unlink tmp_path + end + + def test_state_permission_nil + tmp_file = Tempfile.new("puma-test") + tmp_path = tmp_file.path + tmp_file.close! + + conf = Puma::Configuration.new do |c| + c.state_path tmp_path + c.state_permission nil + end + + launcher(conf).write_state + + assert File.exist?(tmp_path) + ensure + File.unlink tmp_path + end + + def test_no_state_permission + tmp_file = Tempfile.new("puma-test") + tmp_path = tmp_file.path + tmp_file.close! + + conf = Puma::Configuration.new do |c| + c.state_path tmp_path + end + + launcher(conf).write_state + + assert File.exist?(tmp_path) + ensure + File.unlink tmp_path + end + def test_puma_stats conf = Puma::Configuration.new do |c| c.app -> {[200, {}, ['']]}