Skip to content

Commit 5f67714

Browse files
author
Israel Blancas
authored
Merge branch 'main' into bug/3281
2 parents f3e8de0 + 05c901f commit 5f67714

File tree

13 files changed

+243
-6
lines changed

13 files changed

+243
-6
lines changed

.chloggen/fips.yaml

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
2+
change_type: enhancement
3+
4+
# The name of the component, or a single word describing the area of concern, (e.g. collector, target allocator, auto-instrumentation, opamp, github action)
5+
component: collector
6+
7+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
8+
note: Add flag to disable components when operator runs on FIPS enabled cluster.
9+
10+
# One or more tracking issues related to the change
11+
issues: [3315]
12+
13+
# (Optional) One or more lines of additional information to render under the primary note.
14+
# These lines will be padded with 2 spaces and then inserted directly into the document.
15+
# Use pipe (|) for multiline entries.
16+
subtext: |
17+
Flag `--fips-disabled-components=receiver.otlp,exporter.otlp,processor.batch,extension.oidc` can be used to disable
18+
components when operator runs on FIPS enabled cluster. The operator uses `/proc/sys/crypto/fips_enabled` to check
19+
if FIPS is enabled.

apis/v1beta1/collector_webhook.go

+13-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
2828

2929
"github.com/open-telemetry/opentelemetry-operator/internal/config"
30+
"github.com/open-telemetry/opentelemetry-operator/internal/fips"
3031
ta "github.com/open-telemetry/opentelemetry-operator/internal/manifests/targetallocator/adapters"
3132
"github.com/open-telemetry/opentelemetry-operator/internal/rbac"
3233
)
@@ -48,6 +49,7 @@ type CollectorWebhook struct {
4849
reviewer *rbac.Reviewer
4950
metrics *Metrics
5051
bv BuildValidator
52+
fips fips.FIPSCheck
5153
}
5254

5355
func (c CollectorWebhook) Default(_ context.Context, obj runtime.Object) error {
@@ -290,6 +292,13 @@ func (c CollectorWebhook) Validate(ctx context.Context, r *OpenTelemetryCollecto
290292
return warnings, fmt.Errorf("the OpenTelemetry Collector mode is set to %s, which does not support the attribute 'deploymentUpdateStrategy'", r.Spec.Mode)
291293
}
292294

295+
if c.fips != nil {
296+
components := r.Spec.Config.GetEnabledComponents()
297+
if notAllowedComponents := c.fips.DisabledComponents(components[KindReceiver], components[KindExporter], components[KindProcessor], components[KindExtension]); notAllowedComponents != nil {
298+
return nil, fmt.Errorf("the collector configuration contains not FIPS compliant components: %s. Please remove it from the config", notAllowedComponents)
299+
}
300+
}
301+
293302
return warnings, nil
294303
}
295304

