diff --git a/internal/controller/trafficprotectionpolicy_controller.go b/internal/controller/trafficprotectionpolicy_controller.go index 1bfb4587..79c5db58 100644 --- a/internal/controller/trafficprotectionpolicy_controller.go +++ b/internal/controller/trafficprotectionpolicy_controller.go @@ -6,6 +6,7 @@ import ( "context" "encoding/json" "fmt" + "slices" "sort" "strings" @@ -1229,7 +1230,7 @@ func (r *TrafficProtectionPolicyReconciler) getCorazaDirectivesForTrafficProtect secRuleEngine = "Off" } - directives := r.Config.Gateway.Coraza.RouteBaseDirectives + directives := slices.Clone(r.Config.Gateway.Coraza.RouteBaseDirectives) directives = append(directives, fmt.Sprintf("SecRuleEngine %s", secRuleEngine)) diff --git a/internal/controller/trafficprotectionpolicy_controller_test.go b/internal/controller/trafficprotectionpolicy_controller_test.go index 1fd6989b..5b9c9e49 100644 --- a/internal/controller/trafficprotectionpolicy_controller_test.go +++ b/internal/controller/trafficprotectionpolicy_controller_test.go @@ -992,6 +992,36 @@ func TestGetCorazaDirectivesForTrafficProtectionPolicy(t *testing.T) { } } +func TestGetCorazaDirectivesDoesNotAliasRouteBaseDirectives(t *testing.T) { + base := make([]string, 2, 8) + base[0] = "Include @crs-setup-conf" + base[1] = "Include @recommended-conf" + + operatorConfig := config.NetworkServicesOperator{ + Gateway: config.GatewayConfig{ + Coraza: config.CorazaConfig{RouteBaseDirectives: base}, + }, + } + reconciler := &TrafficProtectionPolicyReconciler{Config: operatorConfig} + + enforce := reconciler.getCorazaDirectivesForTrafficProtectionPolicy(&policyContext{ptr.To( + newTrafficProtectionPolicy("default", "tpp-enforce", func(tpp *networkingv1alpha.TrafficProtectionPolicy) { + tpp.Spec.Mode = networkingv1alpha.TrafficProtectionPolicyEnforce + }), + )}) + assert.Contains(t, enforce, "SecRuleEngine On") + + reconciler.getCorazaDirectivesForTrafficProtectionPolicy(&policyContext{ptr.To( + newTrafficProtectionPolicy("default", "tpp-observe"), + )}) + + assert.Contains(t, enforce, "SecRuleEngine On", + "second policy leaked into the first via a shared RouteBaseDirectives backing array") + assert.EqualValues(t, []string{"Include @crs-setup-conf", "Include @recommended-conf"}, + reconciler.Config.Gateway.Coraza.RouteBaseDirectives, + "shared base directives were mutated") +} + // nolint:unparam func newTrafficProtectionPolicy( namespace,