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

[Filebeat][New Input] Http Input #18298

Merged
merged 29 commits into from
May 25, 2020
Merged

[Filebeat][New Input] Http Input #18298

merged 29 commits into from
May 25, 2020

Conversation

P1llus
Copy link
Member

@P1llus P1llus commented May 6, 2020

What does this PR do?

This filebeat input configures a HTTP port listener, accepting JSON formatted POST requests, which again is formatted into a event, initially the event is created with the "json." prefix and expects the ingest pipeline to mutate the event during ingestion.

The initial set of features is based on the Logstash input plugin, but implemented differently: https://www.elastic.co/guide/en/logstash/current/plugins-inputs-http.html

Why is it important?

This idea is based on a few different scenarios:

  • The user already has a large beats installation and no Logstash, and do not want to install Logstash solely for a single feature.
  • HTTP Input allows applications to be directly integrated with Elastic, without needing connectivity to Elasticsearch directly (or Logstash).
  • Allows us to integrate and create modules for any product that supports HTTP POST events like SOAR, cloud applications, ticketing systems etc etc.

Features currently implemented

HTTP Basic Auth On/Off
HTTP/HTTPS configurable
Listening interface and port configurable
Response code on success configurable
Response body on success configurable
Response header on success configurable
Proper HTTP codes on both success and error responses
Message prefix configurable
URL to post to is configurable
SSL path to cert, key and CA is configurable.

TODO

  • Clean up code
  • Import configuration options from common
  • Write documentation
  • Add TLS mutual auth support
  • Config validation
  • Tests

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.

@P1llus P1llus added enhancement in progress Pull request is currently in progress. Team:SIEM labels May 6, 2020
@elasticmachine
Copy link
Collaborator

Pinging @elastic/siem (Team:SIEM)

@botelastic botelastic bot added the needs_team Indicates that the issue/PR needs a Team:* label label May 6, 2020
@elasticmachine
Copy link
Collaborator

elasticmachine commented May 6, 2020

💚 Build Succeeded

Pipeline View Test View Changes Artifacts preview

Expand to view the summary

Build stats

Test stats 🧪

Test Results
Failed 0
Passed 3811
Skipped 672
Total 4483

@P1llus
Copy link
Member Author

P1llus commented May 17, 2020

@kvch Added first iteration of docs, let me know if it looks okay :) Do I need to add it anywhere else as well? I don't think it will be automatically included by just creating a new asciidoc in the inputs docs folder.

@P1llus P1llus requested review from andrewstucki and kvch May 17, 2020 14:00
Copy link
Contributor

@andrewstucki andrewstucki left a comment

Choose a reason for hiding this comment

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

Some more thoughts as I incrementally work through this 🙂

x-pack/filebeat/input/http_endpoint/input.go Outdated Show resolved Hide resolved
x-pack/filebeat/input/http_endpoint/input.go Outdated Show resolved Hide resolved
return http.StatusUnsupportedMediaType, in.createErrorMessage("Wrong Content-Type header, expecting application/json")
}

if r.Header.Get("Accept") != "application/json" {
Copy link
Contributor

Choose a reason for hiding this comment

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

So, my previous comment about overriding headers mainly stems from this line. The Accept header checking seems to indicate that we're always going to respond with a Content-Type: application/json header--but the fact that we allow the response headers to be overridden in the config actually breaks this. Nothing currently prevents the user from doing something like:

{beatname_lc}.inputs:
- type: http_endpoint
  ...
  response_body: '<message>success</message>'
  response_header: '{"Content-Type": "application/xml"}'

If we're actually wanting to make sure we always hand back json I'd do two things:

  1. Always set the Content-Type: application/json header and ignore what the user may specify in the config
  2. Validate the response value that the user specifies in response_body is actually valid JSON.

x-pack/filebeat/input/http_endpoint/input.go Outdated Show resolved Hide resolved
@P1llus
Copy link
Member Author

P1llus commented May 19, 2020

@andrewstucki
I thought more about the response header for now, and it makes sense to me to remove it for now.
There is a few reasons for that.

  1. If we decide later on to add support for more than JSON, it would make more sense.
  2. Currently the custom response headers was more to add other headers than content-type, though I am still having a hard time finding good use-cases for when that would be needed.
    So if it is okay with you, I have hardcoded the response header (upon success), but still allowing anyone to set the response code and will revisit this later if there is requests open for this feature.

@P1llus P1llus requested a review from andrewstucki May 19, 2020 07:41
Copy link
Contributor

@kvch kvch left a comment

Choose a reason for hiding this comment

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

LGTM. Once all questions are resolved, I am OK with merging it.

Copy link
Contributor

@andrewstucki andrewstucki left a comment

Choose a reason for hiding this comment

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

Last comment and then I think I'm good on this

Username string `config:"username"`
Password string `config:"password"`
ResponseCode int `config:"response_code" validate:"positive"`
ResponseBody string `config:"response_body"`
Copy link
Contributor

Choose a reason for hiding this comment

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

If we're going to hardcode that this is a JSON-based response, I think we should likely still sanity check that the user actually entered JSON. You could just make a Validate method for the config structure and inside do something like

func (c *config) Validate() error {
  if !json.Valid(c.ResponseBody) {
    return errors.New("response_body must be valid JSON")
  }
  // other validations here
  return nil 
}

Copy link
Member Author

Choose a reason for hiding this comment

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

Added the validation, just had to convert it from a string to a byteslice as well.

New return upon wrong response body is:

2020-05-25T08:43:01.744+0200	ERROR	instance/beat.go:931	Exiting: Failed to start crawler: starting input failed: Error while initializing input: response_body must be valid JSON accessing 'filebeat.inputs.0' (source:'filebeat.yml')
Exiting: Failed to start crawler: starting input failed: Error while initializing input: response_body must be valid JSON accessing 'filebeat.inputs.0' (source:'filebeat.yml')

@P1llus
Copy link
Member Author

P1llus commented May 25, 2020

Should now be ready for merge and backport :)

