Skip to content
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

[libbeat] Improve syslog parser/processor error handling #31798

Merged
merged 19 commits into from
Jun 27, 2022

Conversation

taylor-swanson
Copy link
Contributor

@taylor-swanson taylor-swanson commented Jun 1, 2022

What does this PR do?

  • Shifted most of the validation logic to the host language instead of the Ragel parser. This allows for the message to be fully parsed even if there are validation errors with one or more fields.
  • Errors are accumulated as they occur, any fields that have already been parsed and validated will be returned, alongside error.message.
  • Priority field for RFC 3164 messages are now optional, as some syslog providers will omit this part of the header (especially when writing to files).
  • Structured data fields for RFC 5424 messages are processed in a second pass. If the structured data format doesn't fit the RFC, it will be prepended to the message, separated by a space.
  • Structured data now uses map[string]interface{}
  • Update testify to v1.7.1 dependency for assert.ErrorContains support

Why is it important?

These changes make the parser/processor more tolerant of non-RFC compliant syslog messages. Many products/services will introduce changes that slightly deviate from RFC.

Checklist

  • My code follows the style guidelines of this project
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • [ ] I have made corresponding change to the default configuration files
  • I have added tests that prove my fix is effective or that my feature works
  • I have added an entry in CHANGELOG.next.asciidoc or CHANGELOG-developer.next.asciidoc.

How to test this PR locally

Run unit tests in these packages:

libbeat/processors/syslog
libbeat/reader/syslog

Related issues

@taylor-swanson taylor-swanson requested a review from a team June 1, 2022 14:21
@taylor-swanson taylor-swanson self-assigned this Jun 1, 2022
@botelastic botelastic bot added needs_team Indicates that the issue/PR needs a Team:* label and removed needs_team Indicates that the issue/PR needs a Team:* label labels Jun 1, 2022
@elasticmachine
Copy link
Collaborator

elasticmachine commented Jun 1, 2022

💚 Build Succeeded

the below badges are clickable and redirect to their specific view in the CI or DOCS
Pipeline View Test View Changes Artifacts preview preview

Expand to view the summary

Build stats

  • Start Time: 2022-06-27T13:21:02.925+0000

  • Duration: 111 min 53 sec

Test stats 🧪

Test Results
Failed 0
Passed 22380
Skipped 1937
Total 24317

💚 Flaky test report

Tests succeeded.

🤖 GitHub comments

To re-run your PR in the CI, just comment with:

  • /test : Re-trigger the build.

  • /package : Generate the packages and run the E2E tests.

  • /beats-tester : Run the installation tests with beats-tester.

  • run elasticsearch-ci/docs : Re-trigger the docs validation. (use unformatted text in the comment!)

@taylor-swanson
Copy link
Contributor Author

/test

1 similar comment
@taylor-swanson
Copy link
Contributor Author

/test

- Shifted most of the validation logic to the host language instead of
the Ragel parser. This allows for the message to be fully parsed even if
there are validation errors with one or more fields.
- Errors are accumulated as they occur, any fields that have already been
parsed and validated will be returned, alongside error.message.
- Priority field for RFC 3164 messages are now optional, as some
syslog providers will omit this part of the header (especially when writing to files).
- Structured data fields for RFC 5424 messages are processed in a
second pass. If the structured data format doesn't fit the RFC, it will be
prepended to the message, separated by a space.
- Structured data now uses map[string]interface{}
- Update testify to v1.7.1 dependency for assert.ErrorContains support
@mergify
Copy link
Contributor

mergify bot commented Jun 6, 2022

This pull request is now in conflicts. Could you fix it? 🙏
To fixup this pull request, you can check out it locally. See documentation: https://help.github.com/articles/checking-out-pull-requests-locally/

git fetch upstream
git checkout -b syslog-parsing upstream/syslog-parsing
git merge upstream/main
git push upstream syslog-parsing

@taylor-swanson
Copy link
Contributor Author

/test

@taylor-swanson taylor-swanson marked this pull request as ready for review June 7, 2022 16:48
@taylor-swanson taylor-swanson requested a review from a team as a code owner June 7, 2022 16:48
@taylor-swanson taylor-swanson requested review from rdner and cmacknz and removed request for a team June 7, 2022 16:48
@elasticmachine
Copy link
Collaborator

Pinging @elastic/security-external-integrations (Team:Security-External Integrations)

@taylor-swanson
Copy link
Contributor Author

/package

Copy link
Member

@rdner rdner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All changes make sense to me.

