From f9cff1edbeb885b3adc3d0db927e45d878aefd72 Mon Sep 17 00:00:00 2001 From: Joseph Sirianni Date: Mon, 20 Jun 2022 11:01:08 -0400 Subject: [PATCH] fix: Set read timeout for forward input operator (#663) * Add ReadTimeout param to forward input operator, defaulting to five seconds * Update gosec and license workflow triggers to match other workflows * Set ReadHeaderTimeout explicitly to satisfy Gosec. This value is set to ReadTimeout by default, but Gosec does not detect this --- .github/workflows/gosec.yml | 1 - .github/workflows/license.yml | 6 +----- docs/operators/forward_input.md | 1 + operator/builtin/input/forward/forward.go | 16 ++++++++++++---- operator/builtin/input/forward/forward_test.go | 3 +++ 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/.github/workflows/gosec.yml b/.github/workflows/gosec.yml index fcbea5055..0170a5cea 100644 --- a/.github/workflows/gosec.yml +++ b/.github/workflows/gosec.yml @@ -13,7 +13,6 @@ on: # * * * * * - cron: '30 1 * * *' pull_request: - branches: [ master ] jobs: tests: diff --git a/.github/workflows/license.yml b/.github/workflows/license.yml index a3480fed8..f4e5787b8 100644 --- a/.github/workflows/license.yml +++ b/.github/workflows/license.yml @@ -1,11 +1,7 @@ name: license on: pull_request: - branches: - - master - push: - branches: - - master + jobs: build: name: Scan Licenses diff --git a/docs/operators/forward_input.md b/docs/operators/forward_input.md index cf7f9db01..534799374 100644 --- a/docs/operators/forward_input.md +++ b/docs/operators/forward_input.md @@ -9,6 +9,7 @@ The `foward_input` operator receives logs from another Stanza instance running ` | `id` | `forward_output` | A unique identifier for the operator | | `listen_address` | `:80` | The IP address and port to listen on | | `tls` | | A block for configuring the server to listen with TLS | +| `read_timeout` | `5s` | Maximum duration for reading the entire request, including the body. | #### TLS block configuration diff --git a/operator/builtin/input/forward/forward.go b/operator/builtin/input/forward/forward.go index 8c6407eb5..5bdeab03e 100644 --- a/operator/builtin/input/forward/forward.go +++ b/operator/builtin/input/forward/forward.go @@ -5,6 +5,7 @@ import ( "encoding/json" "net" "net/http" + "time" "github.com/observiq/stanza/entry" "github.com/observiq/stanza/errors" @@ -21,14 +22,16 @@ func init() { func NewForwardInputConfig(operatorID string) *ForwardInputConfig { return &ForwardInputConfig{ InputConfig: helper.NewInputConfig(operatorID, "stdin"), + ReadTimeout: helper.NewDuration(time.Second * 5), } } // ForwardInputConfig is the configuration of a forward input operator type ForwardInputConfig struct { helper.InputConfig `yaml:",inline"` - ListenAddress string `json:"listen_address" yaml:"listen_address"` - TLS *TLSConfig `json:"tls" yaml:"tls"` + ListenAddress string `json:"listen_address" yaml:"listen_address"` + TLS *TLSConfig `json:"tls" yaml:"tls"` + ReadTimeout helper.Duration `json:"read_timeout" yaml:"read_timeout"` } // TLSConfig is a configuration struct for forward input TLS @@ -50,8 +53,13 @@ func (c *ForwardInputConfig) Build(context operator.BuildContext) ([]operator.Op } forwardInput.srv = &http.Server{ - Addr: c.ListenAddress, - Handler: forwardInput, + Addr: c.ListenAddress, + Handler: forwardInput, + ReadTimeout: c.ReadTimeout.Duration, + // ReadHeaderTimeout defaults to ReadTimeout, but Gosec fails + // if this value is not set. For simplicity, only ReadTimeout + // is exposed to the user. + ReadHeaderTimeout: c.ReadTimeout.Duration, } return []operator.Operator{forwardInput}, nil diff --git a/operator/builtin/input/forward/forward_test.go b/operator/builtin/input/forward/forward_test.go index 5bfd92463..40b4cc243 100644 --- a/operator/builtin/input/forward/forward_test.go +++ b/operator/builtin/input/forward/forward_test.go @@ -23,10 +23,13 @@ func TestForwardInput(t *testing.T) { cfg := NewForwardInputConfig("test") cfg.ListenAddress = "0.0.0.0:0" cfg.OutputIDs = []string{"fake"} + require.Equal(t, time.Second*5, cfg.ReadTimeout.Duration) ops, err := cfg.Build(testutil.NewBuildContext(t)) require.NoError(t, err) forwardInput := ops[0].(*ForwardInput) + require.Equal(t, time.Second*5, forwardInput.srv.ReadTimeout) + require.Equal(t, time.Second*5, forwardInput.srv.ReadHeaderTimeout) fake := testutil.NewFakeOutput(t) err = forwardInput.SetOutputs([]operator.Operator{fake})