From a165b80678876fb4bfc9427330802ea5e039d2ea Mon Sep 17 00:00:00 2001 From: omris94 <46892443+omris94@users.noreply.github.com> Date: Wed, 10 Apr 2024 10:27:22 +0200 Subject: [PATCH] Support enabling enforcement per namespace while using defaultShadow enforcement mode (#407) --- .../controllers/intents_controller.go | 6 +++-- .../controllers/intents_controller_test.go | 1 + .../external_traffic_network_policy_test.go | 5 ++-- ...fic_network_policy_with_no_intents_test.go | 5 ++-- .../intents_reconcilers/istio_policy.go | 7 +++-- .../intents_reconcilers/istio_policy_test.go | 1 + .../intents_reconcilers/kafka_acls.go | 8 ++++-- .../intents_reconcilers/kafka_acls_test.go | 1 + .../builders/ingress_network_policy_test.go | 27 +++++++++++++++++++ .../networkpolicy/builders/test_base.go | 1 + .../networkpolicy/reconciler.go | 5 +++- .../protected_services/should_protect.go | 12 +++++++-- .../controllers/istiopolicy/policy_manager.go | 6 +++-- .../istiopolicy/policy_manager_test.go | 2 +- .../controllers/pod_reconcilers/pods.go | 5 ++-- .../controllers/pod_reconcilers/pods_test.go | 2 +- src/operator/main.go | 7 +++-- src/shared/operatorconfig/config.go | 13 +++++---- 18 files changed, 88 insertions(+), 26 deletions(-) diff --git a/src/operator/controllers/intents_controller.go b/src/operator/controllers/intents_controller.go index a14ef9da7..4f4531ba3 100644 --- a/src/operator/controllers/intents_controller.go +++ b/src/operator/controllers/intents_controller.go @@ -19,6 +19,7 @@ package controllers import ( "context" "fmt" + "github.com/amit7itz/goset" otterizev1alpha3 "github.com/otterize/intents-operator/src/operator/api/v1alpha3" "github.com/otterize/intents-operator/src/operator/controllers/intents_reconcilers" "github.com/otterize/intents-operator/src/operator/controllers/intents_reconcilers/database" @@ -80,14 +81,15 @@ func NewIntentsReconciler( otterizeClient operator_cloud_client.CloudClient, operatorPodName string, operatorPodNamespace string, + enforcedNamespaces *goset.Set[string], additionalReconcilers ...reconcilergroup.ReconcilerWithEvents, ) *IntentsReconciler { serviceIdResolver := serviceidresolver.NewResolver(client) reconcilers := []reconcilergroup.ReconcilerWithEvents{ intents_reconcilers.NewPodLabelReconciler(client, scheme), - intents_reconcilers.NewKafkaACLReconciler(client, scheme, kafkaServerStore, enforcementConfig.EnableKafkaACL, kafkaacls.NewKafkaIntentsAdmin, enforcementConfig.EnforcementDefaultState, operatorPodName, operatorPodNamespace, serviceIdResolver), - intents_reconcilers.NewIstioPolicyReconciler(client, scheme, restrictToNamespaces, enforcementConfig.EnableIstioPolicy, enforcementConfig.EnforcementDefaultState), + intents_reconcilers.NewKafkaACLReconciler(client, scheme, kafkaServerStore, enforcementConfig.EnableKafkaACL, kafkaacls.NewKafkaIntentsAdmin, enforcementConfig.EnforcementDefaultState, operatorPodName, operatorPodNamespace, serviceIdResolver, enforcedNamespaces), + intents_reconcilers.NewIstioPolicyReconciler(client, scheme, restrictToNamespaces, enforcementConfig.EnableIstioPolicy, enforcementConfig.EnforcementDefaultState, enforcedNamespaces), } reconcilers = append(reconcilers, additionalReconcilers...) reconcilersGroup := reconcilergroup.NewGroup( diff --git a/src/operator/controllers/intents_controller_test.go b/src/operator/controllers/intents_controller_test.go index f44be17d2..2a8a70743 100644 --- a/src/operator/controllers/intents_controller_test.go +++ b/src/operator/controllers/intents_controller_test.go @@ -33,6 +33,7 @@ func (s *IntentsControllerTestSuite) SetupTest() { "", "", nil, + nil, ) } diff --git a/src/operator/controllers/intents_reconcilers/external_traffic_network_policy/external_traffic_network_policy_test.go b/src/operator/controllers/intents_reconcilers/external_traffic_network_policy/external_traffic_network_policy_test.go index ea3681ae2..c61227ec8 100644 --- a/src/operator/controllers/intents_reconcilers/external_traffic_network_policy/external_traffic_network_policy_test.go +++ b/src/operator/controllers/intents_reconcilers/external_traffic_network_policy/external_traffic_network_policy_test.go @@ -3,6 +3,7 @@ package external_traffic_network_policy import ( "context" "fmt" + "github.com/amit7itz/goset" "github.com/google/uuid" otterizev1alpha3 "github.com/otterize/intents-operator/src/operator/api/v1alpha3" "github.com/otterize/intents-operator/src/operator/controllers" @@ -71,7 +72,7 @@ func (s *ExternalNetworkPolicyReconcilerTestSuite) SetupTest() { defaultActive := !isShadowMode netpolHandler := external_traffic.NewNetworkPolicyHandler(s.Mgr.GetClient(), s.TestEnv.Scheme, allowexternaltraffic.IfBlockedByOtterize) s.defaultDenyReconciler = protected_service_reconcilers.NewDefaultDenyReconciler(s.Mgr.GetClient(), netpolHandler, true) - netpolReconciler := networkpolicy.NewReconciler(s.Mgr.GetClient(), s.TestEnv.Scheme, netpolHandler, []string{}, true, defaultActive, []networkpolicy.IngressRuleBuilder{builders.NewIngressNetpolBuilder()}, nil) + netpolReconciler := networkpolicy.NewReconciler(s.Mgr.GetClient(), s.TestEnv.Scheme, netpolHandler, []string{}, goset.NewSet[string](), true, defaultActive, []networkpolicy.IngressRuleBuilder{builders.NewIngressNetpolBuilder()}, nil) epReconciler := effectivepolicy.NewGroupReconciler(s.Mgr.GetClient(), s.TestEnv.Scheme, netpolReconciler) s.EffectivePolicyIntentsReconciler = intents_reconcilers.NewServiceEffectiveIntentsReconciler(s.Mgr.GetClient(), s.TestEnv.Scheme, epReconciler) s.Require().NoError((&controllers.IntentsReconciler{}).InitIntentsServerIndices(s.Mgr)) @@ -86,7 +87,7 @@ func (s *ExternalNetworkPolicyReconcilerTestSuite) SetupTest() { s.IngressReconciler.InjectRecorder(recorder) s.Require().NoError(err) - s.podWatcher = pod_reconcilers.NewPodWatcher(s.Mgr.GetClient(), recorder, []string{}, defaultActive, true) + s.podWatcher = pod_reconcilers.NewPodWatcher(s.Mgr.GetClient(), recorder, []string{}, defaultActive, true, goset.NewSet[string]()) err = s.podWatcher.InitIntentsClientIndices(s.Mgr) s.Require().NoError(err) diff --git a/src/operator/controllers/intents_reconcilers/external_traffic_network_policy/external_traffic_network_policy_with_no_intents_test.go b/src/operator/controllers/intents_reconcilers/external_traffic_network_policy/external_traffic_network_policy_with_no_intents_test.go index c9531df8c..3c657a18c 100644 --- a/src/operator/controllers/intents_reconcilers/external_traffic_network_policy/external_traffic_network_policy_with_no_intents_test.go +++ b/src/operator/controllers/intents_reconcilers/external_traffic_network_policy/external_traffic_network_policy_with_no_intents_test.go @@ -3,6 +3,7 @@ package external_traffic_network_policy import ( "context" "fmt" + "github.com/amit7itz/goset" otterizev1alpha3 "github.com/otterize/intents-operator/src/operator/api/v1alpha3" "github.com/otterize/intents-operator/src/operator/controllers" "github.com/otterize/intents-operator/src/operator/controllers/external_traffic" @@ -63,7 +64,7 @@ func (s *ExternalNetworkPolicyReconcilerWithNoIntentsTestSuite) SetupTest() { recorder := s.Mgr.GetEventRecorderFor("intents-operator") netpolHandler := external_traffic.NewNetworkPolicyHandler(s.Mgr.GetClient(), s.TestEnv.Scheme, allowexternaltraffic.Always) - netpolReconciler := networkpolicy.NewReconciler(s.Mgr.GetClient(), s.TestEnv.Scheme, netpolHandler, []string{}, true, true, []networkpolicy.IngressRuleBuilder{builders.NewIngressNetpolBuilder()}, nil) + netpolReconciler := networkpolicy.NewReconciler(s.Mgr.GetClient(), s.TestEnv.Scheme, netpolHandler, []string{}, goset.NewSet[string](), true, true, []networkpolicy.IngressRuleBuilder{builders.NewIngressNetpolBuilder()}, nil) groupReconciler := effectivepolicy.NewGroupReconciler(s.Mgr.GetClient(), s.TestEnv.Scheme, netpolReconciler) s.EffectivePolicyIntentsReconciler = intents_reconcilers.NewServiceEffectiveIntentsReconciler(s.Mgr.GetClient(), s.TestEnv.Scheme, groupReconciler) s.Require().NoError((&controllers.IntentsReconciler{}).InitIntentsServerIndices(s.Mgr)) @@ -78,7 +79,7 @@ func (s *ExternalNetworkPolicyReconcilerWithNoIntentsTestSuite) SetupTest() { s.IngressReconciler.InjectRecorder(recorder) s.Require().NoError(err) - s.podWatcher = pod_reconcilers.NewPodWatcher(s.Mgr.GetClient(), recorder, []string{}, true, true) + s.podWatcher = pod_reconcilers.NewPodWatcher(s.Mgr.GetClient(), recorder, []string{}, true, true, goset.NewSet[string]()) err = s.podWatcher.InitIntentsClientIndices(s.Mgr) s.Require().NoError(err) diff --git a/src/operator/controllers/intents_reconcilers/istio_policy.go b/src/operator/controllers/intents_reconcilers/istio_policy.go index 4d048017f..70998c7d4 100644 --- a/src/operator/controllers/intents_reconcilers/istio_policy.go +++ b/src/operator/controllers/intents_reconcilers/istio_policy.go @@ -2,6 +2,7 @@ package intents_reconcilers import ( "context" + "github.com/amit7itz/goset" otterizev1alpha3 "github.com/otterize/intents-operator/src/operator/api/v1alpha3" "github.com/otterize/intents-operator/src/operator/controllers/intents_reconcilers/consts" istiopolicy "github.com/otterize/intents-operator/src/operator/controllers/istiopolicy" @@ -31,7 +32,9 @@ func NewIstioPolicyReconciler( s *runtime.Scheme, restrictToNamespaces []string, enableIstioPolicyCreation bool, - enforcementDefaultState bool) *IstioPolicyReconciler { + enforcementDefaultState bool, + enforcedNamespaces *goset.Set[string], +) *IstioPolicyReconciler { reconciler := &IstioPolicyReconciler{ Client: c, Scheme: s, @@ -42,7 +45,7 @@ func NewIstioPolicyReconciler( } reconciler.policyManager = istiopolicy.NewPolicyManager(c, &reconciler.InjectableRecorder, restrictToNamespaces, - reconciler.enforcementDefaultState, reconciler.enableIstioPolicyCreation) + reconciler.enforcementDefaultState, reconciler.enableIstioPolicyCreation, enforcedNamespaces) return reconciler } diff --git a/src/operator/controllers/intents_reconcilers/istio_policy_test.go b/src/operator/controllers/intents_reconcilers/istio_policy_test.go index 2d6508d94..63b5eb2d4 100644 --- a/src/operator/controllers/intents_reconcilers/istio_policy_test.go +++ b/src/operator/controllers/intents_reconcilers/istio_policy_test.go @@ -42,6 +42,7 @@ func (s *IstioPolicyReconcilerTestSuite) SetupTest() { restrictToNamespaces, true, true, + nil, ) s.Reconciler.Recorder = s.Recorder diff --git a/src/operator/controllers/intents_reconcilers/kafka_acls.go b/src/operator/controllers/intents_reconcilers/kafka_acls.go index 5978d2c44..6b255ff59 100644 --- a/src/operator/controllers/intents_reconcilers/kafka_acls.go +++ b/src/operator/controllers/intents_reconcilers/kafka_acls.go @@ -2,6 +2,7 @@ package intents_reconcilers import ( "context" + "github.com/amit7itz/goset" otterizev1alpha3 "github.com/otterize/intents-operator/src/operator/api/v1alpha3" "github.com/otterize/intents-operator/src/operator/controllers/intents_reconcilers/consts" "github.com/otterize/intents-operator/src/operator/controllers/intents_reconcilers/protected_services" @@ -38,6 +39,7 @@ type KafkaACLReconciler struct { operatorPodName string operatorPodNamespace string serviceResolver serviceidresolver.ServiceResolver + activeNamespaces *goset.Set[string] injectablerecorder.InjectableRecorder } @@ -51,6 +53,7 @@ func NewKafkaACLReconciler( operatorPodName string, operatorPodNamespace string, serviceResolver serviceidresolver.ServiceResolver, + activeNamespaces *goset.Set[string], ) *KafkaACLReconciler { return &KafkaACLReconciler{ client: client, @@ -62,6 +65,7 @@ func NewKafkaACLReconciler( operatorPodName: operatorPodName, operatorPodNamespace: operatorPodNamespace, serviceResolver: serviceResolver, + activeNamespaces: activeNamespaces, } } @@ -88,7 +92,7 @@ func (r *KafkaACLReconciler) applyACLs(ctx context.Context, intents *otterizev1a if err := r.KafkaServersStore.MapErr(func(serverName types.NamespacedName, config *otterizev1alpha3.KafkaServerConfig, tls otterizev1alpha3.TLSSource) error { intentsForServer := intentsByServer[serverName] - shouldCreatePolicy, err := protected_services.IsServerEnforcementEnabledDueToProtectionOrDefaultState(ctx, r.client, serverName.Name, serverName.Namespace, r.enforcementDefaultState) + shouldCreatePolicy, err := protected_services.IsServerEnforcementEnabledDueToProtectionOrDefaultState(ctx, r.client, serverName.Name, serverName.Namespace, r.enforcementDefaultState, r.activeNamespaces) if err != nil { return errors.Wrap(err) } @@ -130,7 +134,7 @@ func (r *KafkaACLReconciler) applyACLs(ctx context.Context, intents *otterizev1a func (r *KafkaACLReconciler) RemoveACLs(ctx context.Context, intents *otterizev1alpha3.ClientIntents) error { return r.KafkaServersStore.MapErr(func(serverName types.NamespacedName, config *otterizev1alpha3.KafkaServerConfig, tls otterizev1alpha3.TLSSource) error { - shouldCreatePolicy, err := protected_services.IsServerEnforcementEnabledDueToProtectionOrDefaultState(ctx, r.client, serverName.Name, serverName.Namespace, r.enforcementDefaultState) + shouldCreatePolicy, err := protected_services.IsServerEnforcementEnabledDueToProtectionOrDefaultState(ctx, r.client, serverName.Name, serverName.Namespace, r.enforcementDefaultState, r.activeNamespaces) if err != nil { return errors.Wrap(err) } diff --git a/src/operator/controllers/intents_reconcilers/kafka_acls_test.go b/src/operator/controllers/intents_reconcilers/kafka_acls_test.go index 5f28e2708..af923fbfc 100644 --- a/src/operator/controllers/intents_reconcilers/kafka_acls_test.go +++ b/src/operator/controllers/intents_reconcilers/kafka_acls_test.go @@ -121,6 +121,7 @@ func (s *KafkaACLReconcilerTestSuite) initKafkaIntentsAdmin(enableAclCreation bo operatorPodName, s.operatorNamespace, s.mockServiceResolver, + nil, ) s.recorder = record.NewFakeRecorder(100) s.Reconciler.InjectRecorder(s.recorder) diff --git a/src/operator/controllers/intents_reconcilers/networkpolicy/builders/ingress_network_policy_test.go b/src/operator/controllers/intents_reconcilers/networkpolicy/builders/ingress_network_policy_test.go index df7bb3874..62082458b 100644 --- a/src/operator/controllers/intents_reconcilers/networkpolicy/builders/ingress_network_policy_test.go +++ b/src/operator/controllers/intents_reconcilers/networkpolicy/builders/ingress_network_policy_test.go @@ -3,6 +3,7 @@ package builders import ( "context" "fmt" + "github.com/amit7itz/goset" otterizev1alpha3 "github.com/otterize/intents-operator/src/operator/api/v1alpha3" "github.com/otterize/intents-operator/src/operator/controllers/intents_reconcilers" "github.com/otterize/intents-operator/src/operator/controllers/intents_reconcilers/consts" @@ -45,7 +46,9 @@ func (s *NetworkPolicyReconcilerTestSuite) testCreateNetworkPolicy( formattedTargetServer string, defaultEnforcementState bool, protectedServices []otterizev1alpha3.ProtectedService, + enforcedNamespaces *goset.Set[string], ) { + s.Reconciler.EnforcedNamespaces = enforcedNamespaces s.Reconciler.EnforcementDefaultState = defaultEnforcementState namespacedName := types.NamespacedName{ Namespace: testNamespace, @@ -182,6 +185,27 @@ func (s *NetworkPolicyReconcilerTestSuite) TestCreateNetworkPolicy() { formattedTargetServer, true, nil, + goset.NewSet[string](), + ) + s.ExpectEvent(consts.ReasonCreatedNetworkPolicies) +} + +func (s *NetworkPolicyReconcilerTestSuite) TestCreateNetworkPolicyActiveNamespace() { + clientIntentsName := "client-intents" + policyName := "test-server-access" + serviceName := "test-client" + serverNamespace := testNamespace + formattedTargetServer := "test-server-test-namespace-8ddecb" + + s.testCreateNetworkPolicy( + clientIntentsName, + serverNamespace, + serviceName, + policyName, + formattedTargetServer, + false, + nil, + goset.FromSlice([]string{serverNamespace}), ) s.ExpectEvent(consts.ReasonCreatedNetworkPolicies) } @@ -211,6 +235,7 @@ func (s *NetworkPolicyReconcilerTestSuite) TestCreateNetworkPolicyWithProtectedS formattedTargetServer, false, protectedService, + goset.NewSet[string](), ) s.ExpectEvent(consts.ReasonCreatedNetworkPolicies) } @@ -251,6 +276,7 @@ func (s *NetworkPolicyReconcilerTestSuite) TestCreateNetworkPolicyWithProtectedS formattedTargetServer, false, protectedServices, + goset.NewSet[string](), ) s.ExpectEvent(consts.ReasonCreatedNetworkPolicies) } @@ -270,6 +296,7 @@ func (s *NetworkPolicyReconcilerTestSuite) TestNetworkPolicyCreateCrossNamespace formattedTargetServer, true, nil, + goset.NewSet[string](), ) s.ExpectEvent(consts.ReasonCreatedNetworkPolicies) } diff --git a/src/operator/controllers/intents_reconcilers/networkpolicy/builders/test_base.go b/src/operator/controllers/intents_reconcilers/networkpolicy/builders/test_base.go index b5094910a..2add520a1 100644 --- a/src/operator/controllers/intents_reconcilers/networkpolicy/builders/test_base.go +++ b/src/operator/controllers/intents_reconcilers/networkpolicy/builders/test_base.go @@ -50,6 +50,7 @@ func (s *RulesBuilderTestSuiteBase) SetupTest() { s.scheme, s.externalNetpolHandler, restrictToNamespaces, + nil, true, true, nil, diff --git a/src/operator/controllers/intents_reconcilers/networkpolicy/reconciler.go b/src/operator/controllers/intents_reconcilers/networkpolicy/reconciler.go index ff006c4ec..d1621408a 100644 --- a/src/operator/controllers/intents_reconcilers/networkpolicy/reconciler.go +++ b/src/operator/controllers/intents_reconcilers/networkpolicy/reconciler.go @@ -49,6 +49,7 @@ type Reconciler struct { client.Client Scheme *runtime.Scheme RestrictToNamespaces []string + EnforcedNamespaces *goset.Set[string] EnableNetworkPolicyCreation bool EnforcementDefaultState bool injectablerecorder.InjectableRecorder @@ -62,6 +63,7 @@ func NewReconciler( s *runtime.Scheme, externalNetpolHandler ExternalNetpolHandler, restrictToNamespaces []string, + enforcedNamespaces *goset.Set[string], enableNetworkPolicyCreation bool, enforcementDefaultState bool, ingressBuilders []IngressRuleBuilder, @@ -71,6 +73,7 @@ func NewReconciler( Client: c, Scheme: s, RestrictToNamespaces: restrictToNamespaces, + EnforcedNamespaces: enforcedNamespaces, EnableNetworkPolicyCreation: enableNetworkPolicyCreation, EnforcementDefaultState: enforcementDefaultState, egressRuleBuilders: egressBuilders, @@ -216,7 +219,7 @@ func (r *Reconciler) buildIngressRules(ctx context.Context, ep effectivepolicy.S if len(ep.CalledBy) == 0 || len(r.ingressRuleBuilders) == 0 { return rules, false, nil } - shouldCreatePolicy, err := protected_services.IsServerEnforcementEnabledDueToProtectionOrDefaultState(ctx, r.Client, ep.Service.Name, ep.Service.Namespace, r.EnforcementDefaultState) + shouldCreatePolicy, err := protected_services.IsServerEnforcementEnabledDueToProtectionOrDefaultState(ctx, r.Client, ep.Service.Name, ep.Service.Namespace, r.EnforcementDefaultState, r.EnforcedNamespaces) if err != nil { return rules, false, errors.Wrap(err) } diff --git a/src/operator/controllers/intents_reconcilers/protected_services/should_protect.go b/src/operator/controllers/intents_reconcilers/protected_services/should_protect.go index 17d66c0da..75aa8eabd 100644 --- a/src/operator/controllers/intents_reconcilers/protected_services/should_protect.go +++ b/src/operator/controllers/intents_reconcilers/protected_services/should_protect.go @@ -2,6 +2,7 @@ package protected_services import ( "context" + "github.com/amit7itz/goset" otterizev1alpha3 "github.com/otterize/intents-operator/src/operator/api/v1alpha3" "github.com/otterize/intents-operator/src/shared/errors" "github.com/sirupsen/logrus" @@ -10,13 +11,20 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -func IsServerEnforcementEnabledDueToProtectionOrDefaultState(ctx context.Context, kube client.Client, serverName string, serverNamespace string, enforcementDefaultState bool) (bool, error) { +func IsServerEnforcementEnabledDueToProtectionOrDefaultState(ctx context.Context, kube client.Client, serverName string, serverNamespace string, enforcementDefaultState bool, activeNamespaces *goset.Set[string]) (bool, error) { if enforcementDefaultState { logrus.Debug("Enforcement is default on, so all services should be protected") return true, nil } + logrus.Debug("Protected services are enabled") - logrus.Debug("Protected services are enabled, checking if server is in protected list") + logrus.Debugf("checking if server's namespace is in acrive namespaces") + if activeNamespaces != nil && activeNamespaces.Contains(serverNamespace) { + logrus.Debugf("Server %s in namespace %s is in active namespaces", serverName, serverNamespace) + return true, nil + } + + logrus.Debugf("checking if server is in protected list") var protectedServicesResources otterizev1alpha3.ProtectedServiceList err := kube.List(ctx, &protectedServicesResources, client.MatchingFields{otterizev1alpha3.OtterizeProtectedServiceNameIndexField: serverName}, diff --git a/src/operator/controllers/istiopolicy/policy_manager.go b/src/operator/controllers/istiopolicy/policy_manager.go index 24721df9e..4de1ea076 100644 --- a/src/operator/controllers/istiopolicy/policy_manager.go +++ b/src/operator/controllers/istiopolicy/policy_manager.go @@ -45,6 +45,7 @@ type PolicyManagerImpl struct { client client.Client recorder *injectablerecorder.InjectableRecorder restrictToNamespaces []string + activeNamespaces *goset.Set[string] enforcementDefaultState bool enableIstioPolicyCreation bool } @@ -56,13 +57,14 @@ type PolicyManager interface { UpdateServerSidecar(ctx context.Context, clientIntents *v1alpha3.ClientIntents, serverName string, missingSideCar bool) error } -func NewPolicyManager(client client.Client, recorder *injectablerecorder.InjectableRecorder, restrictedNamespaces []string, enforcementDefaultState bool, istioEnforcementEnabled bool) *PolicyManagerImpl { +func NewPolicyManager(client client.Client, recorder *injectablerecorder.InjectableRecorder, restrictedNamespaces []string, enforcementDefaultState bool, istioEnforcementEnabled bool, activeNamespaces *goset.Set[string]) *PolicyManagerImpl { return &PolicyManagerImpl{ client: client, recorder: recorder, restrictToNamespaces: restrictedNamespaces, enforcementDefaultState: enforcementDefaultState, enableIstioPolicyCreation: istioEnforcementEnabled, + activeNamespaces: activeNamespaces, } } @@ -321,7 +323,7 @@ func (c *PolicyManagerImpl) createOrUpdatePolicies( continue } shouldCreatePolicy, err := protected_services.IsServerEnforcementEnabledDueToProtectionOrDefaultState( - ctx, c.client, intent.GetTargetServerName(), intent.GetTargetServerNamespace(clientIntents.Namespace), c.enforcementDefaultState) + ctx, c.client, intent.GetTargetServerName(), intent.GetTargetServerNamespace(clientIntents.Namespace), c.enforcementDefaultState, c.activeNamespaces) if err != nil { return nil, errors.Wrap(err) } diff --git a/src/operator/controllers/istiopolicy/policy_manager_test.go b/src/operator/controllers/istiopolicy/policy_manager_test.go index 92e70d663..ac21e46e1 100644 --- a/src/operator/controllers/istiopolicy/policy_manager_test.go +++ b/src/operator/controllers/istiopolicy/policy_manager_test.go @@ -27,7 +27,7 @@ type PolicyManagerTestSuite struct { func (s *PolicyManagerTestSuite) SetupTest() { s.MocksSuiteBase.SetupTest() - s.admin = NewPolicyManager(s.Client, &injectablerecorder.InjectableRecorder{Recorder: s.Recorder}, []string{}, true, true) + s.admin = NewPolicyManager(s.Client, &injectablerecorder.InjectableRecorder{Recorder: s.Recorder}, []string{}, true, true, nil) } func (s *PolicyManagerTestSuite) TearDownTest() { diff --git a/src/operator/controllers/pod_reconcilers/pods.go b/src/operator/controllers/pod_reconcilers/pods.go index 520363642..73ed93843 100644 --- a/src/operator/controllers/pod_reconcilers/pods.go +++ b/src/operator/controllers/pod_reconcilers/pods.go @@ -3,6 +3,7 @@ package pod_reconcilers import ( "context" "fmt" + "github.com/amit7itz/goset" otterizev1alpha3 "github.com/otterize/intents-operator/src/operator/api/v1alpha3" "github.com/otterize/intents-operator/src/operator/controllers/istiopolicy" "github.com/otterize/intents-operator/src/prometheus" @@ -38,9 +39,9 @@ type PodWatcher struct { injectablerecorder.InjectableRecorder } -func NewPodWatcher(c client.Client, eventRecorder record.EventRecorder, watchedNamespaces []string, enforcementDefaultState bool, istioEnforcementEnabled bool) *PodWatcher { +func NewPodWatcher(c client.Client, eventRecorder record.EventRecorder, watchedNamespaces []string, enforcementDefaultState bool, istioEnforcementEnabled bool, activeNamespaces *goset.Set[string]) *PodWatcher { recorder := injectablerecorder.InjectableRecorder{Recorder: eventRecorder} - creator := istiopolicy.NewPolicyManager(c, &recorder, watchedNamespaces, enforcementDefaultState, istioEnforcementEnabled) + creator := istiopolicy.NewPolicyManager(c, &recorder, watchedNamespaces, enforcementDefaultState, istioEnforcementEnabled, activeNamespaces) return &PodWatcher{ Client: c, serviceIdResolver: serviceidresolver.NewResolver(c), diff --git a/src/operator/controllers/pod_reconcilers/pods_test.go b/src/operator/controllers/pod_reconcilers/pods_test.go index fecc78155..ea70b5162 100644 --- a/src/operator/controllers/pod_reconcilers/pods_test.go +++ b/src/operator/controllers/pod_reconcilers/pods_test.go @@ -48,7 +48,7 @@ func (s *WatcherPodLabelReconcilerTestSuite) SetupSuite() { func (s *WatcherPodLabelReconcilerTestSuite) SetupTest() { s.ControllerManagerTestSuiteBase.SetupTest() recorder := s.Mgr.GetEventRecorderFor("intents-operator") - s.Reconciler = NewPodWatcher(s.Mgr.GetClient(), recorder, []string{}, true, true) + s.Reconciler = NewPodWatcher(s.Mgr.GetClient(), recorder, []string{}, true, true, nil) s.Require().NoError(s.Reconciler.InitIntentsClientIndices(s.Mgr)) } diff --git a/src/operator/main.go b/src/operator/main.go index 9d1f26330..74fd6122f 100644 --- a/src/operator/main.go +++ b/src/operator/main.go @@ -19,6 +19,7 @@ package main import ( "context" "fmt" + "github.com/amit7itz/goset" "github.com/bombsimon/logrusr/v3" "github.com/google/uuid" otterizev1alpha2 "github.com/otterize/intents-operator/src/operator/api/v1alpha2" @@ -128,6 +129,7 @@ func main() { selfSignedCert := viper.GetBool(operatorconfig.SelfSignedCertKey) allowExternalTraffic := allowexternaltraffic.Enum(viper.GetString(operatorconfig.AllowExternalTrafficKey)) watchedNamespaces := viper.GetStringSlice(operatorconfig.WatchedNamespacesKey) + enforcedNamespaces := goset.FromSlice(viper.GetStringSlice(operatorconfig.ActiveEnforcementNamespacesKey)) enforcementConfig := controllers.EnforcementConfig{ EnforcementDefaultState: viper.GetBool(operatorconfig.EnforcementDefaultStateKey), EnableNetworkPolicy: viper.GetBool(operatorconfig.EnableNetworkPolicyKey), @@ -221,7 +223,7 @@ func main() { additionalIntentsReconcilers := make([]reconcilergroup.ReconcilerWithEvents, 0) svcNetworkPolicyBuilder := builders.NewPortNetworkPolicyReconciler(mgr.GetClient()) dnsServerNetpolBuilder := builders.NewIngressDNSServerAutoAllowNetpolBuilder() - epNetpolReconciler := networkpolicy.NewReconciler(mgr.GetClient(), scheme, extNetpolHandler, watchedNamespaces, enforcementConfig.EnableNetworkPolicy, enforcementConfig.EnforcementDefaultState, + epNetpolReconciler := networkpolicy.NewReconciler(mgr.GetClient(), scheme, extNetpolHandler, watchedNamespaces, enforcedNamespaces, enforcementConfig.EnableNetworkPolicy, enforcementConfig.EnforcementDefaultState, []networkpolicy.IngressRuleBuilder{ingressRulesBuilder, svcNetworkPolicyBuilder, dnsServerNetpolBuilder}, make([]networkpolicy.EgressRuleBuilder, 0)) epGroupReconciler := effectivepolicy.NewGroupReconciler(mgr.GetClient(), scheme, epNetpolReconciler) if enforcementConfig.EnableEgressNetworkPolicyReconcilers { @@ -401,6 +403,7 @@ func main() { otterizeCloudClient, podName, podNamespace, + enforcedNamespaces, additionalIntentsReconcilers..., ) @@ -464,7 +467,7 @@ func main() { logrus.WithError(err).Panic("unable to create controller", "controller", "ProtectedServices") } - podWatcher := pod_reconcilers.NewPodWatcher(mgr.GetClient(), mgr.GetEventRecorderFor("intents-operator"), watchedNamespaces, enforcementConfig.EnforcementDefaultState, enforcementConfig.EnableIstioPolicy) + podWatcher := pod_reconcilers.NewPodWatcher(mgr.GetClient(), mgr.GetEventRecorderFor("intents-operator"), watchedNamespaces, enforcementConfig.EnforcementDefaultState, enforcementConfig.EnableIstioPolicy, enforcedNamespaces) nsWatcher := pod_reconcilers.NewNamespaceWatcher(mgr.GetClient()) svcWatcher := port_network_policy.NewServiceWatcher(mgr.GetClient(), mgr.GetEventRecorderFor("intents-operator"), epGroupReconciler) diff --git a/src/shared/operatorconfig/config.go b/src/shared/operatorconfig/config.go index 1cff9073d..1f43d6aa4 100644 --- a/src/shared/operatorconfig/config.go +++ b/src/shared/operatorconfig/config.go @@ -18,11 +18,12 @@ const ( ProbeAddrDefault = ":8181" EnableLeaderElectionKey = "leader-elect" // Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager EnableLeaderElectionDefault = false - WatchedNamespacesKey = "watched-namespaces" // Namespaces that will be watched by the operator. Specify multiple values by specifying multiple times or separate with commas - KafkaServerTLSCertKey = "kafka-server-tls-cert" // name of tls certificate file - KafkaServerTLSKeyKey = "kafka-server-tls-key" // name of tls private key file - KafkaServerTLSCAKey = "kafka-server-tls-ca" // name of tls ca file - SelfSignedCertKey = "self-signed-cert" // Whether to generate and use a self signed cert as the CA for webhooks + WatchedNamespacesKey = "watched-namespaces" // Namespaces that will be watched by the operator. Specify multiple values by specifying multiple times or separate with commas + ActiveEnforcementNamespacesKey = "active-enforcement-namespaces" // When using the "shadow enforcement" mode, namespaces in this list will be treated as if the enforcement were active + KafkaServerTLSCertKey = "kafka-server-tls-cert" // name of tls certificate file + KafkaServerTLSKeyKey = "kafka-server-tls-key" // name of tls private key file + KafkaServerTLSCAKey = "kafka-server-tls-ca" // name of tls ca file + SelfSignedCertKey = "self-signed-cert" // Whether to generate and use a self signed cert as the CA for webhooks SelfSignedCertDefault = true DisableWebhookServerKey = "disable-webhook-server" // Disable webhook validator server DisableWebhookServerDefault = false @@ -88,6 +89,7 @@ func init() { viper.SetDefault(KafkaServerTLSCAKey, "") viper.SetEnvPrefix(EnvPrefix) viper.SetDefault(WatchedNamespacesKey, nil) + viper.SetDefault(ActiveEnforcementNamespacesKey, nil) viper.SetDefault(EnableDatabasePolicy, EnableDatabasePolicyDefault) viper.SetDefault(RetryDelayTimeKey, RetryDelayTimeDefault) viper.SetDefault(DebugLogKey, DebugLogDefault) @@ -109,6 +111,7 @@ func InitCLIFlags() { pflag.String(ProbeAddrKey, ProbeAddrDefault, "The address the probe endpoint binds to.") pflag.Bool(EnableLeaderElectionKey, EnableLeaderElectionDefault, "Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager.") pflag.StringSlice(WatchedNamespacesKey, nil, "Namespaces that will be watched by the operator. Specify multiple values by specifying multiple times or separate with commas.") + pflag.StringSlice(ActiveEnforcementNamespacesKey, nil, "While using the shadow enforcement mode, namespaces in this list will be treated as if the enforcement were active.") pflag.Bool(EnableIstioPolicyKey, EnableIstioPolicyDefault, "Whether to enable Istio authorization policy creation") pflag.Bool(telemetriesconfig.TelemetryEnabledKey, telemetriesconfig.TelemetryEnabledDefault, "When set to false, all telemetries are disabled") pflag.Bool(telemetriesconfig.TelemetryUsageEnabledKey, telemetriesconfig.TelemetryUsageEnabledDefault, "Whether usage telemetry should be enabled")