@elasticmachine
Copy link
Collaborator

elasticmachine commented May 25, 2020

💚 Build Succeeded

Pipeline View Test View Changes Artifacts preview

Expand to view the summary

Build stats

  • Build Cause: [Pull request #18298 updated]

  • Start Time: 2020-05-25T11:32:33.266+0000

  • Duration: 53 min 15 sec

Test stats 🧪

Test Results
Failed 0
Passed 3811
Skipped 672
Total 4483

@P1llus
Copy link
Member Author

P1llus commented May 25, 2020

jenkins, test this please

@kvch
Copy link
Contributor

kvch commented May 25, 2020

jenkins run tests

@kvch kvch merged commit 0b84f0a into elastic:master May 25, 2020
kvch pushed a commit to kvch/beats that referenced this pull request May 25, 2020
## What does this PR do?

This filebeat input configures a HTTP port listener, accepting JSON formatted POST requests, which again is formatted into a event, initially the event is created with the "json." prefix and expects the ingest pipeline to mutate the event during ingestion.

The initial set of features is based on the Logstash input plugin, but implemented differently: https://www.elastic.co/guide/en/logstash/current/plugins-inputs-http.html

## Why is it important?

This idea is based on a few different scenarios:

- The user already has a large beats installation and no Logstash, and do not want to install Logstash solely for a single feature.
- HTTP Input allows applications to be directly integrated with Elastic, without needing connectivity to Elasticsearch directly (or Logstash).
- Allows us to integrate and create modules for any product that supports HTTP POST events like SOAR, cloud applications, ticketing systems etc etc.

## Features currently implemented

- HTTP Basic Auth On/Off
- HTTP/HTTPS configurable
- Listening interface and port configurable
- Response code on success configurable
- Response body on success configurable
- Response header on success configurable
- Proper HTTP codes on both success and error responses
- Message prefix configurable
- URL to post to is configurable
- SSL path to cert, key and CA is configurable.

(cherry picked from commit 0b84f0a)
@kvch kvch added the v7.9.0 label May 25, 2020
kvch added a commit that referenced this pull request May 25, 2020
## What does this PR do?

This filebeat input configures a HTTP port listener, accepting JSON formatted POST requests, which again is formatted into a event, initially the event is created with the "json." prefix and expects the ingest pipeline to mutate the event during ingestion.

The initial set of features is based on the Logstash input plugin, but implemented differently: https://www.elastic.co/guide/en/logstash/current/plugins-inputs-http.html

## Why is it important?

This idea is based on a few different scenarios:

- The user already has a large beats installation and no Logstash, and do not want to install Logstash solely for a single feature.
- HTTP Input allows applications to be directly integrated with Elastic, without needing connectivity to Elasticsearch directly (or Logstash).
- Allows us to integrate and create modules for any product that supports HTTP POST events like SOAR, cloud applications, ticketing systems etc etc.

## Features currently implemented

- HTTP Basic Auth On/Off
- HTTP/HTTPS configurable
- Listening interface and port configurable
- Response code on success configurable
- Response body on success configurable
- Response header on success configurable
- Proper HTTP codes on both success and error responses
- Message prefix configurable
- URL to post to is configurable
- SSL path to cert, key and CA is configurable.

(cherry picked from commit 0b84f0a)

Co-authored-by: Marius Iversen <pillus@chasenet.org>
@P1llus P1llus deleted the http_input_module branch May 25, 2020 17:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants