fluentd 1.19.4 → 1.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/AGENTS.md +46 -0
- data/CHANGELOG.md +75 -0
- data/GithubWorkflow.md +1 -1
- data/MAINTAINERS.md +2 -2
- data/README.md +3 -2
- data/Rakefile +2 -1
- data/SECURITY.md +26 -1
- data/lib/fluent/command/cat.rb +2 -2
- data/lib/fluent/compat/exec_util.rb +20 -5
- data/lib/fluent/config/literal_parser.rb +4 -3
- data/lib/fluent/config/yaml_parser/loader.rb +12 -1
- data/lib/fluent/config/yaml_parser/parser.rb +14 -13
- data/lib/fluent/event.rb +37 -0
- data/lib/fluent/load.rb +0 -1
- data/lib/fluent/log.rb +2 -2
- data/lib/fluent/plugin/buf_file.rb +2 -2
- data/lib/fluent/plugin/buf_file_single.rb +6 -2
- data/lib/fluent/plugin/buffer/file_chunk.rb +23 -10
- data/lib/fluent/plugin/buffer/file_single_chunk.rb +23 -10
- data/lib/fluent/plugin/buffer.rb +102 -36
- data/lib/fluent/plugin/formatter_out_file.rb +3 -4
- data/lib/fluent/plugin/in_exec.rb +6 -4
- data/lib/fluent/plugin/in_forward.rb +39 -29
- data/lib/fluent/plugin/in_object_space.rb +2 -2
- data/lib/fluent/plugin/in_syslog.rb +2 -2
- data/lib/fluent/plugin/in_tail/compatibility.rb +111 -0
- data/lib/fluent/plugin/in_tail/dir_watcher.rb +713 -0
- data/lib/fluent/plugin/in_tail/group_watch.rb +13 -13
- data/lib/fluent/plugin/in_tail/io_handler.rb +391 -0
- data/lib/fluent/plugin/in_tail/line_feeder.rb +230 -0
- data/lib/fluent/plugin/in_tail/stat_watcher.rb +52 -0
- data/lib/fluent/plugin/in_tail/tail_watcher.rb +276 -0
- data/lib/fluent/plugin/in_tail/worker_pool.rb +298 -0
- data/lib/fluent/plugin/in_tail.rb +324 -815
- data/lib/fluent/plugin/in_unix.rb +5 -3
- data/lib/fluent/plugin/out_exec_filter.rb +2 -2
- data/lib/fluent/plugin/out_file.rb +10 -4
- data/lib/fluent/plugin/out_forward.rb +8 -0
- data/lib/fluent/plugin/out_http.rb +0 -10
- data/lib/fluent/plugin/output.rb +49 -19
- data/lib/fluent/plugin/parser_csv.rb +7 -2
- data/lib/fluent/plugin/parser_json.rb +20 -12
- data/lib/fluent/plugin/parser_ltsv.rb +2 -4
- data/lib/fluent/plugin/parser_msgpack.rb +7 -6
- data/lib/fluent/plugin/parser_syslog.rb +52 -5
- data/lib/fluent/plugin/parser_tsv.rb +6 -1
- data/lib/fluent/plugin_helper/http_server/server.rb +29 -13
- data/lib/fluent/plugin_helper/http_server.rb +2 -1
- data/lib/fluent/root_agent.rb +1 -1
- data/lib/fluent/supervisor.rb +24 -5
- data/lib/fluent/system_config.rb +5 -2
- data/lib/fluent/time.rb +8 -7
- data/lib/fluent/version.rb +1 -1
- data/templates/new_gem/.gitignore +8 -0
- metadata +39 -16
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fa67a9199a9bcd73feb7dc286f4a1cb8347bd4d01d515561ceaf151671a9116e
|
|
4
|
+
data.tar.gz: ec7afdf8eea191d4badfb95361c3b41cfb35785c06dbacf3d0c0f65b89d734da
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1e900ecc699cb16836f2467105c09d51917446f7d7a885cbd66512e1fb8d24a2807a5b3ff7eeedec969e3e9dde7f8bc2cff40624e5c7d3d45d2bb5e4b536a75e
|
|
7
|
+
data.tar.gz: 8c258d373881b49dc90bc8e93ade34d46fb79b768203e05889a4ac3196361c97d185fa8b6c8006c9d985df65da20eabf1df62a802a3e365d27ba2f5cc345c1be
|
data/AGENTS.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Guidance for coding agents
|
|
2
|
+
|
|
3
|
+
This file is for AI coding agents (Claude Code, Cursor, Codex, Copilot, ...) working in this repository. Humans should read CONTRIBUTING.md.
|
|
4
|
+
|
|
5
|
+
## Primary sources
|
|
6
|
+
|
|
7
|
+
- Official documentation: https://docs.fluentd.org/
|
|
8
|
+
- Index for agents: https://docs.fluentd.org/llms.txt
|
|
9
|
+
- Every page is also available as Markdown by appending `.md` to its URL, e.g. https://docs.fluentd.org/configuration/config-file.md
|
|
10
|
+
- Read the documentation before answering questions about configuration syntax or plugin parameters. Do not invent parameters; check the plugin's page or its `config_param` declarations in this repository.
|
|
11
|
+
- Configuration has two formats.
|
|
12
|
+
- Classic: https://docs.fluentd.org/configuration/config-file.md
|
|
13
|
+
- YAML: https://docs.fluentd.org/configuration/config-file-yaml.md
|
|
14
|
+
|
|
15
|
+
## Repository layout
|
|
16
|
+
|
|
17
|
+
- `lib/fluent/plugin/` – bundled plugins (`in_*.rb`, `out_*.rb`, `filter_*.rb`, `parser_*.rb`, `formatter_*.rb`, `buf_*.rb`, `storage_*.rb`, `sd_*.rb`, `metrics_*.rb`)
|
|
18
|
+
- `lib/fluent/plugin_helper/` – plugin helpers
|
|
19
|
+
- `lib/fluent/config/` – configuration parsers (classic and YAML)
|
|
20
|
+
- `test/` – tests written with test-unit
|
|
21
|
+
- `templates/new_gem/` – files generated by `fluent-plugin-generate`
|
|
22
|
+
|
|
23
|
+
## Developing
|
|
24
|
+
|
|
25
|
+
- Install: `bundle install`
|
|
26
|
+
- Run all tests: `bundle exec rake test`
|
|
27
|
+
- Run one file: `bundle exec ruby -Ilib -Itest test/plugin/test_in_tail.rb`
|
|
28
|
+
- Plugin API reference: https://docs.fluentd.org/plugin-development/README.md
|
|
29
|
+
- Plugin helper reference: https://docs.fluentd.org/plugin-helper-overview/README.md
|
|
30
|
+
- Test helpers for plugins: https://docs.fluentd.org/plugin-development/plugin-test-code.md
|
|
31
|
+
|
|
32
|
+
## Conventions
|
|
33
|
+
|
|
34
|
+
- Follow CONTRIBUTING.md. Commits need a DCO sign-off (`git commit -s`).
|
|
35
|
+
- Keep changes minimal and focused; do not reformat unrelated code.
|
|
36
|
+
- Add or update tests under `test/` for behavior changes.
|
|
37
|
+
- Do not add runtime dependencies without discussion.
|
|
38
|
+
- Match the surrounding code style; there is no autoformatter to run. CI runs `rubocop`, but only the Security and Performance cops are enabled.
|
|
39
|
+
- Fluentd runs on Linux, macOS and Windows. CI tests `ubuntu-latest`, `macos-latest`, `windows-latest` and `windows-11-arm`. Assume your change must work on Windows.
|
|
40
|
+
|
|
41
|
+
## Issues and pull requests
|
|
42
|
+
|
|
43
|
+
- Pull requests follow `.github/PULL_REQUEST_TEMPLATE.md`. Keep its headings, including `Docs Changes` and `Release Note`, and write `Fixes #<n>` when an issue exists.
|
|
44
|
+
- Blank issues are disabled. Use `.github/ISSUE_TEMPLATE/bug_report.yml` or `.github/ISSUE_TEMPLATE/feature_request.yml` and answer every required field.
|
|
45
|
+
- Questions belong in [Discussions](https://github.com/fluent/fluentd/discussions), not in issues.
|
|
46
|
+
- Note that `gh pr create --body` and `gh issue create --body` skip the template. Pass `--template`, or reproduce the template's sections in the body you supply.
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,78 @@
|
|
|
1
|
+
# v1.20
|
|
2
|
+
|
|
3
|
+
## Release v1.20.0 - 2026/10/23
|
|
4
|
+
|
|
5
|
+
### Enhancement
|
|
6
|
+
|
|
7
|
+
* Replace Yajl with built-in JSON for simple cases https://github.com/fluent/fluentd/pull/5090
|
|
8
|
+
* out_forward: add `send_keepalive_packet` option to enable TCP keepalive (SO_KEEPALIVE) https://github.com/fluent/fluentd/pull/5262
|
|
9
|
+
* in_exec: add `command_timeout` option to limit child process execution time https://github.com/fluent/fluentd/pull/5320
|
|
10
|
+
* Replace Yajl with JSON for handling JSON stream https://github.com/fluent/fluentd/pull/5383
|
|
11
|
+
* When an input stream ends in the middle of a JSON document, Fluentd now logs a warning and discards the incomplete tail instead of raising `ParseError`.
|
|
12
|
+
* system_config: add `umask` option to `<system>` directive https://github.com/fluent/fluentd/pull/5390
|
|
13
|
+
* parser_syslog: accept a space after RFC3164 priority https://github.com/fluent/fluentd/pull/5449
|
|
14
|
+
* in_tail: add opt-in `enable_dir_watcher` and `dir_watcher_limit` to discover new files earlier by watching directories https://github.com/fluent/fluentd/pull/5528
|
|
15
|
+
* in_tail: add opt-in worker-thread parsing via `num_threads` to offload parsing from the event loop https://github.com/fluent/fluentd/pull/5529
|
|
16
|
+
* The default `num_threads 1` keeps the previous synchronous behavior.
|
|
17
|
+
* In worker mode, `monitor_agent` also reports `worker_pending_batch_count`, `worker_pending_bytes` and `worker_parse_error_count`.
|
|
18
|
+
* buffer: add `evacuate_limit_size` to keep evacuated chunks from filling the disk https://github.com/fluent/fluentd/pull/5473
|
|
19
|
+
* This option sets an approximate limit on the total size of the chunk files evacuated when the retry limit is reached, including the ones evacuated before. Chunks that do not fit are purged without being evacuated.
|
|
20
|
+
* The default `nil` keeps the previous behavior. Set `0` to disable evacuation.
|
|
21
|
+
* in_forward: accept metadata on encapsulated timestamps sent by Fluent Bit v5.0.5 or later https://github.com/fluent/fluentd/pull/5411
|
|
22
|
+
* Enable Ruby JIT by default https://github.com/fluent/fluentd/pull/5464
|
|
23
|
+
* The system configuration `enable_jit` now defaults to `true`.
|
|
24
|
+
* JIT increases memory usage of each worker process. Set `enable_jit false` in the `<system>` section to restore the previous behavior.
|
|
25
|
+
* This has no effect on Windows because YJIT is not supported there.
|
|
26
|
+
* fluent-plugin-generate: add .gitignore file https://github.com/fluent/fluentd/pull/5370
|
|
27
|
+
* Performance improvements
|
|
28
|
+
* https://github.com/fluent/fluentd/pull/5281
|
|
29
|
+
* https://github.com/fluent/fluentd/pull/5288
|
|
30
|
+
* https://github.com/fluent/fluentd/pull/5289
|
|
31
|
+
* https://github.com/fluent/fluentd/pull/5344
|
|
32
|
+
* https://github.com/fluent/fluentd/pull/5353
|
|
33
|
+
* https://github.com/fluent/fluentd/pull/5354
|
|
34
|
+
* https://github.com/fluent/fluentd/pull/5357
|
|
35
|
+
* https://github.com/fluent/fluentd/pull/5287
|
|
36
|
+
* https://github.com/fluent/fluentd/pull/5278
|
|
37
|
+
* https://github.com/fluent/fluentd/pull/5567
|
|
38
|
+
|
|
39
|
+
### Bug Fix
|
|
40
|
+
|
|
41
|
+
* http_server helper: Fix IPv6 bind address support in URI construction https://github.com/fluent/fluentd/pull/5239
|
|
42
|
+
* Fixed `URI::InvalidURIError` when binding to IPv6 addresses (e.g., `::`, `::1`)
|
|
43
|
+
* IPv6 addresses are now properly bracketed in URIs per RFC 3986 (e.g., `http://[::]:24231`)
|
|
44
|
+
* Handles pre-bracketed addresses correctly to avoid double-bracketing
|
|
45
|
+
* Affects all plugins using http_server helper with IPv6 bind addresses
|
|
46
|
+
* out_file: create symlinks for all chunks sharing the latest timekey https://github.com/fluent/fluentd/pull/5476
|
|
47
|
+
* time: fix TimeFormatter returning nil for the Unix epoch https://github.com/fluent/fluentd/pull/5420
|
|
48
|
+
* in_tail: fix log duplication when a rotated file is appended during `rotate_wait` with `follow_inodes` https://github.com/fluent/fluentd/pull/5499
|
|
49
|
+
* in_tail: fix `NameError` raised when flushing buffered lines with `emit_unmatched_lines true` https://github.com/fluent/fluentd/pull/5513
|
|
50
|
+
* in_tail: fix unread lines never being collected when a throttled file is removed from the watch list https://github.com/fluent/fluentd/pull/5515
|
|
51
|
+
* in_tail: fix shutdown errors and timeouts caused by an ongoing watcher refresh https://github.com/fluent/fluentd/pull/5530
|
|
52
|
+
* in_tail: fix closed stream error when file rotation overlaps with shutdown https://github.com/fluent/fluentd/pull/5551
|
|
53
|
+
* in_tail: use a monotonic clock for multiline flush timers so that they are not affected by wall-clock adjustments https://github.com/fluent/fluentd/pull/5542
|
|
54
|
+
* buffer: fix a race that could make the buffer `stage_size` gauge transiently negative while a write and a chunk enqueue overlap https://github.com/fluent/fluentd/pull/5481
|
|
55
|
+
* buffer: fix an enqueued unstaged file chunk being re-staged and flushed twice, which caused `closed stream` / `ENOENT` errors and leaked buffer size gauges https://github.com/fluent/fluentd/pull/5517
|
|
56
|
+
* parser_msgpack: fix leftover data from one parse call leaking into the next https://github.com/fluent/fluentd/pull/5553
|
|
57
|
+
* http_server helper: fix HTTP endpoints never recovering after a bind failure https://github.com/fluent/fluentd/pull/5523
|
|
58
|
+
* The plugin now fails to start, and the worker is restarted until the port is available.
|
|
59
|
+
* root_agent: fix `emit_records` and `emit_size` never counted for inputs with `@label` https://github.com/fluent/fluentd/pull/5526
|
|
60
|
+
* supervisor: fix graceful config reload failing for YAML configuration https://github.com/fluent/fluentd/pull/5522
|
|
61
|
+
* It also fixes `<<: !include` of a file that contains a mapping.
|
|
62
|
+
|
|
63
|
+
### Misc
|
|
64
|
+
|
|
65
|
+
* Drop Ruby 3.2 support https://github.com/fluent/fluentd/pull/5465
|
|
66
|
+
* out_http: remove the Net::HTTP extra_chain_cert monkey patch https://github.com/fluent/fluentd/pull/5484
|
|
67
|
+
* gem: add aarch64-mingw-ucrt gem https://github.com/fluent/fluentd/pull/5400
|
|
68
|
+
* gem: add json gem (>= 2.21) as runtime dependency and remove Refinements workaround https://github.com/fluent/fluentd/pull/5429
|
|
69
|
+
* in_tail: internal refactoring
|
|
70
|
+
* https://github.com/fluent/fluentd/pull/5518
|
|
71
|
+
* https://github.com/fluent/fluentd/pull/5520
|
|
72
|
+
* https://github.com/fluent/fluentd/pull/5521
|
|
73
|
+
* https://github.com/fluent/fluentd/pull/5527
|
|
74
|
+
* https://github.com/fluent/fluentd/pull/5554
|
|
75
|
+
|
|
1
76
|
# v1.19
|
|
2
77
|
|
|
3
78
|
## Release v1.19.4 - 2026/09/28
|
data/GithubWorkflow.md
CHANGED
|
@@ -9,7 +9,7 @@ Table of Contents
|
|
|
9
9
|
* [Create a Pull Request](#create-a-pull-request)
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
The [fluentd](https://github.com/fluent/fluentd.git) code is hosted on Github (https://github.com/fluent/fluentd). The repository is called `upstream`. Contributors will develop and commit their changes in a clone of upstream repository. Then contributors push their change to their forked repository (`origin`) and create a Pull Request (PR), the PR will be merged to `upstream` repository if it meets
|
|
12
|
+
The [fluentd](https://github.com/fluent/fluentd.git) code is hosted on Github (https://github.com/fluent/fluentd). The repository is called `upstream`. Contributors will develop and commit their changes in a clone of upstream repository. Then contributors push their change to their forked repository (`origin`) and create a Pull Request (PR), the PR will be merged to `upstream` repository if it meets all the necessary requirements.
|
|
13
13
|
|
|
14
14
|
## Fork a repository
|
|
15
15
|
|
data/MAINTAINERS.md
CHANGED
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
- [Satoshi Tagomori](https://github.com/tagomoris)
|
|
8
8
|
- [Toru Takahashi](https://github.com/toru-takahashi), [Treasure Data](https://www.treasuredata.com/)
|
|
9
9
|
- [Eduardo Silva](https://github.com/edsiper), [Chronosphere](https://chronosphere.io/)
|
|
10
|
-
- [Fujimoto Seiji](https://github.com/
|
|
10
|
+
- [Fujimoto Seiji](https://github.com/fujimotos)
|
|
11
11
|
- [Takuro Ashie](https://github.com/ashie), [ClearCode](https://www.clear-code.com/)
|
|
12
12
|
- [Kentaro Hayashi](https://github.com/kenhys), [ClearCode](https://www.clear-code.com/)
|
|
13
|
-
- [Daijiro Fukuda](https://github.com/daipom)
|
|
13
|
+
- [Daijiro Fukuda](https://github.com/daipom)
|
|
14
14
|
|
|
15
15
|
## Sub Projects: Fluent Bit
|
|
16
16
|
|
data/README.md
CHANGED
|
@@ -5,6 +5,7 @@ Fluentd: Open-Source Log Collector
|
|
|
5
5
|
[](https://github.com/fluent/fluentd/actions/workflows/test-ruby-head.yml)
|
|
6
6
|
[](https://bestpractices.coreinfrastructure.org/projects/1189)
|
|
7
7
|
[](https://scorecard.dev/viewer/?uri=github.com/fluent/fluentd)
|
|
8
|
+
[](https://github.com/fluent/fluentd/actions/workflows/backport.yml)
|
|
8
9
|
|
|
9
10
|
[Fluentd](https://www.fluentd.org/) collects events from various data sources and writes them to files, RDBMS, NoSQL, IaaS, SaaS, Hadoop and so on. Fluentd helps you unify your logging infrastructure (Learn more about the [Unified Logging Layer](https://www.fluentd.org/blog/unified-logging-layer)).
|
|
10
11
|
|
|
@@ -24,11 +25,11 @@ Fluentd: Open-Source Log Collector
|
|
|
24
25
|
### Branch
|
|
25
26
|
|
|
26
27
|
- master: For v1 development.
|
|
27
|
-
- v0.12: For v0.12. This is deprecated version. we already stopped supporting (See https://www.fluentd.org/blog/drop-schedule-announcement-in-2019).
|
|
28
|
+
- v0.12: For v0.12. This is a deprecated version. we already stopped supporting (See https://www.fluentd.org/blog/drop-schedule-announcement-in-2019).
|
|
28
29
|
|
|
29
30
|
### Prerequisites
|
|
30
31
|
|
|
31
|
-
- Ruby 3.
|
|
32
|
+
- Ruby 3.3 or later
|
|
32
33
|
- git
|
|
33
34
|
|
|
34
35
|
`git` should be in `PATH`. On Windows, you can use `Github for Windows` and `GitShell` for easy setup.
|
data/Rakefile
CHANGED
|
@@ -6,6 +6,7 @@ require 'rake/testtask'
|
|
|
6
6
|
require 'rake/clean'
|
|
7
7
|
|
|
8
8
|
require_relative 'tasks/benchmark'
|
|
9
|
+
require_relative 'tasks/backport'
|
|
9
10
|
|
|
10
11
|
task test: [:base_test]
|
|
11
12
|
|
|
@@ -16,7 +17,7 @@ namespace :build do
|
|
|
16
17
|
desc 'Build gems for all platforms'
|
|
17
18
|
task :all do
|
|
18
19
|
Bundler.with_original_env do
|
|
19
|
-
%w[ruby x86-mingw32 x64-mingw32 x64-mingw-ucrt].each do |name|
|
|
20
|
+
%w[ruby x86-mingw32 x64-mingw32 x64-mingw-ucrt aarch64-mingw-ucrt].each do |name|
|
|
20
21
|
ENV['GEM_BUILD_FAKE_PLATFORM'] = name
|
|
21
22
|
Rake::Task["build"].execute
|
|
22
23
|
end
|
data/SECURITY.md
CHANGED
|
@@ -4,10 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
| Version | Supported |
|
|
6
6
|
|-----------|--------------------|
|
|
7
|
+
| 1.20.x | :white_check_mark: |
|
|
7
8
|
| 1.19.x | :white_check_mark: |
|
|
8
9
|
| 1.18.x | :x: |
|
|
9
10
|
| 1.17.x | :x: |
|
|
10
|
-
| 1.16.x | :
|
|
11
|
+
| 1.16.x | :x: |
|
|
11
12
|
| <= 1.15.x | :x: |
|
|
12
13
|
|
|
13
14
|
## Reporting a Vulnerability
|
|
@@ -15,8 +16,32 @@
|
|
|
15
16
|
Please post your vulnerability report from the following page:
|
|
16
17
|
https://github.com/fluent/fluentd/security/advisories
|
|
17
18
|
|
|
19
|
+
> [!CAUTION]
|
|
20
|
+
> In above contact form, we accept about **ONLY** Fluentd's vulnerability, in contrast, **REJECT** your vulnerability report about Fluentd derivative products such as fluent-package, Fluentd container images and Fluentd kubernetes deamonset images and so on. There are appropriate contact forms for every these derivative products. See the following notice.
|
|
21
|
+
|
|
18
22
|
> [!NOTE]
|
|
19
23
|
> If you use fluent-package, please check [fluent-package-builder](https://github.com/fluent/fluent-package-builder/blob/master/SECURITY.md) and report it there.
|
|
20
24
|
|
|
21
25
|
> [!NOTE]
|
|
22
26
|
> If you use a Docker image of Fluentd, please check [Fluentd Docker Image](https://github.com/fluent/fluentd-docker-image/blob/master/SECURITY.md) and report it there.
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
## Out of Scope / Non-Vulnerabilities
|
|
30
|
+
|
|
31
|
+
Before reporting a vulnerability, please check if it falls under the following expected behaviors, design choices, or configuration issues. Reports regarding these items will be closed immediately as **not a bug** or **out of scope**.
|
|
32
|
+
|
|
33
|
+
### 1. `in_debug_agent` and arbitrary code execution (`eval`)
|
|
34
|
+
|
|
35
|
+
* **Description:** The `in_debug_agent` plugin is a developer tool designed specifically for debugging a running Fluentd process via dRuby. It requires explicit activation in the local configuration file and is disabled by default.
|
|
36
|
+
* **Why it is not a vulnerability:** The ability to execute arbitrary Ruby code (`eval`) is **by design**. It functions similarly to `gdbserver`, allowing maintainers to inspect internal process states. It does not introduce a security risk unless an administrator explicitly enables it and exposes the port to an untrusted network, which constitutes a severe misconfiguration rather than a flaw in Fluentd itself.
|
|
37
|
+
|
|
38
|
+
### 2. `record_transformer` with `enable_ruby`
|
|
39
|
+
|
|
40
|
+
* **Description:** The `enable_ruby` option in the `record_transformer` plugin allows administrators to use Ruby expressions within the configuration file to transform log records dynamically.
|
|
41
|
+
* **Why it is not a vulnerability:** Executing the Ruby code block defined in the configuration file is **by design**. It does not allow arbitrary code execution from untrusted log inputs unless the user explicitly writes insecure expressions (e.g., passing untrusted input directly into another dynamic evaluation nested inside the block). If an attacker can modify the local Fluentd configuration file to enable this feature and inject malicious Ruby code, the system is already fully compromised at the OS/infrastructure level (Post-Exploitation). We do not accept RCE reports that rely on the ability to modify the local configuration file.
|
|
42
|
+
|
|
43
|
+
### 3. ReDoS (Regular Expression Denial of Service) reproducible only on Ruby 3.2 or older
|
|
44
|
+
|
|
45
|
+
* **Description:** Potential algorithmic complexity issues in regular expressions that could lead to High CPU usage or Denial of Service on older Ruby runtimes.
|
|
46
|
+
* **Why it is out of scope:** Fluentd officially supports modern Ruby environments. Our primary distribution channels including the official `fluent-package` and official Docker images ship with **Ruby 3.3 or later (e.g., Ruby 3.4)**, which includes built-in, robust mitigation against ReDoS at the language level (such as matching timeouts and engine-level optimizations). We do not accept ReDoS reports that only impact legacy Ruby versions (Ruby 3.2 or older) unless the issue can be demonstrated to cause a practical denial of service on Ruby 3.3+.
|
|
47
|
+
However, if you find inefficient regular expressions, we welcome them as standard bug reports or performance improvement suggestions via regular GitHub Issues rather than security advisories.
|
data/lib/fluent/command/cat.rb
CHANGED
|
@@ -107,7 +107,7 @@ rescue
|
|
|
107
107
|
end
|
|
108
108
|
|
|
109
109
|
require 'socket'
|
|
110
|
-
require '
|
|
110
|
+
require 'json'
|
|
111
111
|
require 'msgpack'
|
|
112
112
|
require 'fluent/ext_monitor_require'
|
|
113
113
|
|
|
@@ -304,7 +304,7 @@ class Writer
|
|
|
304
304
|
end
|
|
305
305
|
|
|
306
306
|
def abort_message(time, record)
|
|
307
|
-
$stdout.puts "!#{time}:#{
|
|
307
|
+
$stdout.puts "!#{time}:#{JSON.generate(record)}"
|
|
308
308
|
end
|
|
309
309
|
end
|
|
310
310
|
|
|
@@ -15,8 +15,9 @@
|
|
|
15
15
|
#
|
|
16
16
|
|
|
17
17
|
require 'msgpack'
|
|
18
|
-
require '
|
|
18
|
+
require 'json'
|
|
19
19
|
|
|
20
|
+
require 'fluent/env'
|
|
20
21
|
require 'fluent/engine'
|
|
21
22
|
require 'fluent/plugin'
|
|
22
23
|
require 'fluent/parser'
|
|
@@ -76,10 +77,24 @@ module Fluent
|
|
|
76
77
|
end
|
|
77
78
|
|
|
78
79
|
class JSONParser < Parser
|
|
80
|
+
BYTES_TO_READ = 8192
|
|
81
|
+
|
|
79
82
|
def call(io)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
parser = JSON::ResumableParser.new(**Fluent::DEFAULT_JSON_PARSE_OPTIONS)
|
|
84
|
+
begin
|
|
85
|
+
chunk = +"".b
|
|
86
|
+
while io.readpartial(BYTES_TO_READ, chunk)
|
|
87
|
+
parser << chunk
|
|
88
|
+
while parser.parse
|
|
89
|
+
@on_message.call(parser.value)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
rescue EOFError
|
|
93
|
+
unless parser.empty?
|
|
94
|
+
$log&.warn "JSON stream ended in the middle of a document; " \
|
|
95
|
+
"discarding incomplete data"
|
|
96
|
+
end
|
|
97
|
+
end
|
|
83
98
|
end
|
|
84
99
|
end
|
|
85
100
|
|
|
@@ -115,7 +130,7 @@ module Fluent
|
|
|
115
130
|
|
|
116
131
|
class JSONFormatter < Formatter
|
|
117
132
|
def call(record, out)
|
|
118
|
-
out <<
|
|
133
|
+
out << JSON.generate(record) << "\n"
|
|
119
134
|
end
|
|
120
135
|
end
|
|
121
136
|
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
require 'stringio'
|
|
18
18
|
|
|
19
19
|
require 'json'
|
|
20
|
-
require 'yajl'
|
|
21
20
|
require 'socket'
|
|
22
21
|
require 'ripper'
|
|
23
22
|
|
|
@@ -236,8 +235,10 @@ EOM
|
|
|
236
235
|
|
|
237
236
|
def scan_json(is_array)
|
|
238
237
|
result = nil
|
|
239
|
-
#
|
|
240
|
-
#
|
|
238
|
+
# scan_json detects the end of a JSON literal by repeatedly attempting
|
|
239
|
+
# to parse the buffer and treating a successful parse as completion.
|
|
240
|
+
# This requires a parser that raises JSON::ParserError for incomplete
|
|
241
|
+
# input like '[1', '{"h"', '{"h":' or '{"h1":1'.
|
|
241
242
|
|
|
242
243
|
buffer = (is_array ? "[" : "{")
|
|
243
244
|
line_buffer = ""
|
|
@@ -71,9 +71,17 @@ module Fluent
|
|
|
71
71
|
else
|
|
72
72
|
pattern = path
|
|
73
73
|
end
|
|
74
|
+
# A single file keeps its own shape; only glob matches are aggregated.
|
|
75
|
+
return load(pattern) if File.file?(pattern)
|
|
76
|
+
|
|
74
77
|
result = []
|
|
75
78
|
Dir.glob(pattern).sort.each do |path|
|
|
76
|
-
|
|
79
|
+
loaded = load(Pathname.new(path))
|
|
80
|
+
if loaded.is_a?(Hash)
|
|
81
|
+
result.push(loaded)
|
|
82
|
+
else
|
|
83
|
+
result.concat(loaded)
|
|
84
|
+
end
|
|
77
85
|
end
|
|
78
86
|
result
|
|
79
87
|
rescue SystemCallError => e
|
|
@@ -93,6 +101,9 @@ module Fluent
|
|
|
93
101
|
|
|
94
102
|
def revive_hash(hash, o)
|
|
95
103
|
super(hash, o).tap do |r|
|
|
104
|
+
if r[SHOVEL].is_a?(Array) && r[SHOVEL].all?(Hash)
|
|
105
|
+
r[SHOVEL] = r[SHOVEL].reverse_each.reduce({}) { |a, e| a.merge!(e) }
|
|
106
|
+
end
|
|
96
107
|
if r[SHOVEL].is_a?(Hash)
|
|
97
108
|
h2 = {}
|
|
98
109
|
r.each do |k, v|
|
|
@@ -106,19 +106,20 @@ module Fluent
|
|
|
106
106
|
|
|
107
107
|
def included_sections_build(config, section_builder, indent: 0)
|
|
108
108
|
config.each_entry do |e|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
109
|
+
e.keys.each do |k|
|
|
110
|
+
cc = e.delete(k)
|
|
111
|
+
case k
|
|
112
|
+
when 'label'
|
|
113
|
+
section_builder.add_section(label_build(cc, indent: indent))
|
|
114
|
+
when 'worker'
|
|
115
|
+
section_builder.add_section(worker_build(cc, indent: indent))
|
|
116
|
+
when 'source'
|
|
117
|
+
section_builder.add_section(source_build(cc, indent: indent))
|
|
118
|
+
when 'filter'
|
|
119
|
+
section_builder.add_section(filter_build(cc, indent: indent))
|
|
120
|
+
when 'match'
|
|
121
|
+
section_builder.add_section(match_build(cc, indent: indent))
|
|
122
|
+
end
|
|
122
123
|
end
|
|
123
124
|
end
|
|
124
125
|
end
|
data/lib/fluent/event.rb
CHANGED
|
@@ -309,6 +309,43 @@ module Fluent
|
|
|
309
309
|
end
|
|
310
310
|
end
|
|
311
311
|
|
|
312
|
+
class MetadataTimeEventStream < EventStream
|
|
313
|
+
def initialize(es)
|
|
314
|
+
@es = es
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def empty?
|
|
318
|
+
@es.empty?
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
def dup
|
|
322
|
+
self.class.new(@es.dup)
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
def size
|
|
326
|
+
@es.size
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
def repeatable?
|
|
330
|
+
@es.repeatable?
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
def slice(index, num)
|
|
334
|
+
self.class.new(@es.slice(index, num))
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
def each(unpacker: nil, &block)
|
|
338
|
+
@es.each(unpacker: unpacker) do |time, record|
|
|
339
|
+
next if record.nil?
|
|
340
|
+
|
|
341
|
+
time = time[0] if time.is_a?(Array)
|
|
342
|
+
time = Fluent::EventTime.now if time.nil? || time.to_i == 0
|
|
343
|
+
block.call(time, record)
|
|
344
|
+
end
|
|
345
|
+
nil
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
|
|
312
349
|
module ChunkMessagePackEventStreamer
|
|
313
350
|
# chunk.extend(ChunkMessagePackEventStreamer)
|
|
314
351
|
# => chunk.each{|time, record| ... }
|
data/lib/fluent/load.rb
CHANGED
data/lib/fluent/log.rb
CHANGED
|
@@ -221,7 +221,7 @@ module Fluent
|
|
|
221
221
|
if wid = get_worker_id(type)
|
|
222
222
|
r['worker_id'] = wid
|
|
223
223
|
end
|
|
224
|
-
|
|
224
|
+
JSON.generate(r)
|
|
225
225
|
}
|
|
226
226
|
end
|
|
227
227
|
|
|
@@ -554,7 +554,7 @@ module Fluent
|
|
|
554
554
|
Thread.current[:last_repeated_stacktrace] = CachedLog.new(backtrace, time) if @suppress_repeated_stacktrace
|
|
555
555
|
end
|
|
556
556
|
|
|
557
|
-
puts
|
|
557
|
+
puts JSON.generate(r)
|
|
558
558
|
end
|
|
559
559
|
|
|
560
560
|
nil
|
|
@@ -174,7 +174,7 @@ module Fluent
|
|
|
174
174
|
when :staged
|
|
175
175
|
# unstaged chunk created at Buffer#write_step_by_step is identified as the staged chunk here because FileChunk#assume_chunk_state checks only the file name.
|
|
176
176
|
# https://github.com/fluent/fluentd/blob/9d113029d4550ce576d8825bfa9612aa3e55bff0/lib/fluent/plugin/buffer.rb#L663
|
|
177
|
-
# This case can happen when fluentd process is killed by signal or other reasons between creating unstaged chunks and
|
|
177
|
+
# This case can happen when fluentd process is killed by signal or other reasons between creating unstaged chunks and enqueueing them (which renames them) in Buffer#write
|
|
178
178
|
# these chunks(unstaged chunks) has shared the same metadata
|
|
179
179
|
# So perform enqueue step again https://github.com/fluent/fluentd/blob/9d113029d4550ce576d8825bfa9612aa3e55bff0/lib/fluent/plugin/buffer.rb#L364
|
|
180
180
|
if chunk_size_full?(chunk) || stage.key?(chunk.metadata)
|
|
@@ -234,7 +234,7 @@ module Fluent
|
|
|
234
234
|
raise ArgumentError, "The chunk must be FileChunk, but it was #{chunk.class}."
|
|
235
235
|
end
|
|
236
236
|
|
|
237
|
-
backup_dir =
|
|
237
|
+
backup_dir = evacuate_dir
|
|
238
238
|
FileUtils.mkdir_p(backup_dir, mode: system_config.dir_permission || Fluent::DEFAULT_DIR_PERMISSION) unless Dir.exist?(backup_dir)
|
|
239
239
|
|
|
240
240
|
FileUtils.copy([chunk.path, chunk.meta_path], backup_dir)
|
|
@@ -193,7 +193,11 @@ module Fluent
|
|
|
193
193
|
|
|
194
194
|
case chunk.state
|
|
195
195
|
when :staged
|
|
196
|
-
stage
|
|
196
|
+
if chunk_size_full?(chunk) || stage.key?(chunk.metadata)
|
|
197
|
+
queue << chunk.enqueued!
|
|
198
|
+
else
|
|
199
|
+
stage[chunk.metadata] = chunk
|
|
200
|
+
end
|
|
197
201
|
when :queued
|
|
198
202
|
queue << chunk
|
|
199
203
|
end
|
|
@@ -246,7 +250,7 @@ module Fluent
|
|
|
246
250
|
raise ArgumentError, "The chunk must be FileSingleChunk, but it was #{chunk.class}."
|
|
247
251
|
end
|
|
248
252
|
|
|
249
|
-
backup_dir =
|
|
253
|
+
backup_dir = evacuate_dir
|
|
250
254
|
FileUtils.mkdir_p(backup_dir, mode: system_config.dir_permission || Fluent::DEFAULT_DIR_PERMISSION) unless Dir.exist?(backup_dir)
|
|
251
255
|
|
|
252
256
|
FileUtils.copy(chunk.path, backup_dir)
|
|
@@ -100,8 +100,14 @@ module Fluent
|
|
|
100
100
|
end
|
|
101
101
|
|
|
102
102
|
def enqueued!
|
|
103
|
-
return unless self.
|
|
103
|
+
return self unless self.writable?
|
|
104
104
|
|
|
105
|
+
super
|
|
106
|
+
rename_to_queued_path
|
|
107
|
+
self
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def rename_to_queued_path
|
|
105
111
|
new_chunk_path = self.class.generate_queued_chunk_path(@path, @unique_id)
|
|
106
112
|
new_meta_path = new_chunk_path + '.meta'
|
|
107
113
|
|
|
@@ -139,9 +145,8 @@ module Fluent
|
|
|
139
145
|
|
|
140
146
|
@path = new_chunk_path
|
|
141
147
|
@meta_path = new_meta_path
|
|
142
|
-
|
|
143
|
-
super
|
|
144
148
|
end
|
|
149
|
+
private :rename_to_queued_path
|
|
145
150
|
|
|
146
151
|
def close
|
|
147
152
|
super
|
|
@@ -266,19 +271,27 @@ module Fluent
|
|
|
266
271
|
|
|
267
272
|
def file_rename(file, old_path, new_path, callback=nil)
|
|
268
273
|
pos = file.pos
|
|
274
|
+
setup = ->(f) {
|
|
275
|
+
f.set_encoding(Encoding::ASCII_8BIT)
|
|
276
|
+
f.sync = true
|
|
277
|
+
f.binmode
|
|
278
|
+
f.pos = pos
|
|
279
|
+
callback.call(f) if callback
|
|
280
|
+
}
|
|
269
281
|
if Fluent.windows?
|
|
270
282
|
file.close
|
|
271
|
-
|
|
272
|
-
|
|
283
|
+
renamed = false
|
|
284
|
+
begin
|
|
285
|
+
File.rename(old_path, new_path)
|
|
286
|
+
renamed = true
|
|
287
|
+
ensure
|
|
288
|
+
setup.call(File.open(renamed ? new_path : old_path, 'rb', @permission))
|
|
289
|
+
end
|
|
273
290
|
else
|
|
274
291
|
File.rename(old_path, new_path)
|
|
275
292
|
file.reopen(new_path, 'rb')
|
|
293
|
+
setup.call(file)
|
|
276
294
|
end
|
|
277
|
-
file.set_encoding(Encoding::ASCII_8BIT)
|
|
278
|
-
file.sync = true
|
|
279
|
-
file.binmode
|
|
280
|
-
file.pos = pos
|
|
281
|
-
callback.call(file) if callback
|
|
282
295
|
end
|
|
283
296
|
|
|
284
297
|
def create_new_chunk(path, perm)
|
|
@@ -93,8 +93,14 @@ module Fluent
|
|
|
93
93
|
end
|
|
94
94
|
|
|
95
95
|
def enqueued!
|
|
96
|
-
return unless self.
|
|
96
|
+
return self unless self.writable?
|
|
97
97
|
|
|
98
|
+
super
|
|
99
|
+
rename_to_queued_path
|
|
100
|
+
self
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def rename_to_queued_path
|
|
98
104
|
new_chunk_path = self.class.generate_queued_chunk_path(@path, @unique_id)
|
|
99
105
|
|
|
100
106
|
begin
|
|
@@ -114,9 +120,8 @@ module Fluent
|
|
|
114
120
|
end
|
|
115
121
|
|
|
116
122
|
@path = new_chunk_path
|
|
117
|
-
|
|
118
|
-
super
|
|
119
123
|
end
|
|
124
|
+
private :rename_to_queued_path
|
|
120
125
|
|
|
121
126
|
def close
|
|
122
127
|
super
|
|
@@ -225,19 +230,27 @@ module Fluent
|
|
|
225
230
|
|
|
226
231
|
def file_rename(file, old_path, new_path, callback = nil)
|
|
227
232
|
pos = file.pos
|
|
233
|
+
setup = ->(f) {
|
|
234
|
+
f.set_encoding(Encoding::ASCII_8BIT)
|
|
235
|
+
f.sync = true
|
|
236
|
+
f.binmode
|
|
237
|
+
f.pos = pos
|
|
238
|
+
callback.call(f) if callback
|
|
239
|
+
}
|
|
228
240
|
if Fluent.windows?
|
|
229
241
|
file.close
|
|
230
|
-
|
|
231
|
-
|
|
242
|
+
renamed = false
|
|
243
|
+
begin
|
|
244
|
+
File.rename(old_path, new_path)
|
|
245
|
+
renamed = true
|
|
246
|
+
ensure
|
|
247
|
+
setup.call(File.open(renamed ? new_path : old_path, 'rb', @permission))
|
|
248
|
+
end
|
|
232
249
|
else
|
|
233
250
|
File.rename(old_path, new_path)
|
|
234
251
|
file.reopen(new_path, 'rb')
|
|
252
|
+
setup.call(file)
|
|
235
253
|
end
|
|
236
|
-
file.set_encoding(Encoding::ASCII_8BIT)
|
|
237
|
-
file.sync = true
|
|
238
|
-
file.binmode
|
|
239
|
-
file.pos = pos
|
|
240
|
-
callback.call(file) if callback
|
|
241
254
|
end
|
|
242
255
|
|
|
243
256
|
ESCAPE_REGEXP = /[^-_.a-zA-Z0-9]/n
|