Skip to content

Commit ccea0c7

Browse files
Allow Filebeat modules to be excluded from FIPS-capable artifacts (#44920) (#45014)
* Add ability for Filebeat plugins (inputs) to specify that they should be excluded from FIPS builds * Remove ExcludeForFIPS implementation * Create and check FIPSAwareInput interface * Make o365 input use FIPSAwareInput interface * Running mage fmt * Remove debugging statement * Explain behavior for types not implementing the interface * Adding godoc comments for implementations of the IsFIPSCapable() method * Add unit test for checkFIPSCapability() * Running mage fmt * Remove example implementation (cherry picked from commit 322d694) Co-authored-by: Shaunak Kashyap <ycombinator@gmail.com>
1 parent 0ec0052 commit ccea0c7

File tree

7 files changed

+179
-0
lines changed

7 files changed

+179
-0
lines changed

filebeat/beater/crawler.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,10 @@ func (c *crawler) startInput(
144144
inputRunner.Once = c.once
145145
}
146146

147+
if err := checkFIPSCapability(runner); err != nil {
148+
return err
149+
}
150+
147151
c.inputs[id] = runner
148152

149153
c.log.Infof("Starting input (ID: %d)", id)

filebeat/beater/crawler_fips.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Licensed to Elasticsearch B.V. under one or more contributor
2+
// license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright
4+
// ownership. Elasticsearch B.V. licenses this file to you under
5+
// the Apache License, Version 2.0 (the "License"); you may
6+
// not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
//go:build requirefips
19+
20+
package beater
21+
22+
import (
23+
"fmt"
24+
25+
v2 "github.com/elastic/beats/v7/filebeat/input/v2"
26+
"github.com/elastic/beats/v7/libbeat/cfgfile"
27+
)
28+
29+
func checkFIPSCapability(runner cfgfile.Runner) error {
30+
fipsAwareInput, ok := runner.(v2.FIPSAwareInput)
31+
if !ok {
32+
// Input is not FIPS-aware; assume it's FIPS capable and proceed
33+
// without error
34+
return nil
35+
}
36+
37+
if fipsAwareInput.IsFIPSCapable() {
38+
// Input is FIPS-capable, proceed without error
39+
return nil
40+
}
41+
42+
return fmt.Errorf("running a FIPS-capable distribution but input [%s] is not FIPS capable", runner.String())
43+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Licensed to Elasticsearch B.V. under one or more contributor
2+
// license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright
4+
// ownership. Elasticsearch B.V. licenses this file to you under
5+
// the Apache License, Version 2.0 (the "License"); you may
6+
// not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
//go:build requirefips
19+
20+
package beater
21+
22+
import (
23+
"testing"
24+
25+
"github.com/stretchr/testify/require"
26+
27+
"github.com/elastic/beats/v7/libbeat/cfgfile"
28+
)
29+
30+
type fipsUnawareInput struct{}
31+
32+
func newFIPSUnawareInput() *fipsUnawareInput { return &fipsUnawareInput{} }
33+
func (f *fipsUnawareInput) String() string { return "fips_unaware_input" }
34+
func (f *fipsUnawareInput) Start() {}
35+
func (f *fipsUnawareInput) Stop() {}
36+
37+
type fipsAwareInput struct{ isFIPSCapable bool }
38+
39+
func newFIPSAwareInput(isFIPSCapable bool) *fipsAwareInput {
40+
return &fipsAwareInput{isFIPSCapable: isFIPSCapable}
41+
}
42+
func (f *fipsAwareInput) String() string { return "fips_aware_input" }
43+
func (f *fipsAwareInput) Start() {}
44+
func (f *fipsAwareInput) Stop() {}
45+
func (f *fipsAwareInput) IsFIPSCapable() bool { return f.isFIPSCapable }
46+
47+
func TestCheckFIPSCapability(t *testing.T) {
48+
tests := map[string]struct {
49+
runner cfgfile.Runner
50+
expectedErr string
51+
}{
52+
"input_is_not_fips_aware": {
53+
runner: newFIPSUnawareInput(),
54+
expectedErr: "",
55+
},
56+
"input_is_fips_aware_but_not_fips_capable": {
57+
runner: newFIPSAwareInput(false),
58+
expectedErr: "running a FIPS-capable distribution but input [fips_aware_input] is not FIPS capable",
59+
},
60+
"input_is_fips_aware_and_fips_capable": {
61+
runner: newFIPSAwareInput(true),
62+
expectedErr: "",
63+
},
64+
}
65+
66+
for name, test := range tests {
67+
t.Run(name, func(t *testing.T) {
68+
err := checkFIPSCapability(test.runner)
69+
if test.expectedErr == "" {
70+
require.NoError(t, err)
71+
} else {
72+
require.EqualError(t, err, test.expectedErr)
73+
}
74+
})
75+
}
76+
}

filebeat/beater/crawler_nofips.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Licensed to Elasticsearch B.V. under one or more contributor
2+
// license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright
4+
// ownership. Elasticsearch B.V. licenses this file to you under
5+
// the Apache License, Version 2.0 (the "License"); you may
6+
// not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
//go:build !requirefips
19+
20+
package beater
21+
22+
import "github.com/elastic/beats/v7/libbeat/cfgfile"
23+
24+
func checkFIPSCapability(_ cfgfile.Runner) error {
25+
// In non-FIPS builds, we assume all inputs are FIPS capable
26+
// and proceed without error
27+
return nil
28+
}

filebeat/input/v2/compat/compat.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,3 +223,14 @@ func (f *factory) generateCheckConfig(config *conf.C) (*conf.C, error) {
223223

224224
return testCfg, nil
225225
}
226+
227+
// IsFIPSCapable returns true if the input is capable of running with
228+
// FIPS-compliant algorithms; false, otherwise.
229+
func (r *runner) IsFIPSCapable() bool {
230+
if fipsAwareInput, ok := r.input.(v2.FIPSAwareInput); ok {
231+
return fipsAwareInput.IsFIPSCapable()
232+
}
233+
234+
// Input does not implement FIPSAwareInput, assume it is FIPS-capable
235+
return true
236+
}

filebeat/input/v2/input-cursor/input.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,15 @@ func (inp *managedInput) Test(ctx input.TestContext) error {
8686
return nil
8787
}
8888

89+
// IsFIPSCapable returns true if the input is capable of running with
90+
// FIPS-compliant algorithms; false, otherwise.
91+
func (inp *managedInput) IsFIPSCapable() bool {
92+
if fipsAware, ok := inp.input.(input.FIPSAwareInput); ok {
93+
return fipsAware.IsFIPSCapable()
94+
}
95+
return true
96+
}
97+
8998
func (inp *managedInput) testSource(ctx input.TestContext, source Source) (err error) {
9099
defer func() {
91100
if v := recover(); v != nil {

filebeat/input/v2/input.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,14 @@ type Input interface {
7878
Run(Context, beat.PipelineConnector) error
7979
}
8080

81+
// FIPSAwareInput is able to report if it is FIPS capable or not. If a type does
82+
// not implement this interface, that type will be considered to be FIPS capable.
83+
type FIPSAwareInput interface {
84+
// IsFIPSCapable returns true if the input is capable of running with
85+
// FIPS-compliant algorithms; false, otherwise.
86+
IsFIPSCapable() bool
87+
}
88+
8189
// Context provides the Input Run function with common environmental
8290
// information and services.
8391
type Context struct {

0 commit comments

Comments
 (0)