Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions docs/configuration/system.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# System Configuration

The `<system>` directive in Fluentd's configuration controls process-wide settings.

## Configuration Parameters

### `umask`

The `umask` parameter sets the process umask (file permission mask). This affects the default permissions of files created by Fluentd.

```
<system>
umask 0022 # Allows r/w for owner, read for group/others
</system>
```

You can specify the umask value in octal format (e.g., `0022`, `0027`, `0077`). The meaning of umask values:
- `0022`: Allow read/write for owner, read for group/others
- `0027`: Allow read/write for owner, read for group, no access for others
- `0077`: Allow read/write for owner only, no access for group/others

Note: If not specified, Fluentd will use the system default umask.

### Examples

Restrictive umask (owner only):
```
<system>
umask 0077
</system>
```

Standard umask:
```
<system>
umask 0022
</system>
```

Group readable:
```
<system>
umask 0027
</system>
```
26 changes: 25 additions & 1 deletion lib/fluent/system_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class SystemConfig
:file_permission, :dir_permission, :counter_server, :counter_client,
:strict_config_value, :enable_msgpack_time_support, :disable_shared_socket,
:metrics, :enable_input_metrics, :enable_size_metrics, :enable_jit, :source_only_buffer,
:config_include_dir
:config_include_dir, :umask
]

config_param :workers, :integer, default: 1
Expand Down Expand Up @@ -61,6 +61,7 @@ class SystemConfig
v.to_i(8)
end
config_param :config_include_dir, default: Fluent::DEFAULT_CONFIG_INCLUDE_DIR
config_param :umask, :string, default: nil # Keep as string for validation in apply()
config_section :log, required: false, init: true, multi: false do
config_param :path, :string, default: nil
config_param :format, :enum, list: [:text, :json], default: :text
Expand Down Expand Up @@ -151,6 +152,29 @@ def initialize(conf=nil, strict_config_value=false)
configure(conf, strict_config_value)
end

def apply(log)
return unless @umask

begin
# Parse as octal integer and validate
new_mask = Integer(@umask, 8)

if new_mask < 0 || new_mask > 0o777
log.warn "umask value out of range (must be between 0000 and 0777): #{@umask}"
return
end

# Only apply if valid
old_mask = File.umask(new_mask)
log.info "System umask changed from #{sprintf('0%03o', old_mask)} to #{sprintf('0%03o', new_mask)}"
rescue ArgumentError
log.warn "Invalid umask value '#{@umask}' - must be octal format (e.g., 0022)"
rescue => e
log.error "Failed to set umask", error: e
log.error_backtrace
end
end

def configure(conf, strict_config_value=false)
strict = strict_config_value
if !strict && conf && conf.has_key?("strict_config_value")
Expand Down
74 changes: 74 additions & 0 deletions test/config/test_system_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,81 @@ def parse_text(text)
'enable_input_metrics' => ['enable_input_metrics', false],
'enable_size_metrics' => ['enable_size_metrics', true],
'enable_jit' => ['enable_jit', true],
'umask' => ['umask', '0022'],
)
sub_test_case "umask configuration" do
setup do
@original_umask = File.umask
end

teardown do
File.umask(@original_umask) # Restore original umask
end

test 'valid umask is applied' do
conf = parse_text(<<-EOS)
<system>
umask 0022
</system>
EOS

log = Fluent::Test::TestLogger.new
sc = Fluent::SystemConfig.new(conf)
sc.apply(log)

assert_equal '0022', sc.umask
assert_equal 0o022, File.umask
assert_true log.logs.any? { |msg| msg.include?('System umask changed') }
end

test 'invalid umask format logs warning' do
conf = parse_text(<<-EOS)
<system>
umask invalid
</system>
EOS

log = Fluent::Test::TestLogger.new
sc = Fluent::SystemConfig.new(conf)
old_mask = File.umask
sc.apply(log)

assert_equal old_mask, File.umask # Should not change
assert_true log.logs.any? { |msg| msg.include?('Invalid umask value') }
end

test 'out of range umask logs warning' do
conf = parse_text(<<-EOS)
<system>
umask 0888
</system>
EOS

log = Fluent::Test::TestLogger.new
sc = Fluent::SystemConfig.new(conf)
old_mask = File.umask
sc.apply(log)

assert_equal old_mask, File.umask # Should not change
assert_true log.logs.any? { |msg| msg.include?('out of range') }
end

test 'nil umask is ignored' do
conf = parse_text(<<-EOS)
<system>
</system>
EOS

log = Fluent::Test::TestLogger.new
sc = Fluent::SystemConfig.new(conf)
old_mask = File.umask
sc.apply(log)

assert_nil sc.umask
assert_equal old_mask, File.umask
end
end

test "accepts parameters" do |(k, v)|
conf = parse_text(<<-EOS)
<system>
Expand Down