@@ -423,6 +432,7 @@ func NewCollectorWebhook(
423432
reviewer *rbac.Reviewer,
424433
metrics *Metrics,
425434
bv BuildValidator,
435+
fips fips.FIPSCheck,
426436
) *CollectorWebhook {
427437
return &CollectorWebhook{
428438
logger: logger,
@@ -431,11 +441,12 @@ func NewCollectorWebhook(
431441
reviewer: reviewer,
432442
metrics: metrics,
433443
bv: bv,
444+
fips: fips,
434445
}
435446
}
436447

437-
func SetupCollectorWebhook(mgr ctrl.Manager, cfg config.Config, reviewer *rbac.Reviewer, metrics *Metrics, bv BuildValidator) error {
438-
cvw := NewCollectorWebhook(mgr.GetLogger().WithValues("handler", "CollectorWebhook", "version", "v1beta1"), mgr.GetScheme(), cfg, reviewer, metrics, bv)
448+
func SetupCollectorWebhook(mgr ctrl.Manager, cfg config.Config, reviewer *rbac.Reviewer, metrics *Metrics, bv BuildValidator, fipsCheck fips.FIPSCheck) error {
449+
cvw := NewCollectorWebhook(mgr.GetLogger().WithValues("handler", "CollectorWebhook", "version", "v1beta1"), mgr.GetScheme(), cfg, reviewer, metrics, bv, fipsCheck)
439450
return ctrl.NewWebhookManagedBy(mgr).
440451
For(&OpenTelemetryCollector{}).
441452
WithValidator(cvw).

apis/v1beta1/collector_webhook_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ func TestValidate(t *testing.T) {
113113
getReviewer(test.shouldFailSar),
114114
nil,
115115
bv,
116+
nil,
116117
)
117118
t.Run(tt.name, func(t *testing.T) {
118119
tt := tt
@@ -494,6 +495,7 @@ func TestCollectorDefaultingWebhook(t *testing.T) {
494495
getReviewer(test.shouldFailSar),
495496
nil,
496497
bv,
498+
nil,
497499
)
498500
ctx := context.Background()
499501
err := cvw.Default(ctx, &test.otelcol)
@@ -1285,6 +1287,7 @@ func TestOTELColValidatingWebhook(t *testing.T) {
12851287
getReviewer(test.shouldFailSar),
12861288
nil,
12871289
bv,
1290+
nil,
12881291
)
12891292
ctx := context.Background()
12901293
warnings, err := cvw.ValidateCreate(ctx, &test.otelcol)
@@ -1352,6 +1355,7 @@ func TestOTELColValidateUpdateWebhook(t *testing.T) {
13521355
getReviewer(test.shouldFailSar),
13531356
nil,
13541357
bv,
1358+
nil,
13551359
)
13561360
ctx := context.Background()
13571361
warnings, err := cvw.ValidateUpdate(ctx, &test.otelcolOld, &test.otelcolNew)

apis/v1beta1/config.go

+4
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ func (c *Config) GetEnabledComponents() map[ComponentKind]map[string]interface{}
113113
KindExporter: {},
114114
KindExtension: {},
115115
}
116+
for _, extension := range c.Service.Extensions {
117+
toReturn[KindExtension][extension] = struct{}{}
118+
}
119+
116120
for _, pipeline := range c.Service.Pipelines {
117121
if pipeline == nil {
118122
continue

controllers/suite_test.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ type mockAutoDetect struct {
102102
RBACPermissionsFunc func(ctx context.Context) (autoRBAC.Availability, error)
103103
}
104104

105+
func (m *mockAutoDetect) FIPSEnabled(ctx context.Context) bool {
106+
return false
107+
}
108+
105109
func (m *mockAutoDetect) PrometheusCRsAvailability() (prometheus.Availability, error) {
106110
if m.PrometheusCRsAvailabilityFunc != nil {
107111
return m.PrometheusCRsAvailabilityFunc()
@@ -178,7 +182,7 @@ func TestMain(m *testing.M) {
178182
}
179183
reviewer := rbac.NewReviewer(clientset)
180184

181-
if err = v1beta1.SetupCollectorWebhook(mgr, config.New(), reviewer, nil, nil); err != nil {
185+
if err = v1beta1.SetupCollectorWebhook(mgr, config.New(), reviewer, nil, nil, nil); err != nil {
182186
fmt.Printf("failed to SetupWebhookWithManager: %v", err)
183187
os.Exit(1)
184188
}
+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright The OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package fips
16+
17+
import (
18+
"errors"
19+
"os"
20+
"strings"
21+
)
22+
23+
const fipsFile = "/proc/sys/crypto/fips_enabled"
24+
25+
// IsFipsEnabled checks whether FIPS is enabled on the platform.
26+
func IsFipsEnabled() bool {
27+
// check if file exists
28+
if _, err := os.Stat(fipsFile); errors.Is(err, os.ErrNotExist) {
29+
return false
30+
}
31+
content, err := os.ReadFile(fipsFile)
32+
if err != nil {
33+
// file cannot be read, enable FIPS to avoid any violations
34+
return true
35+
}
36+
contentStr := string(content)
37+
contentStr = strings.TrimSpace(contentStr)
38+
return contentStr == "1"
39+
}

internal/autodetect/main.go

+6
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"k8s.io/client-go/discovery"
2323
"k8s.io/client-go/rest"
2424

25+
"github.com/open-telemetry/opentelemetry-operator/internal/autodetect/fips"
2526
"github.com/open-telemetry/opentelemetry-operator/internal/autodetect/openshift"
2627
"github.com/open-telemetry/opentelemetry-operator/internal/autodetect/prometheus"
2728
autoRBAC "github.com/open-telemetry/opentelemetry-operator/internal/autodetect/rbac"
@@ -35,6 +36,7 @@ type AutoDetect interface {
3536
OpenShiftRoutesAvailability() (openshift.RoutesAvailability, error)
3637
PrometheusCRsAvailability() (prometheus.Availability, error)
3738
RBACPermissions(ctx context.Context) (autoRBAC.Availability, error)
39+
FIPSEnabled(ctx context.Context) bool
3840
}
3941

4042
type autoDetect struct {
@@ -122,3 +124,7 @@ func (a *autoDetect) RBACPermissions(ctx context.Context) (autoRBAC.Availability
122124

123125
return autoRBAC.Available, nil
124126
}
127+
128+
func (a *autoDetect) FIPSEnabled(_ context.Context) bool {
129+
return fips.IsFipsEnabled()
130+
}

internal/config/main_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ type mockAutoDetect struct {
8282
RBACPermissionsFunc func(ctx context.Context) (rbac.Availability, error)
8383
}
8484

85+
func (m *mockAutoDetect) FIPSEnabled(_ context.Context) bool {
86+
return false
87+
}
88+
8589
func (m *mockAutoDetect) OpenShiftRoutesAvailability() (openshift.RoutesAvailability, error) {
8690
if m.OpenShiftRoutesAvailabilityFunc != nil {
8791
return m.OpenShiftRoutesAvailabilityFunc()

internal/fips/fipscheck.go

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright The OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package fips
16+
17+
import (
18+
"strings"
19+
)
20+
21+
type FIPSCheck interface {
22+
// DisabledComponents checks if a submitted components are denied or not.
23+
DisabledComponents(receivers map[string]interface{}, exporters map[string]interface{}, processors map[string]interface{}, extensions map[string]interface{}) []string
24+
}
25+
26+
// FipsCheck holds configuration for FIPS deny list.
27+
type fipsCheck struct {
28+
receivers map[string]bool
29+
exporters map[string]bool
30+
processors map[string]bool
31+
extensions map[string]bool
32+
}
33+
34+
// NewFipsCheck creates new FipsCheck.
35+
func NewFipsCheck(receivers, exporters, processors, extensions []string) FIPSCheck {
36+
return &fipsCheck{
37+
receivers: listToMap(receivers),
38+
exporters: listToMap(exporters),
39+
processors: listToMap(processors),
40+
extensions: listToMap(extensions),
41+
}
42+
}
43+
44+
func listToMap(list []string) map[string]bool {
45+
m := map[string]bool{}
46+
for _, v := range list {
47+
m[v] = true
48+
}
49+
return m
50+
}
51+
52+
func (fips fipsCheck) DisabledComponents(receivers map[string]interface{}, exporters map[string]interface{}, processors map[string]interface{}, extensions map[string]interface{}) []string {
53+
var disabled []string
54+
if comp := isDisabled(fips.receivers, receivers); comp != "" {
55+
disabled = append(disabled, comp)
56+
}
57+
if comp := isDisabled(fips.exporters, exporters); comp != "" {
58+
disabled = append(disabled, comp)
59+
}
60+
if comp := isDisabled(fips.processors, processors); comp != "" {
61+
disabled = append(disabled, comp)
62+
}
63+
if comp := isDisabled(fips.extensions, extensions); comp != "" {
64+
disabled = append(disabled, comp)
65+
}
66+
return disabled
67+
}
68+
69+
func isDisabled(denyList map[string]bool, cfg map[string]interface{}) string {
70+
for id := range cfg {
71+
component := strings.Split(id, "/")[0]
72+
if denyList[component] {
73+
return component
74+
}
75+
}
76+
return ""
77+
}

internal/fips/fipscheck_test.go

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright The OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package fips
16+
17+
import (
18+
"testing"
19+
20+
"github.com/stretchr/testify/assert"
21+
)
22+
23+
func TestFipsCheck(t *testing.T) {
24+
fipsCheck := NewFipsCheck([]string{"rec1", "rec2"}, []string{"exp1"}, []string{"processor"}, []string{"ext1"})
25+
blocked := fipsCheck.DisabledComponents(
26+
map[string]interface{}{"otlp": true, "rec1/my": true},
27+
map[string]interface{}{"exp1": true},
28+
map[string]interface{}{"processor": true},
29+
map[string]interface{}{"ext1": true})
30+
31+
assert.Equal(t, []string{"rec1", "exp1", "processor", "ext1"}, blocked)
32+
}

internal/webhook/podmutation/webhookhandler_suite_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ func TestMain(m *testing.M) {
105105
}
106106
reviewer := rbac.NewReviewer(clientset)
107107

108-
if err = v1beta1.SetupCollectorWebhook(mgr, config.New(), reviewer, nil, nil); err != nil {
108+
if err = v1beta1.SetupCollectorWebhook(mgr, config.New(), reviewer, nil, nil, nil); err != nil {
109109
fmt.Printf("failed to SetupWebhookWithManager: %v", err)
110110
os.Exit(1)
111111
}

0 commit comments

Comments
 (0)