libbeat/reader/syslog/util_test.go Outdated Show resolved Hide resolved
libbeat/reader/syslog/syslog.go Outdated Show resolved Hide resolved
libbeat/reader/syslog/util_test.go Show resolved Hide resolved
libbeat/reader/syslog/message.go Outdated Show resolved Hide resolved
libbeat/reader/syslog/message_test.go Outdated Show resolved Hide resolved
libbeat/reader/syslog/rfc3164_test.go Outdated Show resolved Hide resolved
// ErrPriority indicates a priority value is outside the acceptable range.
ErrPriority = errors.New("priority value out of range (expected 0..191)")
// ErrEOF indicates the message is truncated and cannot be parsed.
ErrEOF = errors.New("message is truncated (unexpected EOF)")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason to not use io.ErrUnexpectedEOF? It's commonly used for thing like this.

Copy link
Contributor Author

@taylor-swanson taylor-swanson Jun 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe EOF is the wrong terminology here. I don't want to confuse an improperly formatted/shaped message with not receiving enough data, but then again, how do you accurately tell the difference? I'd be okay with using the one from the standard library as long as it doesn't lose its meaning here (does it really matter saying "message is truncated"?).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't make a lot of sense either (error that is):

input:

<13> test-host this is the message

error: "parsing error at position 5: unexpected EOF"

The actual error here is that the input doesn't match the expected shape. There should be a timestamp directly after the <13>, but for this test, it's missing. The parser is supposed to pull out the individual fields (timestamp, hostname, etc) and validation on those values happens in the host language, after the parser has run. If, however, the parser can't pull out all the fields, it fails completely. Aside from error-ing out, the only other thing I can think of is that whatever can't be parsed out will be put into the message field and we move on. This already happens, but I believe the original, whole message gets used. It seems a bit pointless to do that, though, and I would argue using something like grok instead.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. Depending on how much you want to go into it, a way to do this might be to have (parse error([new error type]missing field(unexpected EOF))), which would end up looking like "parsing error at position 5: missing timestamp: unexpected EOF" when rendered. The logic would be to look for the first missing field when there is an io.ErrUnexpectedEOF added by the parser and interpose the missing field error, or similar.

In terms of use of the io.ErrUnexpectedEOF sentinel, its used generally in decoders for this kind of thing. It's best to put yourself in the mindset of a plan9 developer where everything is a file to see why.

- Add explicit wants to test cases
- Un-export test input fields
- Add checks for errors in timestamp tests
@taylor-swanson
Copy link
Contributor Author

I'm going to let this sit for a good week or two. Beats CI is just too unstable right now to get a clean build out of it. As far as I can tell, all of the failures recently have been completely unrelated to any changes introduced in this PR.

@taylor-swanson taylor-swanson merged commit cabc8ba into elastic:main Jun 27, 2022
@taylor-swanson taylor-swanson deleted the syslog-parsing branch June 27, 2022 16:27
mergify bot pushed a commit that referenced this pull request Jun 27, 2022
- Shifted most of the validation logic to the host language instead of
the Ragel parser. This allows for the message to be fully parsed even if
there are validation errors with one or more fields.
- Errors are accumulated as they occur, any fields that have already been
parsed and validated will be returned, alongside error.message.
- Priority field for RFC 3164 messages are now optional, as some
syslog providers will omit this part of the header (especially when writing to files).
- Structured data fields for RFC 5424 messages are processed in a
second pass. If the structured data format doesn't fit the RFC, it will be
prepended to the message, separated by a space.
- Structured data now uses map[string]interface{}
- Update testify to v1.7.1 dependency for assert.ErrorContains support

(cherry picked from commit cabc8ba)

# Conflicts:
#	libbeat/processors/syslog/syslog_test.go
#	libbeat/reader/syslog/message.go
#	libbeat/reader/syslog/message_test.go
#	libbeat/reader/syslog/syslog.go
#	libbeat/reader/syslog/syslog_test.go
#	libbeat/reader/syslog/util_test.go
mergify bot pushed a commit that referenced this pull request Jun 27, 2022
- Shifted most of the validation logic to the host language instead of
the Ragel parser. This allows for the message to be fully parsed even if
there are validation errors with one or more fields.
- Errors are accumulated as they occur, any fields that have already been
parsed and validated will be returned, alongside error.message.
- Priority field for RFC 3164 messages are now optional, as some
syslog providers will omit this part of the header (especially when writing to files).
- Structured data fields for RFC 5424 messages are processed in a
second pass. If the structured data format doesn't fit the RFC, it will be
prepended to the message, separated by a space.
- Structured data now uses map[string]interface{}
- Update testify to v1.7.1 dependency for assert.ErrorContains support

