-
Notifications
You must be signed in to change notification settings - Fork 5k
[Filebeat/Journald] allow to use a chroot when calling journalctl
#48008
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
🤖 GitHub commentsJust comment with:
|
|
The failing test on Windows is unrelated to this PR. The flaky test issue: #48009 |
journalctl
🔍 Preview links for changed docs |
|
Pinging @elastic/elastic-agent-data-plane (Team:Elastic-Agent-Data-Plane) |
AndersonQ
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just a few suggestions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of my concerns are security related, executing whatever happens to be called journalctl in the path as root seems like a not so good idea.
| # Long description; in case the summary is not enough to describe the change | ||
| # this field accommodate a description without length limits. | ||
| # NOTE: This field will be rendered only for breaking-change and known-issue kinds at the moment. | ||
| #description: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| #description: | |
| description: | | |
| Add support in the journald inpur for using chroot when calling | |
| `journalctl`. In a container environment this allows to mount the host | |
| file system into the container and use its `journalctl`, which | |
| prevents any sort of incompatibility between the `journalctl` in the | |
| container image and the host Journald. Allows using the journald input with Wolfi based Docker containers. |
Let's include the context from the PR to help people know why they would want to use this.
| When using the Journald input from a Docker container, make sure that | ||
| either: | ||
| - {applies_to}`stack: ga 9.3.0` [`chroot`](#filebeat-input-journald-chroot), [`journalct_path`](#filebeat-input-journald-journalctl-path) are set, or | ||
| - The `journalctl` binary in the container is compatible with your |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
List the container variants that include journald by default.
| # The absolute path for the `journalctl` binary. If not set Filebeat | ||
| # will look for `journalctl` in `PATH`. When using |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to allow executing whatever thing called journalctl we happen find?
That seems less secure than requiring the absolute path to the binary, as there is only a single file system path that can be exploited now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Especially if we execute journalctl as root, we should narrow the scope of what we will execute as much as possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only reason to just look for journalctl is if the path to it isn't consistent all hosts, where finding it then becomes really annoying.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On an ubuntu24 box I see it as the following which is certainly not hard to find.
ubuntu@ubuntu24:~$ which journalctl
/usr/bin/journalctl
If we think using PATH is necessary we could make it optional and default to off.
| if !errors.Is(err, io.EOF) { | ||
| var logError = false | ||
| var pathError *fs.PathError | ||
| if errors.As(err, &pathError) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why isn't this also handled for stderr?
|
|
||
| jctlCommandMsg := fmt.Sprintf("Journalctl command: %s %s", journalctlPath, strings.Join(args, " ")) | ||
| if chroot != "" { | ||
| jctlCommandMsg = fmt.Sprintf("%s Chroot: %s (command path relative to chroot)", jctlCommandMsg, chroot) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be a bit tidier to use InfoW with command and chroot keys instead of this formatting IMO.
| return nil, nil, fmt.Errorf("provided chroot (%s) is not a directory", config.Chroot) | ||
| } | ||
|
|
||
| fullPath := filepath.Join(config.Chroot, config.JournalctlPath) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may want to verify the ownership of the file, maybe that it is only writable by root so it can't be replaced by something from an arbitrary user, especially if we are going to execute it as root.
Speaking of executing it as a root, if we can execute this as a lower privileged user that would help the security boundary here too.
| ``` | ||
| A folder to be used as chroot when calling `journalctl`. This allows | ||
| Filebeat to call the host's `journalctl` directly. If using this | ||
| option, {{filebeat}} must be run as root and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The wolfi containers are not root by default, you will need examples of how to give the capabilities needed to do this.
You potentially only need CAP_SYS_CHROOT and not all the root capabilities, we should identify what the least privileged way for this to execute is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we can say that you just need CAP_SYS_CHROOT without actually being uid 0 that would help considerably so we are also not executing potentially arbitrary commands as root.
Proposed commit message
Checklist
stresstest.shscript to run them under stress conditions and race detector to verify their stability../changelog/fragmentsusing the changelog tool.## Disruptive User ImpactAuthor's Checklist
How to test this PR locally
Run the tests
Manual testing
1. Create a
filebeat.ymlfilebeat.yml
2. Build a staicaly linked Filebeat binary
3. Create a Dockerfile and build a test image
Dockerfile
4. Run the container
You should see in the logs the
journalctlstarting:{ "@timestamp": "2025-12-10T17:10:04.317Z", "ecs.version": "1.6.0", "id": "journald-input-id", "input_id": "journald-input-id", "input_source": "LOCAL_SYSTEM_JOURNAL", "log.level": "info", "log.logger": "input.journald.reader.journalctl-runner", "log.origin": { "file.line": 152, "file.name": "journalctl/journalctl.go", "function": "github.com/elastic/beats/v7/filebeat/input/journald/pkg/journalctl.NewFactory.func1" }, "message": "Journalctl command: journalctl --utc --output=json --no-pager --all --follow --no-tail --boot all", "path": "LOCAL_SYSTEM_JOURNAL", "service.name": "filebeat" } { "@timestamp": "2025-12-10T17:10:04.317Z", "ecs.version": "1.6.0", "id": "journald-input-id", "input_id": "journald-input-id", "input_source": "LOCAL_SYSTEM_JOURNAL", "log.level": "info", "log.logger": "input.journald.reader.journalctl-runner", "log.origin": { "file.line": 158, "file.name": "journalctl/journalctl.go", "function": "github.com/elastic/beats/v7/filebeat/input/journald/pkg/journalctl.NewFactory.func1" }, "message": "journalctl started with PID 23", "path": "LOCAL_SYSTEM_JOURNAL", "service.name": "filebeat" }You can also see the number events published in the metrics that are logged every 5s.
If you want to see the events, remove the discard output and uncomment
the console output in
filebeat.yml, then rebuild the docker imageand run it again.
Related issues
journalctlfrom the host, thus eliminating version issues #47323## Use cases## Screenshots## Logs