(cherry picked from commit cabc8ba)
rdner pushed a commit that referenced this pull request Jun 28, 2022
…2118)

- Shifted most of the validation logic to the host language instead of
the Ragel parser. This allows for the message to be fully parsed even if
there are validation errors with one or more fields.
- Errors are accumulated as they occur, any fields that have already been
parsed and validated will be returned, alongside error.message.
- Priority field for RFC 3164 messages are now optional, as some
syslog providers will omit this part of the header (especially when writing to files).
- Structured data fields for RFC 5424 messages are processed in a
second pass. If the structured data format doesn't fit the RFC, it will be
prepended to the message, separated by a space.
- Structured data now uses map[string]interface{}
- Update testify to v1.7.1 dependency for assert.ErrorContains support

(cherry picked from commit cabc8ba)

Co-authored-by: Taylor Swanson <90622908+taylor-swanson@users.noreply.github.com>
taylor-swanson added a commit that referenced this pull request Jul 5, 2022
- Shifted most of the validation logic to the host language instead of
the Ragel parser. This allows for the message to be fully parsed even if
there are validation errors with one or more fields.
- Errors are accumulated as they occur, any fields that have already been
parsed and validated will be returned, alongside error.message.
- Priority field for RFC 3164 messages are now optional, as some
syslog providers will omit this part of the header (especially when writing to files).
- Structured data fields for RFC 5424 messages are processed in a
second pass. If the structured data format doesn't fit the RFC, it will be
prepended to the message, separated by a space.
- Structured data now uses map[string]interface{}
- Update testify to v1.7.1 dependency for assert.ErrorContains support

(cherry picked from commit cabc8ba)
taylor-swanson added a commit that referenced this pull request Jul 5, 2022
…2117)

- Shifted most of the validation logic to the host language instead of
the Ragel parser. This allows for the message to be fully parsed even if
there are validation errors with one or more fields.
- Errors are accumulated as they occur, any fields that have already been
parsed and validated will be returned, alongside error.message.
- Priority field for RFC 3164 messages are now optional, as some
syslog providers will omit this part of the header (especially when writing to files).
- Structured data fields for RFC 5424 messages are processed in a
second pass. If the structured data format doesn't fit the RFC, it will be
prepended to the message, separated by a space.
- Structured data now uses map[string]interface{}
- Update testify to v1.7.1 dependency for assert.ErrorContains support

(cherry picked from commit cabc8ba)

Co-authored-by: Taylor Swanson <90622908+taylor-swanson@users.noreply.github.com>
leweafan pushed a commit to leweafan/beats that referenced this pull request Apr 28, 2023
…) (elastic#32117)

- Shifted most of the validation logic to the host language instead of
the Ragel parser. This allows for the message to be fully parsed even if
there are validation errors with one or more fields.
- Errors are accumulated as they occur, any fields that have already been
parsed and validated will be returned, alongside error.message.
- Priority field for RFC 3164 messages are now optional, as some
syslog providers will omit this part of the header (especially when writing to files).
- Structured data fields for RFC 5424 messages are processed in a
second pass. If the structured data format doesn't fit the RFC, it will be
prepended to the message, separated by a space.
- Structured data now uses map[string]interface{}
- Update testify to v1.7.1 dependency for assert.ErrorContains support

(cherry picked from commit 7ba9a7b)

Co-authored-by: Taylor Swanson <90622908+taylor-swanson@users.noreply.github.com>
chrisberkhout pushed a commit that referenced this pull request Jun 1, 2023
- Shifted most of the validation logic to the host language instead of
the Ragel parser. This allows for the message to be fully parsed even if
there are validation errors with one or more fields.
- Errors are accumulated as they occur, any fields that have already been
parsed and validated will be returned, alongside error.message.
- Priority field for RFC 3164 messages are now optional, as some
syslog providers will omit this part of the header (especially when writing to files).
- Structured data fields for RFC 5424 messages are processed in a
second pass. If the structured data format doesn't fit the RFC, it will be
prepended to the message, separated by a space.
- Structured data now uses map[string]interface{}
- Update testify to v1.7.1 dependency for assert.ErrorContains support
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
8.4-candidate backport-v8.2.0 Automated backport with mergify backport-v8.3.0 Automated backport with mergify enhancement libbeat :Processors
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Make Syslog parser/processor handle errors more gracefully
4 participants