Repository: operator-framework/operator-lifecycle-manager
Pull request #3568 (2025-04-30 20:21:59)

✨ Include network policy for all configmap and grpc catalogsources
<!--

Before making a PR, please read our contributing guidelines https://github.com/operator-framework/operator-lifecycle-manager/blob/master/CONTRIBUTING.md

Note: Make sure your branch is rebased to the latest upstream master.

-->

**Description of the change:**

This change updates OLMv0 to generate and reconcile two `NetworkPolicy` objects for each `CatalogSource` where OLMv0 also manages a catalog pod (i.e. configmap and grpc-based catalog sources).
1. GRPC server pods need to listen and receive requests on port 50051
2. Bundle unpack pods need to make connections to the kubernetes API server.

Related implementation details:
- Informer events from network policies are handled by the catalog operator, so any deletions or changes are reverted.
- Each NetworkPolicy gets an owner reference so that it is automatically cleaned up when the catalog source is deleted.
- Each NetworkPolicy uses a pod selector that specifically targets the appropriate pods, so there should be no accidental blocking of traffic of unrelated pods.


Unit tests are updated to ensure that NetworkPolicy objects are handled correctly.

**Motivation for the change:**

By adding NetworkPolicy, we can provide more security to mitigate vulnerabilities and avoid accidental data leaks.

**Architectural changes:**

None (unless you count managing NetworkPolicy for CatalogSources as an architectural change)

<!--
If necessary, briefly describe any architectural changes, other options considered, and/or link to any EPs or design docs
-->

**Testing remarks:**

<!--
Call out any information around how you've tested the code change that may be useful for reviewers. For instance:
 * any edge-cases you have (dis)covered
 * how you have reproduced and tested for regressions in bug fixes
 * how you've tested for flakes in e2e tests or flake fixes
-->

**Reviewer Checklist**
- [ ] Implementation matches the proposed design, or proposal is updated to match implementation
- [ ] Sufficient unit test coverage
- [ ] Sufficient end-to-end test coverage
- [ ] Bug fixes are accompanied by regression test(s)
- [ ] e2e tests and flake fixes are accompanied evidence of flake testing, e.g. executing the test 100(0) times
- [ ] tech debt/todo is accompanied by issue link(s) in comments in the surrounding code
- [ ] Tests are comprehensible, e.g. Ginkgo DSL is being used appropriately
- [ ] Docs updated or added to `/doc`
- [ ] Commit messages sensible and descriptive
- [ ] Tests marked as `[FLAKE]` are truly flaky and have an issue
- [ ] Code is properly formatted


<!--

Note: If this PR is fixing an issue make sure to add a note saying:
Closes #<ISSUE_NUMBER>

-->


perdasilva: @joelanford is this ready for review? it looks pretty good to me =D
joelanford: > is this ready for review? it looks pretty good to me =D

Yes-ish. I think the catalog pod network policy is reviewable. But I realized I also need to add dynamic network policy handling for bundle unpack pods.

I could do that here, or I could do it in a separate PR. I don't really care which.

I also have this listed as a draft because the RFC is still in review: https://docs.google.com/document/d/1TCb2YsSHaXBUnUUFp44Bt2hdsb2jwLnL77imP25QGVs/edit?tab=t.0#heading=h.x3tfh25grvnv
joelanford: Ready for review again!

RFC is here: https://docs.google.com/document/d/1TCb2YsSHaXBUnUUFp44Bt2hdsb2jwLnL77imP25QGVs/edit?tab=t.0#heading=h.x3tfh25grvnv

Patch:
diff --git a/pkg/controller/bundle/bundle_unpacker.go b/pkg/controller/bundle/bundle_unpacker.go
index d16ae7d0d..b8ee90700 100644
--- a/pkg/controller/bundle/bundle_unpacker.go
+++ b/pkg/controller/bundle/bundle_unpacker.go
@@ -48,8 +48,8 @@ const (
 	// attempting to recreate a failed unpack job for a bundle.
 	BundleUnpackRetryMinimumIntervalAnnotationKey = "operatorframework.io/bundle-unpack-min-retry-interval"
 
-	// bundleUnpackRefLabel is used to filter for all unpack jobs for a specific bundle.
-	bundleUnpackRefLabel = "operatorframework.io/bundle-unpack-ref"
+	// BundleUnpackRefLabel is used to filter for all unpack jobs or pods for a specific bundle.
+	BundleUnpackRefLabel = "operatorframework.io/bundle-unpack-ref"
 )
 
 type BundleUnpackResult struct {
@@ -98,7 +98,7 @@ func (c *ConfigMapUnpacker) job(cmRef *corev1.ObjectReference, bundlePath string
 		ObjectMeta: metav1.ObjectMeta{
 			Labels: map[string]string{
 				install.OLMManagedLabelKey: install.OLMManagedLabelValue,
-				bundleUnpackRefLabel:       cmRef.Name,
+				BundleUnpackRefLabel:       cmRef.Name,
 			},
 		},
 		Spec: batchv1.JobSpec{
@@ -108,6 +108,7 @@ func (c *ConfigMapUnpacker) job(cmRef *corev1.ObjectReference, bundlePath string
 					Name: cmRef.Name,
 					Labels: map[string]string{
 						install.OLMManagedLabelKey: install.OLMManagedLabelValue,
+						BundleUnpackRefLabel:       cmRef.Name,
 					},
 				},
 				Spec: corev1.PodSpec{
@@ -665,7 +666,7 @@ func (c *ConfigMapUnpacker) ensureConfigmap(csRef *corev1.ObjectReference, name
 func (c *ConfigMapUnpacker) ensureJob(cmRef *corev1.ObjectReference, bundlePath string, secrets []corev1.LocalObjectReference, timeout time.Duration, unpackRetryInterval time.Duration) (job *batchv1.Job, err error) {
 	fresh := c.job(cmRef, bundlePath, secrets, timeout)
 	var jobs, toDelete []*batchv1.Job
-	jobs, err = c.jobLister.Jobs(fresh.GetNamespace()).List(k8slabels.ValidatedSetSelector{bundleUnpackRefLabel: cmRef.Name})
+	jobs, err = c.jobLister.Jobs(fresh.GetNamespace()).List(k8slabels.ValidatedSetSelector{BundleUnpackRefLabel: cmRef.Name})
 	if err != nil {
 		return
 	}
@@ -676,7 +677,7 @@ func (c *ConfigMapUnpacker) ensureJob(cmRef *corev1.ObjectReference, bundlePath
 		return
 	}
 	if jobWithoutLabel != nil {
-		_, labelExists := jobWithoutLabel.Labels[bundleUnpackRefLabel]
+		_, labelExists := jobWithoutLabel.Labels[BundleUnpackRefLabel]
 		if !labelExists {
 			jobs = append(jobs, jobWithoutLabel)
 		}
diff --git a/pkg/controller/operators/catalog/operator.go b/pkg/controller/operators/catalog/operator.go
index 44f38ef52..6893c87d3 100644
--- a/pkg/controller/operators/catalog/operator.go
+++ b/pkg/controller/operators/catalog/operator.go
@@ -18,6 +18,7 @@ import (
 	"google.golang.org/grpc/connectivity"
 	batchv1 "k8s.io/api/batch/v1"
 	corev1 "k8s.io/api/core/v1"
+	networkingv1 "k8s.io/api/networking/v1"
 	rbacv1 "k8s.io/api/rbac/v1"
 	"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
 	apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
@@ -38,6 +39,7 @@ import (
 	"k8s.io/apimachinery/pkg/util/yaml"
 	batchv1applyconfigurations "k8s.io/client-go/applyconfigurations/batch/v1"
 	corev1applyconfigurations "k8s.io/client-go/applyconfigurations/core/v1"
+	networkingv1applyconfigurations "k8s.io/client-go/applyconfigurations/networking/v1"
 	rbacv1applyconfigurations "k8s.io/client-go/applyconfigurations/rbac/v1"
 	"k8s.io/client-go/dynamic"
 	"k8s.io/client-go/informers"
@@ -600,6 +602,23 @@ func NewOperator(ctx context.Context, kubeconfigPath string, clock utilclock.Clo
 		}
 	}
 
+	// Wire NetworkPolicies
+	networkPolicyInformer := k8sInformerFactory.Networking().V1().NetworkPolicies()
+	op.lister.NetworkingV1().RegisterNetworkPolicyLister(metav1.NamespaceAll, networkPolicyInformer.Lister())
+	sharedIndexInformers = append(sharedIndexInformers, networkPolicyInformer.Informer())
+
+	networkPoliciesGVR := networkingv1.SchemeGroupVersion.WithResource("networkpolicies")
+	if err := labelObjects(networkPoliciesGVR, networkPolicyInformer.Informer(), labeller.ObjectLabeler[*networkingv1.NetworkPolicy, *networkingv1applyconfigurations.NetworkPolicyApplyConfiguration](
+		ctx, op.logger, labeller.Filter(networkPoliciesGVR),
+		networkPolicyInformer.Lister().List,
+		networkingv1applyconfigurations.NetworkPolicy,
+		func(namespace string, ctx context.Context, cfg *networkingv1applyconfigurations.NetworkPolicyApplyConfiguration, opts metav1.ApplyOptions) (*networkingv1.NetworkPolicy, error) {
+			return op.opClient.KubernetesInterface().NetworkingV1().NetworkPolicies(namespace).Apply(ctx, cfg, opts)
+		},
+	)); err != nil {
+		return nil, err
+	}
+
 	// Wire Pods for CatalogSource
 	catsrcReq, err := labels.NewRequirement(reconciler.CatalogSourceLabelKey, selection.Exists, nil)
 	if err != nil {
diff --git a/pkg/controller/registry/reconciler/configmap.go b/pkg/controller/registry/reconciler/configmap.go
index f9a63162a..5207265b1 100644
--- a/pkg/controller/registry/reconciler/configmap.go
+++ b/pkg/controller/registry/reconciler/configmap.go
@@ -6,11 +6,11 @@ import (
 	"errors"
 	"fmt"
 
-	"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install"
 	hashutil "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/util/hash"
 	pkgerrors "github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 	corev1 "k8s.io/api/core/v1"
+	networkingv1 "k8s.io/api/networking/v1"
 	rbacv1 "k8s.io/api/rbac/v1"
 	apierrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -19,6 +19,7 @@ import (
 	"k8s.io/utils/ptr"
 
 	"github.com/operator-framework/api/pkg/operators/v1alpha1"
+	"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install"
 	"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient"
 	"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorlister"
 	"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/ownerutil"
@@ -122,6 +123,14 @@ func (s *configMapCatalogSourceDecorator) Pod(image string, defaultPodSecurityCo
 	return pod, nil
 }
 
+func (s *configMapCatalogSourceDecorator) GRPCServerNetworkPolicy() *networkingv1.NetworkPolicy {
+	return DesiredGRPCServerNetworkPolicy(s.CatalogSource, s.Labels())
+}
+
+func (s *configMapCatalogSourceDecorator) UnpackBundlesNetworkPolicy() *networkingv1.NetworkPolicy {
+	return DesiredUnpackBundlesNetworkPolicy(s.CatalogSource)
+}
+
 func (s *configMapCatalogSourceDecorator) ServiceAccount() *corev1.ServiceAccount {
 	sa := &corev1.ServiceAccount{
 		ObjectMeta: metav1.ObjectMeta{
@@ -210,6 +219,26 @@ func (c *ConfigMapRegistryReconciler) currentService(source configMapCatalogSour
 	return service, nil
 }
 
+func (c *ConfigMapRegistryReconciler) currentGRPCServerNetworkPolicy(source configMapCatalogSourceDecorator) *networkingv1.NetworkPolicy {
+	npName := source.GRPCServerNetworkPolicy().GetName()
+	np, err := c.Lister.NetworkingV1().NetworkPolicyLister().NetworkPolicies(source.GetNamespace()).Get(npName)
+	if err != nil {
+		logrus.WithField("networkPolicy", npName).WithError(err).Debug("couldn't find grpc server network policy in cache")
+		return nil
+	}
+	return np
+}
+
+func (c *ConfigMapRegistryReconciler) currentUnpackBundlesNetworkPolicy(source configMapCatalogSourceDecorator) *networkingv1.NetworkPolicy {
+	npName := source.UnpackBundlesNetworkPolicy().GetName()
+	np, err := c.Lister.NetworkingV1().NetworkPolicyLister().NetworkPolicies(source.GetNamespace()).Get(npName)
+	if err != nil {
+		logrus.WithField("networkPolicy", npName).WithError(err).Debug("couldn't find unpack bundles network policy in cache")
+		return nil
+	}
+	return np
+}
+
 func (c *ConfigMapRegistryReconciler) currentServiceAccount(source configMapCatalogSourceDecorator) *corev1.ServiceAccount {
 	serviceAccountName := source.ServiceAccount().GetName()
 	serviceAccount, err := c.Lister.CoreV1().ServiceAccountLister().ServiceAccounts(source.GetNamespace()).Get(serviceAccountName)
@@ -328,6 +357,12 @@ func (c *ConfigMapRegistryReconciler) EnsureRegistryServer(logger *logrus.Entry,
 	}
 
 	//TODO: if any of these error out, we should write a status back (possibly set RegistryServiceStatus to nil so they get recreated)
+	if err := c.ensureGRPCServerNetworkPolicy(source); err != nil {
+		return pkgerrors.Wrapf(err, "error ensuring grpc server network policy: %s", source.GetName())
+	}
+	if err := c.ensureUnpackBundlesNetworkPolicy(source); err != nil {
+		return pkgerrors.Wrapf(err, "error ensuring unpack bundles network policy: %s", source.GetName())
+	}
 	if err := c.ensureServiceAccount(source, overwrite); err != nil {
 		return pkgerrors.Wrapf(err, "error ensuring service account: %s", source.serviceAccountName())
 	}
@@ -365,6 +400,31 @@ func (c *ConfigMapRegistryReconciler) EnsureRegistryServer(logger *logrus.Entry,
 	return nil
 }
 
+func (c *ConfigMapRegistryReconciler) ensureGRPCServerNetworkPolicy(source configMapCatalogSourceDecorator) error {
+	desired := source.GRPCServerNetworkPolicy()
+	current := c.currentGRPCServerNetworkPolicy(source)
+	return c.ensureNetworkPolicy(desired, current)
+}
+
+func (c *ConfigMapRegistryReconciler) ensureUnpackBundlesNetworkPolicy(source configMapCatalogSourceDecorator) error {
+	desired := source.UnpackBundlesNetworkPolicy()
+	current := c.currentUnpackBundlesNetworkPolicy(source)
+	return c.ensureNetworkPolicy(desired, current)
+}
+
+func (c *ConfigMapRegistryReconciler) ensureNetworkPolicy(desired, current *networkingv1.NetworkPolicy) error {
+	if current != nil {
+		if isExpectedNetworkPolicy(desired, current) {
+			return nil
+		}
+		if err := c.OpClient.DeleteNetworkPolicy(current.GetNamespace(), current.GetName(), metav1.NewDeleteOptions(0)); err != nil && !apierrors.IsNotFound(err) {
+			return err
+		}
+	}
+	_, err := c.OpClient.CreateNetworkPolicy(desired)
+	return err
+}
+
 func (c *ConfigMapRegistryReconciler) ensureServiceAccount(source configMapCatalogSourceDecorator, overwrite bool) error {
 	serviceAccount := source.ServiceAccount()
 	if c.currentServiceAccount(source) != nil {
@@ -497,6 +557,30 @@ func (c *ConfigMapRegistryReconciler) CheckRegistryServer(logger *logrus.Entry,
 	// Check on registry resources
 	// TODO: more complex checks for resources
 	// TODO: add gRPC health check
+	np := c.currentGRPCServerNetworkPolicy(source)
+	if np == nil {
+		logger.Error("registry service not healthy: could not get grpc server network policy")
+		healthy = false
+		return
+	}
+	if !isExpectedNetworkPolicy(source.GRPCServerNetworkPolicy(), np) {
+		logger.Error("registry service not healthy: unexpected grpc server network policy")
+		healthy = false
+		return
+	}
+
+	np = c.currentUnpackBundlesNetworkPolicy(source)
+	if np == nil {
+		logger.Error("registry service not healthy: could not get unpack bundles network policy")
+		healthy = false
+		return
+	}
+	if !isExpectedNetworkPolicy(source.UnpackBundlesNetworkPolicy(), np) {
+		logger.Error("registry service not healthy: unexpected unpack bundles network policy")
+		healthy = false
+		return
+	}
+
 	service, err := c.currentService(source)
 	if err != nil {
 		return false, err
diff --git a/pkg/controller/registry/reconciler/grpc.go b/pkg/controller/registry/reconciler/grpc.go
index dacee6a37..57cedd0eb 100644
--- a/pkg/controller/registry/reconciler/grpc.go
+++ b/pkg/controller/registry/reconciler/grpc.go
@@ -19,6 +19,7 @@ import (
 	pkgerrors "github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 	corev1 "k8s.io/api/core/v1"
+	networkingv1 "k8s.io/api/networking/v1"
 	apierrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/labels"
@@ -102,6 +103,14 @@ func (s *grpcCatalogSourceDecorator) Service() (*corev1.Service, error) {
 	return svc, nil
 }
 
+func (s *grpcCatalogSourceDecorator) GRPCServerNetworkPolicy() *networkingv1.NetworkPolicy {
+	return DesiredGRPCServerNetworkPolicy(s.CatalogSource, s.Labels())
+}
+
+func (s *grpcCatalogSourceDecorator) UnpackBundlesNetworkPolicy() *networkingv1.NetworkPolicy {
+	return DesiredUnpackBundlesNetworkPolicy(s.CatalogSource)
+}
+
 func (s *grpcCatalogSourceDecorator) ServiceAccount() *corev1.ServiceAccount {
 	var secrets []corev1.LocalObjectReference
 	blockOwnerDeletion := true
@@ -153,6 +162,26 @@ type GrpcRegistryReconciler struct {
 
 var _ RegistryReconciler = &GrpcRegistryReconciler{}
 
+func (c *GrpcRegistryReconciler) currentGRPCServerNetworkPolicy(source grpcCatalogSourceDecorator) *networkingv1.NetworkPolicy {
+	npName := source.GRPCServerNetworkPolicy().GetName()
+	np, err := c.Lister.NetworkingV1().NetworkPolicyLister().NetworkPolicies(source.GetNamespace()).Get(npName)
+	if err != nil {
+		logrus.WithField("networkPolicy", npName).WithError(err).Debug("couldn't find grpc server network policy in cache")
+		return nil
+	}
+	return np
+}
+
+func (c *GrpcRegistryReconciler) currentUnpackBundlesNetworkPolicy(source grpcCatalogSourceDecorator) *networkingv1.NetworkPolicy {
+	npName := source.UnpackBundlesNetworkPolicy().GetName()
+	np, err := c.Lister.NetworkingV1().NetworkPolicyLister().NetworkPolicies(source.GetNamespace()).Get(npName)
+	if err != nil {
+		logrus.WithField("networkPolicy", npName).WithError(err).Debug("couldn't find unpack bundles network policy in cache")
+		return nil
+	}
+	return np
+}
+
 func (c *GrpcRegistryReconciler) currentService(source grpcCatalogSourceDecorator) (*corev1.Service, error) {
 	protoService, err := source.Service()
 	if err != nil {
@@ -261,6 +290,15 @@ func (c *GrpcRegistryReconciler) EnsureRegistryServer(logger *logrus.Entry, cata
 	}
 
 	//TODO: if any of these error out, we should write a status back (possibly set RegistryServiceStatus to nil so they get recreated)
+	if err := c.ensureGRPCServerNetworkPolicy(source); err != nil {
+		logger.WithError(err).Error("error ensuring registry server: could not ensure grpc server network policy")
+		return pkgerrors.Wrapf(err, "error ensuring grpc server network policy for catalog source %s", source.GetName())
+	}
+	if err := c.ensureUnpackBundlesNetworkPolicy(source); err != nil {
+		logger.WithError(err).Error("error ensuring registry server: could not ensure bundle unpack network policy")
+		return pkgerrors.Wrapf(err, "error ensuring bundle unpack network policy for catalog source %s", source.GetName())
+	}
+
 	sa, err := c.ensureSA(source)
 	if err != nil && !apierrors.IsAlreadyExists(err) {
 		logger.WithError(err).Error("error ensuring registry server: could not ensure registry service account")
@@ -467,6 +505,31 @@ func (c *GrpcRegistryReconciler) ensureService(source grpcCatalogSourceDecorator
 	return err
 }
 
+func (c *GrpcRegistryReconciler) ensureGRPCServerNetworkPolicy(source grpcCatalogSourceDecorator) error {
+	desired := source.GRPCServerNetworkPolicy()
+	current := c.currentGRPCServerNetworkPolicy(source)
+	return c.ensureNetworkPolicy(desired, current)
+}
+
+func (c *GrpcRegistryReconciler) ensureUnpackBundlesNetworkPolicy(source grpcCatalogSourceDecorator) error {
+	desired := source.UnpackBundlesNetworkPolicy()
+	current := c.currentUnpackBundlesNetworkPolicy(source)
+	return c.ensureNetworkPolicy(desired, current)
+}
+
+func (c *GrpcRegistryReconciler) ensureNetworkPolicy(desired, current *networkingv1.NetworkPolicy) error {
+	if current != nil {
+		if isExpectedNetworkPolicy(desired, current) {
+			return nil
+		}
+		if err := c.OpClient.DeleteNetworkPolicy(current.GetNamespace(), current.GetName(), metav1.NewDeleteOptions(0)); err != nil && !apierrors.IsNotFound(err) {
+			return err
+		}
+	}
+	_, err := c.OpClient.CreateNetworkPolicy(desired)
+	return err
+}
+
 func (c *GrpcRegistryReconciler) ensureSA(source grpcCatalogSourceDecorator) (*corev1.ServiceAccount, error) {
 	sa := source.ServiceAccount()
 	if _, err := c.OpClient.CreateServiceAccount(sa); err != nil {
@@ -606,6 +669,28 @@ func (c *GrpcRegistryReconciler) CheckRegistryServer(logger *logrus.Entry, catal
 
 	// Check on registry resources
 	// TODO: add gRPC health check
+	currentNetworkPolicy := c.currentGRPCServerNetworkPolicy(source)
+	if currentNetworkPolicy == nil {
+		logger.Error("registry service not healthy: could not get grpc server network policy")
+		return false, nil
+	}
+	expectedNetworkPolicy := source.GRPCServerNetworkPolicy()
+	if !isExpectedNetworkPolicy(expectedNetworkPolicy, currentNetworkPolicy) {
+		logger.Error("registry service not healthy: unexpected grpc server network policy")
+		return false, nil
+	}
+
+	currentNetworkPolicy = c.currentUnpackBundlesNetworkPolicy(source)
+	if currentNetworkPolicy == nil {
+		logger.Error("registry service not healthy: could not get unpack bundles network policy")
+		return false, nil
+	}
+	expectedNetworkPolicy = source.UnpackBundlesNetworkPolicy()
+	if !isExpectedNetworkPolicy(expectedNetworkPolicy, currentNetworkPolicy) {
+		logger.Error("registry service not healthy: unexpected unpack bundles network policy")
+		return false, nil
+	}
+
 	service, err := c.currentService(source)
 	if err != nil {
 		logger.WithError(err).Error("registry service not healthy: could not get current service")
diff --git a/pkg/controller/registry/reconciler/helpers.go b/pkg/controller/registry/reconciler/helpers.go
new file mode 100644
index 000000000..15f263e7b
--- /dev/null
+++ b/pkg/controller/registry/reconciler/helpers.go
@@ -0,0 +1,121 @@
+package reconciler
+
+import (
+	"fmt"
+
+	corev1 "k8s.io/api/core/v1"
+	networkingv1 "k8s.io/api/networking/v1"
+	"k8s.io/apimachinery/pkg/api/equality"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/util/intstr"
+	"k8s.io/utils/ptr"
+	"sigs.k8s.io/controller-runtime/pkg/client"
+
+	"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/bundle"
+	"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install"
+	"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/ownerutil"
+)
+
+func DesiredGRPCServerNetworkPolicy(catalogSource client.Object, matchLabels map[string]string) *networkingv1.NetworkPolicy {
+	np := &networkingv1.NetworkPolicy{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      fmt.Sprintf("%s-grpc-server", catalogSource.GetName()),
+			Namespace: catalogSource.GetNamespace(),
+			Labels: map[string]string{
+				install.OLMManagedLabelKey: install.OLMManagedLabelValue,
+				CatalogSourceLabelKey:      catalogSource.GetName(),
+			},
+		},
+		Spec: networkingv1.NetworkPolicySpec{
+			PodSelector: metav1.LabelSelector{
+				MatchLabels: matchLabels,
+			},
+			PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress, networkingv1.PolicyTypeEgress},
+			Ingress: []networkingv1.NetworkPolicyIngressRule{
+				{
+					Ports: []networkingv1.NetworkPolicyPort{
+						{
+							Protocol: ptr.To(corev1.ProtocolTCP),
+							Port:     ptr.To(intstr.FromInt32(50051)),
+						},
+					},
+				},
+			},
+		},
+	}
+	ownerutil.AddOwner(np, catalogSource, false, false)
+	return np
+}
+
+func DesiredUnpackBundlesNetworkPolicy(catalogSource client.Object) *networkingv1.NetworkPolicy {
+	np := &networkingv1.NetworkPolicy{
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      fmt.Sprintf("%s-unpack-bundles", catalogSource.GetName()),
+			Namespace: catalogSource.GetNamespace(),
+			Labels: map[string]string{
+				install.OLMManagedLabelKey: install.OLMManagedLabelValue,
+				CatalogSourceLabelKey:      catalogSource.GetName(),
+			},
+		},
+		Spec: networkingv1.NetworkPolicySpec{
+			PodSelector: metav1.LabelSelector{
+				MatchExpressions: []metav1.LabelSelectorRequirement{
+					{
+						Key:      bundle.BundleUnpackRefLabel,
+						Operator: metav1.LabelSelectorOpExists,
+					},
+					{
+						Key:      install.OLMManagedLabelKey,
+						Operator: metav1.LabelSelectorOpIn,
+						Values:   []string{install.OLMManagedLabelValue},
+					},
+				},
+			},
+			PolicyTypes: []networkingv1.PolicyType{networkingv1.PolicyTypeIngress, networkingv1.PolicyTypeEgress},
+			Egress: []networkingv1.NetworkPolicyEgressRule{
+				{
+					Ports: []networkingv1.NetworkPolicyPort{
+						{
+							Protocol: ptr.To(corev1.ProtocolTCP),
+							Port:     ptr.To(intstr.FromInt32(6443)),
+						},
+					},
+				},
+			},
+		},
+	}
+	ownerutil.AddOwner(np, catalogSource, false, false)
+	return np
+}
+
+func isExpectedNetworkPolicy(expected, current *networkingv1.NetworkPolicy) bool {
+	if !equality.Semantic.DeepEqual(expected.Spec, current.Spec) {
+		return false
+	}
+	if !equality.Semantic.DeepDerivative(expected.ObjectMeta.Labels, current.ObjectMeta.Labels) {
+		return false
+	}
+	return true
+}
+
+//
+//func isExpectedNetworkPolicy(desired client.Object, current client.Object) bool {
+//	desired = desired.DeepCopyObject().(client.Object)
+//	current = current.DeepCopyObject().(client.Object)
+//	if v := desired.GetUID(); v == "" {
+//		current.SetUID(v)
+//	}
+//	if v := desired.GetResourceVersion(); v == "" {
+//		current.SetResourceVersion(v)
+//	}
+//	if v := desired.GetGeneration(); v == 0 {
+//		current.SetGeneration(v)
+//	}
+//	if v := desired.GetManagedFields(); len(v) == 0 {
+//		current.SetManagedFields(v)
+//	}
+//	if v := desired.GetCreationTimestamp(); v.IsZero() {
+//		current.SetCreationTimestamp(v)
+//	}
+//	return equality.Semantic.DeepEqual(desired, current)
+//}
diff --git a/pkg/lib/operatorclient/client.go b/pkg/lib/operatorclient/client.go
index b53d2da7d..30593acfa 100644
--- a/pkg/lib/operatorclient/client.go
+++ b/pkg/lib/operatorclient/client.go
@@ -5,6 +5,7 @@ import (
 	"github.com/sirupsen/logrus"
 	appsv1 "k8s.io/api/apps/v1"
 	v1 "k8s.io/api/core/v1"
+	networkingv1 "k8s.io/api/networking/v1"
 	rbacv1 "k8s.io/api/rbac/v1"
 	apiextensions "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -34,6 +35,7 @@ type ClientInterface interface {
 	ClusterRoleClient
 	DeploymentClient
 	ConfigMapClient
+	NetworkPolicyClient
 }
 
 // CustomResourceClient contains methods for the Custom Resource.
@@ -141,6 +143,14 @@ type ConfigMapClient interface {
 	DeleteConfigMap(namespace, name string, options *metav1.DeleteOptions) error
 }
 
+// NetworkPolicyClient contains methods for the NetworkPolicy resource
+type NetworkPolicyClient interface {
+	CreateNetworkPolicy(*networkingv1.NetworkPolicy) (*networkingv1.NetworkPolicy, error)
+	GetNetworkPolicy(namespace, name string) (*networkingv1.NetworkPolicy, error)
+	UpdateNetworkPolicy(modified *networkingv1.NetworkPolicy) (*networkingv1.NetworkPolicy, error)
+	DeleteNetworkPolicy(namespace, name string, options *metav1.DeleteOptions) error
+}
+
 // Interface assertion.
 var _ ClientInterface = &Client{}
 
diff --git a/pkg/lib/operatorclient/networkpolicy.go b/pkg/lib/operatorclient/networkpolicy.go
new file mode 100644
index 000000000..23b447ddf
--- /dev/null
+++ b/pkg/lib/operatorclient/networkpolicy.go
@@ -0,0 +1,45 @@
+package operatorclient
+
+import (
+	"context"
+	"fmt"
+
+	networkingv1 "k8s.io/api/networking/v1"
+	apierrors "k8s.io/apimachinery/pkg/api/errors"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/types"
+	"k8s.io/klog"
+)
+
+// CreateNetworkPolicy creates the NetworkPolicy.
+func (c *Client) CreateNetworkPolicy(in *networkingv1.NetworkPolicy) (*networkingv1.NetworkPolicy, error) {
+	createdNP, err := c.NetworkingV1().NetworkPolicies(in.GetNamespace()).Create(context.TODO(), in, metav1.CreateOptions{})
+	if apierrors.IsAlreadyExists(err) {
+		return c.UpdateNetworkPolicy(in)
+	}
+	return createdNP, err
+}
+
+// GetNetworkPolicy returns the existing NetworkPolicy.
+func (c *Client) GetNetworkPolicy(namespace, name string) (*networkingv1.NetworkPolicy, error) {
+	return c.NetworkingV1().NetworkPolicies(namespace).Get(context.TODO(), name, metav1.GetOptions{})
+}
+
+// DeleteNetworkPolicy deletes the NetworkPolicy.
+func (c *Client) DeleteNetworkPolicy(namespace, name string, options *metav1.DeleteOptions) error {
+	return c.NetworkingV1().NetworkPolicies(namespace).Delete(context.TODO(), name, *options)
+}
+
+// UpdateNetworkPolicy will update the given NetworkPolicy resource.
+func (c *Client) UpdateNetworkPolicy(networkPolicy *networkingv1.NetworkPolicy) (*networkingv1.NetworkPolicy, error) {
+	klog.V(4).Infof("[UPDATE NetworkPolicy]: %s", networkPolicy.GetName())
+	oldNp, err := c.GetNetworkPolicy(networkPolicy.GetNamespace(), networkPolicy.GetName())
+	if err != nil {
+		return nil, err
+	}
+	patchBytes, err := createPatch(oldNp, networkPolicy)
+	if err != nil {
+		return nil, fmt.Errorf("error creating patch for NetworkPolicy: %v", err)
+	}
+	return c.NetworkingV1().NetworkPolicies(networkPolicy.GetNamespace()).Patch(context.TODO(), networkPolicy.GetName(), types.StrategicMergePatchType, patchBytes, metav1.PatchOptions{})
+}
diff --git a/pkg/lib/operatorclient/operatorclientmocks/mock_client.go b/pkg/lib/operatorclient/operatorclientmocks/mock_client.go
index b82217b8d..4a7c3bc72 100644
--- a/pkg/lib/operatorclient/operatorclientmocks/mock_client.go
+++ b/pkg/lib/operatorclient/operatorclientmocks/mock_client.go
@@ -11,15 +11,16 @@ import (
 	operatorclient "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient"
 	v1 "k8s.io/api/apps/v1"
 	v10 "k8s.io/api/core/v1"
-	v11 "k8s.io/api/rbac/v1"
+	v11 "k8s.io/api/networking/v1"
+	v12 "k8s.io/api/rbac/v1"
 	clientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
-	v12 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	v13 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	unstructured "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	labels "k8s.io/apimachinery/pkg/labels"
-	v13 "k8s.io/client-go/applyconfigurations/core/v1"
-	v14 "k8s.io/client-go/applyconfigurations/rbac/v1"
+	v14 "k8s.io/client-go/applyconfigurations/core/v1"
+	v15 "k8s.io/client-go/applyconfigurations/rbac/v1"
 	kubernetes "k8s.io/client-go/kubernetes"
-	v15 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
+	v16 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
 	clientset0 "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
 )
 
@@ -75,10 +76,10 @@ func (mr *MockClientInterfaceMockRecorder) ApiregistrationV1Interface() *gomock.
 }
 
 // ApplyClusterRoleBinding mocks base method.
-func (m *MockClientInterface) ApplyClusterRoleBinding(applyConfig *v14.ClusterRoleBindingApplyConfiguration, applyOptions v12.ApplyOptions) (*v11.ClusterRoleBinding, error) {
+func (m *MockClientInterface) ApplyClusterRoleBinding(applyConfig *v15.ClusterRoleBindingApplyConfiguration, applyOptions v13.ApplyOptions) (*v12.ClusterRoleBinding, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "ApplyClusterRoleBinding", applyConfig, applyOptions)
-	ret0, _ := ret[0].(*v11.ClusterRoleBinding)
+	ret0, _ := ret[0].(*v12.ClusterRoleBinding)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -90,10 +91,10 @@ func (mr *MockClientInterfaceMockRecorder) ApplyClusterRoleBinding(applyConfig,
 }
 
 // ApplyRoleBinding mocks base method.
-func (m *MockClientInterface) ApplyRoleBinding(applyConfig *v14.RoleBindingApplyConfiguration, applyOptions v12.ApplyOptions) (*v11.RoleBinding, error) {
+func (m *MockClientInterface) ApplyRoleBinding(applyConfig *v15.RoleBindingApplyConfiguration, applyOptions v13.ApplyOptions) (*v12.RoleBinding, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "ApplyRoleBinding", applyConfig, applyOptions)
-	ret0, _ := ret[0].(*v11.RoleBinding)
+	ret0, _ := ret[0].(*v12.RoleBinding)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -105,7 +106,7 @@ func (mr *MockClientInterfaceMockRecorder) ApplyRoleBinding(applyConfig, applyOp
 }
 
 // ApplyService mocks base method.
-func (m *MockClientInterface) ApplyService(arg0 *v13.ServiceApplyConfiguration, arg1 v12.ApplyOptions) (*v10.Service, error) {
+func (m *MockClientInterface) ApplyService(arg0 *v14.ServiceApplyConfiguration, arg1 v13.ApplyOptions) (*v10.Service, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "ApplyService", arg0, arg1)
 	ret0, _ := ret[0].(*v10.Service)
@@ -134,10 +135,10 @@ func (mr *MockClientInterfaceMockRecorder) AtomicModifyCustomResource(apiGroup,
 }
 
 // CreateAPIService mocks base method.
-func (m *MockClientInterface) CreateAPIService(arg0 *v15.APIService) (*v15.APIService, error) {
+func (m *MockClientInterface) CreateAPIService(arg0 *v16.APIService) (*v16.APIService, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "CreateAPIService", arg0)
-	ret0, _ := ret[0].(*v15.APIService)
+	ret0, _ := ret[0].(*v16.APIService)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -149,10 +150,10 @@ func (mr *MockClientInterfaceMockRecorder) CreateAPIService(arg0 interface{}) *g
 }
 
 // CreateClusterRole mocks base method.
-func (m *MockClientInterface) CreateClusterRole(arg0 *v11.ClusterRole) (*v11.ClusterRole, error) {
+func (m *MockClientInterface) CreateClusterRole(arg0 *v12.ClusterRole) (*v12.ClusterRole, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "CreateClusterRole", arg0)
-	ret0, _ := ret[0].(*v11.ClusterRole)
+	ret0, _ := ret[0].(*v12.ClusterRole)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -164,10 +165,10 @@ func (mr *MockClientInterfaceMockRecorder) CreateClusterRole(arg0 interface{}) *
 }
 
 // CreateClusterRoleBinding mocks base method.
-func (m *MockClientInterface) CreateClusterRoleBinding(arg0 *v11.ClusterRoleBinding) (*v11.ClusterRoleBinding, error) {
+func (m *MockClientInterface) CreateClusterRoleBinding(arg0 *v12.ClusterRoleBinding) (*v12.ClusterRoleBinding, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "CreateClusterRoleBinding", arg0)
-	ret0, _ := ret[0].(*v11.ClusterRoleBinding)
+	ret0, _ := ret[0].(*v12.ClusterRoleBinding)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -251,6 +252,21 @@ func (mr *MockClientInterfaceMockRecorder) CreateDeployment(arg0 interface{}) *g
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateDeployment", reflect.TypeOf((*MockClientInterface)(nil).CreateDeployment), arg0)
 }
 
+// CreateNetworkPolicy mocks base method.
+func (m *MockClientInterface) CreateNetworkPolicy(arg0 *v11.NetworkPolicy) (*v11.NetworkPolicy, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CreateNetworkPolicy", arg0)
+	ret0, _ := ret[0].(*v11.NetworkPolicy)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// CreateNetworkPolicy indicates an expected call of CreateNetworkPolicy.
+func (mr *MockClientInterfaceMockRecorder) CreateNetworkPolicy(arg0 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateNetworkPolicy", reflect.TypeOf((*MockClientInterface)(nil).CreateNetworkPolicy), arg0)
+}
+
 // CreateOrRollingUpdateDeployment mocks base method.
 func (m *MockClientInterface) CreateOrRollingUpdateDeployment(arg0 *v1.Deployment) (*v1.Deployment, bool, error) {
 	m.ctrl.T.Helper()
@@ -282,10 +298,10 @@ func (mr *MockClientInterfaceMockRecorder) CreateOrUpdateCustomeResourceRaw(apiG
 }
 
 // CreateRole mocks base method.
-func (m *MockClientInterface) CreateRole(arg0 *v11.Role) (*v11.Role, error) {
+func (m *MockClientInterface) CreateRole(arg0 *v12.Role) (*v12.Role, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "CreateRole", arg0)
-	ret0, _ := ret[0].(*v11.Role)
+	ret0, _ := ret[0].(*v12.Role)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -297,10 +313,10 @@ func (mr *MockClientInterfaceMockRecorder) CreateRole(arg0 interface{}) *gomock.
 }
 
 // CreateRoleBinding mocks base method.
-func (m *MockClientInterface) CreateRoleBinding(arg0 *v11.RoleBinding) (*v11.RoleBinding, error) {
+func (m *MockClientInterface) CreateRoleBinding(arg0 *v12.RoleBinding) (*v12.RoleBinding, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "CreateRoleBinding", arg0)
-	ret0, _ := ret[0].(*v11.RoleBinding)
+	ret0, _ := ret[0].(*v12.RoleBinding)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -357,7 +373,7 @@ func (mr *MockClientInterfaceMockRecorder) CreateServiceAccount(arg0 interface{}
 }
 
 // DeleteAPIService mocks base method.
-func (m *MockClientInterface) DeleteAPIService(name string, options *v12.DeleteOptions) error {
+func (m *MockClientInterface) DeleteAPIService(name string, options *v13.DeleteOptions) error {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "DeleteAPIService", name, options)
 	ret0, _ := ret[0].(error)
@@ -371,7 +387,7 @@ func (mr *MockClientInterfaceMockRecorder) DeleteAPIService(name, options interf
 }
 
 // DeleteClusterRole mocks base method.
-func (m *MockClientInterface) DeleteClusterRole(name string, options *v12.DeleteOptions) error {
+func (m *MockClientInterface) DeleteClusterRole(name string, options *v13.DeleteOptions) error {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "DeleteClusterRole", name, options)
 	ret0, _ := ret[0].(error)
@@ -385,7 +401,7 @@ func (mr *MockClientInterfaceMockRecorder) DeleteClusterRole(name, options inter
 }
 
 // DeleteClusterRoleBinding mocks base method.
-func (m *MockClientInterface) DeleteClusterRoleBinding(name string, options *v12.DeleteOptions) error {
+func (m *MockClientInterface) DeleteClusterRoleBinding(name string, options *v13.DeleteOptions) error {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "DeleteClusterRoleBinding", name, options)
 	ret0, _ := ret[0].(error)
@@ -399,7 +415,7 @@ func (mr *MockClientInterfaceMockRecorder) DeleteClusterRoleBinding(name, option
 }
 
 // DeleteConfigMap mocks base method.
-func (m *MockClientInterface) DeleteConfigMap(namespace, name string, options *v12.DeleteOptions) error {
+func (m *MockClientInterface) DeleteConfigMap(namespace, name string, options *v13.DeleteOptions) error {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "DeleteConfigMap", namespace, name, options)
 	ret0, _ := ret[0].(error)
@@ -427,7 +443,7 @@ func (mr *MockClientInterfaceMockRecorder) DeleteCustomResource(apiGroup, versio
 }
 
 // DeleteDeployment mocks base method.
-func (m *MockClientInterface) DeleteDeployment(namespace, name string, options *v12.DeleteOptions) error {
+func (m *MockClientInterface) DeleteDeployment(namespace, name string, options *v13.DeleteOptions) error {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "DeleteDeployment", namespace, name, options)
 	ret0, _ := ret[0].(error)
@@ -440,8 +456,22 @@ func (mr *MockClientInterfaceMockRecorder) DeleteDeployment(namespace, name, opt
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteDeployment", reflect.TypeOf((*MockClientInterface)(nil).DeleteDeployment), namespace, name, options)
 }
 
+// DeleteNetworkPolicy mocks base method.
+func (m *MockClientInterface) DeleteNetworkPolicy(namespace, name string, options *v13.DeleteOptions) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteNetworkPolicy", namespace, name, options)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// DeleteNetworkPolicy indicates an expected call of DeleteNetworkPolicy.
+func (mr *MockClientInterfaceMockRecorder) DeleteNetworkPolicy(namespace, name, options interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteNetworkPolicy", reflect.TypeOf((*MockClientInterface)(nil).DeleteNetworkPolicy), namespace, name, options)
+}
+
 // DeleteRole mocks base method.
-func (m *MockClientInterface) DeleteRole(namespace, name string, options *v12.DeleteOptions) error {
+func (m *MockClientInterface) DeleteRole(namespace, name string, options *v13.DeleteOptions) error {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "DeleteRole", namespace, name, options)
 	ret0, _ := ret[0].(error)
@@ -455,7 +485,7 @@ func (mr *MockClientInterfaceMockRecorder) DeleteRole(namespace, name, options i
 }
 
 // DeleteRoleBinding mocks base method.
-func (m *MockClientInterface) DeleteRoleBinding(namespace, name string, options *v12.DeleteOptions) error {
+func (m *MockClientInterface) DeleteRoleBinding(namespace, name string, options *v13.DeleteOptions) error {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "DeleteRoleBinding", namespace, name, options)
 	ret0, _ := ret[0].(error)
@@ -469,7 +499,7 @@ func (mr *MockClientInterfaceMockRecorder) DeleteRoleBinding(namespace, name, op
 }
 
 // DeleteSecret mocks base method.
-func (m *MockClientInterface) DeleteSecret(namespace, name string, options *v12.DeleteOptions) error {
+func (m *MockClientInterface) DeleteSecret(namespace, name string, options *v13.DeleteOptions) error {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "DeleteSecret", namespace, name, options)
 	ret0, _ := ret[0].(error)
@@ -483,7 +513,7 @@ func (mr *MockClientInterfaceMockRecorder) DeleteSecret(namespace, name, options
 }
 
 // DeleteService mocks base method.
-func (m *MockClientInterface) DeleteService(namespace, name string, options *v12.DeleteOptions) error {
+func (m *MockClientInterface) DeleteService(namespace, name string, options *v13.DeleteOptions) error {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "DeleteService", namespace, name, options)
 	ret0, _ := ret[0].(error)
@@ -497,7 +527,7 @@ func (mr *MockClientInterfaceMockRecorder) DeleteService(namespace, name, option
 }
 
 // DeleteServiceAccount mocks base method.
-func (m *MockClientInterface) DeleteServiceAccount(namespace, name string, options *v12.DeleteOptions) error {
+func (m *MockClientInterface) DeleteServiceAccount(namespace, name string, options *v13.DeleteOptions) error {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "DeleteServiceAccount", namespace, name, options)
 	ret0, _ := ret[0].(error)
@@ -511,10 +541,10 @@ func (mr *MockClientInterfaceMockRecorder) DeleteServiceAccount(namespace, name,
 }
 
 // GetAPIService mocks base method.
-func (m *MockClientInterface) GetAPIService(name string) (*v15.APIService, error) {
+func (m *MockClientInterface) GetAPIService(name string) (*v16.APIService, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "GetAPIService", name)
-	ret0, _ := ret[0].(*v15.APIService)
+	ret0, _ := ret[0].(*v16.APIService)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -526,10 +556,10 @@ func (mr *MockClientInterfaceMockRecorder) GetAPIService(name interface{}) *gomo
 }
 
 // GetClusterRole mocks base method.
-func (m *MockClientInterface) GetClusterRole(name string) (*v11.ClusterRole, error) {
+func (m *MockClientInterface) GetClusterRole(name string) (*v12.ClusterRole, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "GetClusterRole", name)
-	ret0, _ := ret[0].(*v11.ClusterRole)
+	ret0, _ := ret[0].(*v12.ClusterRole)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -541,10 +571,10 @@ func (mr *MockClientInterfaceMockRecorder) GetClusterRole(name interface{}) *gom
 }
 
 // GetClusterRoleBinding mocks base method.
-func (m *MockClientInterface) GetClusterRoleBinding(name string) (*v11.ClusterRoleBinding, error) {
+func (m *MockClientInterface) GetClusterRoleBinding(name string) (*v12.ClusterRoleBinding, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "GetClusterRoleBinding", name)
-	ret0, _ := ret[0].(*v11.ClusterRoleBinding)
+	ret0, _ := ret[0].(*v12.ClusterRoleBinding)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -615,11 +645,26 @@ func (mr *MockClientInterfaceMockRecorder) GetDeployment(namespace, name interfa
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDeployment", reflect.TypeOf((*MockClientInterface)(nil).GetDeployment), namespace, name)
 }
 
+// GetNetworkPolicy mocks base method.
+func (m *MockClientInterface) GetNetworkPolicy(namespace, name string) (*v11.NetworkPolicy, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetNetworkPolicy", namespace, name)
+	ret0, _ := ret[0].(*v11.NetworkPolicy)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// GetNetworkPolicy indicates an expected call of GetNetworkPolicy.
+func (mr *MockClientInterfaceMockRecorder) GetNetworkPolicy(namespace, name interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNetworkPolicy", reflect.TypeOf((*MockClientInterface)(nil).GetNetworkPolicy), namespace, name)
+}
+
 // GetRole mocks base method.
-func (m *MockClientInterface) GetRole(namespace, name string) (*v11.Role, error) {
+func (m *MockClientInterface) GetRole(namespace, name string) (*v12.Role, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "GetRole", namespace, name)
-	ret0, _ := ret[0].(*v11.Role)
+	ret0, _ := ret[0].(*v12.Role)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -631,10 +676,10 @@ func (mr *MockClientInterfaceMockRecorder) GetRole(namespace, name interface{})
 }
 
 // GetRoleBinding mocks base method.
-func (m *MockClientInterface) GetRoleBinding(namespace, name string) (*v11.RoleBinding, error) {
+func (m *MockClientInterface) GetRoleBinding(namespace, name string) (*v12.RoleBinding, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "GetRoleBinding", namespace, name)
-	ret0, _ := ret[0].(*v11.RoleBinding)
+	ret0, _ := ret[0].(*v12.RoleBinding)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -815,10 +860,10 @@ func (mr *MockClientInterfaceMockRecorder) RollingUpdateDeploymentMigrations(nam
 }
 
 // UpdateAPIService mocks base method.
-func (m *MockClientInterface) UpdateAPIService(modified *v15.APIService) (*v15.APIService, error) {
+func (m *MockClientInterface) UpdateAPIService(modified *v16.APIService) (*v16.APIService, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "UpdateAPIService", modified)
-	ret0, _ := ret[0].(*v15.APIService)
+	ret0, _ := ret[0].(*v16.APIService)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -830,10 +875,10 @@ func (mr *MockClientInterfaceMockRecorder) UpdateAPIService(modified interface{}
 }
 
 // UpdateClusterRole mocks base method.
-func (m *MockClientInterface) UpdateClusterRole(modified *v11.ClusterRole) (*v11.ClusterRole, error) {
+func (m *MockClientInterface) UpdateClusterRole(modified *v12.ClusterRole) (*v12.ClusterRole, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "UpdateClusterRole", modified)
-	ret0, _ := ret[0].(*v11.ClusterRole)
+	ret0, _ := ret[0].(*v12.ClusterRole)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -845,10 +890,10 @@ func (mr *MockClientInterfaceMockRecorder) UpdateClusterRole(modified interface{
 }
 
 // UpdateClusterRoleBinding mocks base method.
-func (m *MockClientInterface) UpdateClusterRoleBinding(modified *v11.ClusterRoleBinding) (*v11.ClusterRoleBinding, error) {
+func (m *MockClientInterface) UpdateClusterRoleBinding(modified *v12.ClusterRoleBinding) (*v12.ClusterRoleBinding, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "UpdateClusterRoleBinding", modified)
-	ret0, _ := ret[0].(*v11.ClusterRoleBinding)
+	ret0, _ := ret[0].(*v12.ClusterRoleBinding)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -918,11 +963,26 @@ func (mr *MockClientInterfaceMockRecorder) UpdateDeployment(arg0 interface{}) *g
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateDeployment", reflect.TypeOf((*MockClientInterface)(nil).UpdateDeployment), arg0)
 }
 
+// UpdateNetworkPolicy mocks base method.
+func (m *MockClientInterface) UpdateNetworkPolicy(modified *v11.NetworkPolicy) (*v11.NetworkPolicy, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "UpdateNetworkPolicy", modified)
+	ret0, _ := ret[0].(*v11.NetworkPolicy)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// UpdateNetworkPolicy indicates an expected call of UpdateNetworkPolicy.
+func (mr *MockClientInterfaceMockRecorder) UpdateNetworkPolicy(modified interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateNetworkPolicy", reflect.TypeOf((*MockClientInterface)(nil).UpdateNetworkPolicy), modified)
+}
+
 // UpdateRole mocks base method.
-func (m *MockClientInterface) UpdateRole(modified *v11.Role) (*v11.Role, error) {
+func (m *MockClientInterface) UpdateRole(modified *v12.Role) (*v12.Role, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "UpdateRole", modified)
-	ret0, _ := ret[0].(*v11.Role)
+	ret0, _ := ret[0].(*v12.Role)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -934,10 +994,10 @@ func (mr *MockClientInterfaceMockRecorder) UpdateRole(modified interface{}) *gom
 }
 
 // UpdateRoleBinding mocks base method.
-func (m *MockClientInterface) UpdateRoleBinding(modified *v11.RoleBinding) (*v11.RoleBinding, error) {
+func (m *MockClientInterface) UpdateRoleBinding(modified *v12.RoleBinding) (*v12.RoleBinding, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "UpdateRoleBinding", modified)
-	ret0, _ := ret[0].(*v11.RoleBinding)
+	ret0, _ := ret[0].(*v12.RoleBinding)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -1198,10 +1258,10 @@ func (m *MockAPIServiceClient) EXPECT() *MockAPIServiceClientMockRecorder {
 }
 
 // CreateAPIService mocks base method.
-func (m *MockAPIServiceClient) CreateAPIService(arg0 *v15.APIService) (*v15.APIService, error) {
+func (m *MockAPIServiceClient) CreateAPIService(arg0 *v16.APIService) (*v16.APIService, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "CreateAPIService", arg0)
-	ret0, _ := ret[0].(*v15.APIService)
+	ret0, _ := ret[0].(*v16.APIService)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -1213,7 +1273,7 @@ func (mr *MockAPIServiceClientMockRecorder) CreateAPIService(arg0 interface{}) *
 }
 
 // DeleteAPIService mocks base method.
-func (m *MockAPIServiceClient) DeleteAPIService(name string, options *v12.DeleteOptions) error {
+func (m *MockAPIServiceClient) DeleteAPIService(name string, options *v13.DeleteOptions) error {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "DeleteAPIService", name, options)
 	ret0, _ := ret[0].(error)
@@ -1227,10 +1287,10 @@ func (mr *MockAPIServiceClientMockRecorder) DeleteAPIService(name, options inter
 }
 
 // GetAPIService mocks base method.
-func (m *MockAPIServiceClient) GetAPIService(name string) (*v15.APIService, error) {
+func (m *MockAPIServiceClient) GetAPIService(name string) (*v16.APIService, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "GetAPIService", name)
-	ret0, _ := ret[0].(*v15.APIService)
+	ret0, _ := ret[0].(*v16.APIService)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -1242,10 +1302,10 @@ func (mr *MockAPIServiceClientMockRecorder) GetAPIService(name interface{}) *gom
 }
 
 // UpdateAPIService mocks base method.
-func (m *MockAPIServiceClient) UpdateAPIService(modified *v15.APIService) (*v15.APIService, error) {
+func (m *MockAPIServiceClient) UpdateAPIService(modified *v16.APIService) (*v16.APIService, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "UpdateAPIService", modified)
-	ret0, _ := ret[0].(*v15.APIService)
+	ret0, _ := ret[0].(*v16.APIService)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -1295,7 +1355,7 @@ func (mr *MockSecretClientMockRecorder) CreateSecret(arg0 interface{}) *gomock.C
 }
 
 // DeleteSecret mocks base method.
-func (m *MockSecretClient) DeleteSecret(namespace, name string, options *v12.DeleteOptions) error {
+func (m *MockSecretClient) DeleteSecret(namespace, name string, options *v13.DeleteOptions) error {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "DeleteSecret", namespace, name, options)
 	ret0, _ := ret[0].(error)
@@ -1362,7 +1422,7 @@ func (m *MockServiceClient) EXPECT() *MockServiceClientMockRecorder {
 }
 
 // ApplyService mocks base method.
-func (m *MockServiceClient) ApplyService(arg0 *v13.ServiceApplyConfiguration, arg1 v12.ApplyOptions) (*v10.Service, error) {
+func (m *MockServiceClient) ApplyService(arg0 *v14.ServiceApplyConfiguration, arg1 v13.ApplyOptions) (*v10.Service, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "ApplyService", arg0, arg1)
 	ret0, _ := ret[0].(*v10.Service)
@@ -1392,7 +1452,7 @@ func (mr *MockServiceClientMockRecorder) CreateService(arg0 interface{}) *gomock
 }
 
 // DeleteService mocks base method.
-func (m *MockServiceClient) DeleteService(namespace, name string, options *v12.DeleteOptions) error {
+func (m *MockServiceClient) DeleteService(namespace, name string, options *v13.DeleteOptions) error {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "DeleteService", namespace, name, options)
 	ret0, _ := ret[0].(error)
@@ -1474,7 +1534,7 @@ func (mr *MockServiceAccountClientMockRecorder) CreateServiceAccount(arg0 interf
 }
 
 // DeleteServiceAccount mocks base method.
-func (m *MockServiceAccountClient) DeleteServiceAccount(namespace, name string, options *v12.DeleteOptions) error {
+func (m *MockServiceAccountClient) DeleteServiceAccount(namespace, name string, options *v13.DeleteOptions) error {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "DeleteServiceAccount", namespace, name, options)
 	ret0, _ := ret[0].(error)
@@ -1541,10 +1601,10 @@ func (m *MockRoleClient) EXPECT() *MockRoleClientMockRecorder {
 }
 
 // CreateRole mocks base method.
-func (m *MockRoleClient) CreateRole(arg0 *v11.Role) (*v11.Role, error) {
+func (m *MockRoleClient) CreateRole(arg0 *v12.Role) (*v12.Role, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "CreateRole", arg0)
-	ret0, _ := ret[0].(*v11.Role)
+	ret0, _ := ret[0].(*v12.Role)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -1556,7 +1616,7 @@ func (mr *MockRoleClientMockRecorder) CreateRole(arg0 interface{}) *gomock.Call
 }
 
 // DeleteRole mocks base method.
-func (m *MockRoleClient) DeleteRole(namespace, name string, options *v12.DeleteOptions) error {
+func (m *MockRoleClient) DeleteRole(namespace, name string, options *v13.DeleteOptions) error {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "DeleteRole", namespace, name, options)
 	ret0, _ := ret[0].(error)
@@ -1570,10 +1630,10 @@ func (mr *MockRoleClientMockRecorder) DeleteRole(namespace, name, options interf
 }
 
 // GetRole mocks base method.
-func (m *MockRoleClient) GetRole(namespace, name string) (*v11.Role, error) {
+func (m *MockRoleClient) GetRole(namespace, name string) (*v12.Role, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "GetRole", namespace, name)
-	ret0, _ := ret[0].(*v11.Role)
+	ret0, _ := ret[0].(*v12.Role)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -1585,10 +1645,10 @@ func (mr *MockRoleClientMockRecorder) GetRole(namespace, name interface{}) *gomo
 }
 
 // UpdateRole mocks base method.
-func (m *MockRoleClient) UpdateRole(modified *v11.Role) (*v11.Role, error) {
+func (m *MockRoleClient) UpdateRole(modified *v12.Role) (*v12.Role, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "UpdateRole", modified)
-	ret0, _ := ret[0].(*v11.Role)
+	ret0, _ := ret[0].(*v12.Role)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -1623,10 +1683,10 @@ func (m *MockRoleBindingClient) EXPECT() *MockRoleBindingClientMockRecorder {
 }
 
 // ApplyRoleBinding mocks base method.
-func (m *MockRoleBindingClient) ApplyRoleBinding(applyConfig *v14.RoleBindingApplyConfiguration, applyOptions v12.ApplyOptions) (*v11.RoleBinding, error) {
+func (m *MockRoleBindingClient) ApplyRoleBinding(applyConfig *v15.RoleBindingApplyConfiguration, applyOptions v13.ApplyOptions) (*v12.RoleBinding, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "ApplyRoleBinding", applyConfig, applyOptions)
-	ret0, _ := ret[0].(*v11.RoleBinding)
+	ret0, _ := ret[0].(*v12.RoleBinding)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -1638,10 +1698,10 @@ func (mr *MockRoleBindingClientMockRecorder) ApplyRoleBinding(applyConfig, apply
 }
 
 // CreateRoleBinding mocks base method.
-func (m *MockRoleBindingClient) CreateRoleBinding(arg0 *v11.RoleBinding) (*v11.RoleBinding, error) {
+func (m *MockRoleBindingClient) CreateRoleBinding(arg0 *v12.RoleBinding) (*v12.RoleBinding, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "CreateRoleBinding", arg0)
-	ret0, _ := ret[0].(*v11.RoleBinding)
+	ret0, _ := ret[0].(*v12.RoleBinding)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -1653,7 +1713,7 @@ func (mr *MockRoleBindingClientMockRecorder) CreateRoleBinding(arg0 interface{})
 }
 
 // DeleteRoleBinding mocks base method.
-func (m *MockRoleBindingClient) DeleteRoleBinding(namespace, name string, options *v12.DeleteOptions) error {
+func (m *MockRoleBindingClient) DeleteRoleBinding(namespace, name string, options *v13.DeleteOptions) error {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "DeleteRoleBinding", namespace, name, options)
 	ret0, _ := ret[0].(error)
@@ -1667,10 +1727,10 @@ func (mr *MockRoleBindingClientMockRecorder) DeleteRoleBinding(namespace, name,
 }
 
 // GetRoleBinding mocks base method.
-func (m *MockRoleBindingClient) GetRoleBinding(namespace, name string) (*v11.RoleBinding, error) {
+func (m *MockRoleBindingClient) GetRoleBinding(namespace, name string) (*v12.RoleBinding, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "GetRoleBinding", namespace, name)
-	ret0, _ := ret[0].(*v11.RoleBinding)
+	ret0, _ := ret[0].(*v12.RoleBinding)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -1682,10 +1742,10 @@ func (mr *MockRoleBindingClientMockRecorder) GetRoleBinding(namespace, name inte
 }
 
 // UpdateRoleBinding mocks base method.
-func (m *MockRoleBindingClient) UpdateRoleBinding(modified *v11.RoleBinding) (*v11.RoleBinding, error) {
+func (m *MockRoleBindingClient) UpdateRoleBinding(modified *v12.RoleBinding) (*v12.RoleBinding, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "UpdateRoleBinding", modified)
-	ret0, _ := ret[0].(*v11.RoleBinding)
+	ret0, _ := ret[0].(*v12.RoleBinding)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -1720,10 +1780,10 @@ func (m *MockClusterRoleClient) EXPECT() *MockClusterRoleClientMockRecorder {
 }
 
 // CreateClusterRole mocks base method.
-func (m *MockClusterRoleClient) CreateClusterRole(arg0 *v11.ClusterRole) (*v11.ClusterRole, error) {
+func (m *MockClusterRoleClient) CreateClusterRole(arg0 *v12.ClusterRole) (*v12.ClusterRole, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "CreateClusterRole", arg0)
-	ret0, _ := ret[0].(*v11.ClusterRole)
+	ret0, _ := ret[0].(*v12.ClusterRole)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -1735,7 +1795,7 @@ func (mr *MockClusterRoleClientMockRecorder) CreateClusterRole(arg0 interface{})
 }
 
 // DeleteClusterRole mocks base method.
-func (m *MockClusterRoleClient) DeleteClusterRole(name string, options *v12.DeleteOptions) error {
+func (m *MockClusterRoleClient) DeleteClusterRole(name string, options *v13.DeleteOptions) error {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "DeleteClusterRole", name, options)
 	ret0, _ := ret[0].(error)
@@ -1749,10 +1809,10 @@ func (mr *MockClusterRoleClientMockRecorder) DeleteClusterRole(name, options int
 }
 
 // GetClusterRole mocks base method.
-func (m *MockClusterRoleClient) GetClusterRole(name string) (*v11.ClusterRole, error) {
+func (m *MockClusterRoleClient) GetClusterRole(name string) (*v12.ClusterRole, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "GetClusterRole", name)
-	ret0, _ := ret[0].(*v11.ClusterRole)
+	ret0, _ := ret[0].(*v12.ClusterRole)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -1764,10 +1824,10 @@ func (mr *MockClusterRoleClientMockRecorder) GetClusterRole(name interface{}) *g
 }
 
 // UpdateClusterRole mocks base method.
-func (m *MockClusterRoleClient) UpdateClusterRole(modified *v11.ClusterRole) (*v11.ClusterRole, error) {
+func (m *MockClusterRoleClient) UpdateClusterRole(modified *v12.ClusterRole) (*v12.ClusterRole, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "UpdateClusterRole", modified)
-	ret0, _ := ret[0].(*v11.ClusterRole)
+	ret0, _ := ret[0].(*v12.ClusterRole)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -1802,10 +1862,10 @@ func (m *MockClusterRoleBindingClient) EXPECT() *MockClusterRoleBindingClientMoc
 }
 
 // ApplyClusterRoleBinding mocks base method.
-func (m *MockClusterRoleBindingClient) ApplyClusterRoleBinding(applyConfig *v14.ClusterRoleBindingApplyConfiguration, applyOptions v12.ApplyOptions) (*v11.ClusterRoleBinding, error) {
+func (m *MockClusterRoleBindingClient) ApplyClusterRoleBinding(applyConfig *v15.ClusterRoleBindingApplyConfiguration, applyOptions v13.ApplyOptions) (*v12.ClusterRoleBinding, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "ApplyClusterRoleBinding", applyConfig, applyOptions)
-	ret0, _ := ret[0].(*v11.ClusterRoleBinding)
+	ret0, _ := ret[0].(*v12.ClusterRoleBinding)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -1817,10 +1877,10 @@ func (mr *MockClusterRoleBindingClientMockRecorder) ApplyClusterRoleBinding(appl
 }
 
 // CreateClusterRoleBinding mocks base method.
-func (m *MockClusterRoleBindingClient) CreateClusterRoleBinding(arg0 *v11.ClusterRoleBinding) (*v11.ClusterRoleBinding, error) {
+func (m *MockClusterRoleBindingClient) CreateClusterRoleBinding(arg0 *v12.ClusterRoleBinding) (*v12.ClusterRoleBinding, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "CreateClusterRoleBinding", arg0)
-	ret0, _ := ret[0].(*v11.ClusterRoleBinding)
+	ret0, _ := ret[0].(*v12.ClusterRoleBinding)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -1832,7 +1892,7 @@ func (mr *MockClusterRoleBindingClientMockRecorder) CreateClusterRoleBinding(arg
 }
 
 // DeleteClusterRoleBinding mocks base method.
-func (m *MockClusterRoleBindingClient) DeleteClusterRoleBinding(name string, options *v12.DeleteOptions) error {
+func (m *MockClusterRoleBindingClient) DeleteClusterRoleBinding(name string, options *v13.DeleteOptions) error {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "DeleteClusterRoleBinding", name, options)
 	ret0, _ := ret[0].(error)
@@ -1846,10 +1906,10 @@ func (mr *MockClusterRoleBindingClientMockRecorder) DeleteClusterRoleBinding(nam
 }
 
 // GetClusterRoleBinding mocks base method.
-func (m *MockClusterRoleBindingClient) GetClusterRoleBinding(name string) (*v11.ClusterRoleBinding, error) {
+func (m *MockClusterRoleBindingClient) GetClusterRoleBinding(name string) (*v12.ClusterRoleBinding, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "GetClusterRoleBinding", name)
-	ret0, _ := ret[0].(*v11.ClusterRoleBinding)
+	ret0, _ := ret[0].(*v12.ClusterRoleBinding)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -1861,10 +1921,10 @@ func (mr *MockClusterRoleBindingClientMockRecorder) GetClusterRoleBinding(name i
 }
 
 // UpdateClusterRoleBinding mocks base method.
-func (m *MockClusterRoleBindingClient) UpdateClusterRoleBinding(modified *v11.ClusterRoleBinding) (*v11.ClusterRoleBinding, error) {
+func (m *MockClusterRoleBindingClient) UpdateClusterRoleBinding(modified *v12.ClusterRoleBinding) (*v12.ClusterRoleBinding, error) {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "UpdateClusterRoleBinding", modified)
-	ret0, _ := ret[0].(*v11.ClusterRoleBinding)
+	ret0, _ := ret[0].(*v12.ClusterRoleBinding)
 	ret1, _ := ret[1].(error)
 	return ret0, ret1
 }
@@ -1930,7 +1990,7 @@ func (mr *MockDeploymentClientMockRecorder) CreateOrRollingUpdateDeployment(arg0
 }
 
 // DeleteDeployment mocks base method.
-func (m *MockDeploymentClient) DeleteDeployment(namespace, name string, options *v12.DeleteOptions) error {
+func (m *MockDeploymentClient) DeleteDeployment(namespace, name string, options *v13.DeleteOptions) error {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "DeleteDeployment", namespace, name, options)
 	ret0, _ := ret[0].(error)
@@ -2108,7 +2168,7 @@ func (mr *MockConfigMapClientMockRecorder) CreateConfigMap(arg0 interface{}) *go
 }
 
 // DeleteConfigMap mocks base method.
-func (m *MockConfigMapClient) DeleteConfigMap(namespace, name string, options *v12.DeleteOptions) error {
+func (m *MockConfigMapClient) DeleteConfigMap(namespace, name string, options *v13.DeleteOptions) error {
 	m.ctrl.T.Helper()
 	ret := m.ctrl.Call(m, "DeleteConfigMap", namespace, name, options)
 	ret0, _ := ret[0].(error)
@@ -2150,3 +2210,85 @@ func (mr *MockConfigMapClientMockRecorder) UpdateConfigMap(modified interface{})
 	mr.mock.ctrl.T.Helper()
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateConfigMap", reflect.TypeOf((*MockConfigMapClient)(nil).UpdateConfigMap), modified)
 }
+
+// MockNetworkPolicyClient is a mock of NetworkPolicyClient interface.
+type MockNetworkPolicyClient struct {
+	ctrl     *gomock.Controller
+	recorder *MockNetworkPolicyClientMockRecorder
+}
+
+// MockNetworkPolicyClientMockRecorder is the mock recorder for MockNetworkPolicyClient.
+type MockNetworkPolicyClientMockRecorder struct {
+	mock *MockNetworkPolicyClient
+}
+
+// NewMockNetworkPolicyClient creates a new mock instance.
+func NewMockNetworkPolicyClient(ctrl *gomock.Controller) *MockNetworkPolicyClient {
+	mock := &MockNetworkPolicyClient{ctrl: ctrl}
+	mock.recorder = &MockNetworkPolicyClientMockRecorder{mock}
+	return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockNetworkPolicyClient) EXPECT() *MockNetworkPolicyClientMockRecorder {
+	return m.recorder
+}
+
+// CreateNetworkPolicy mocks base method.
+func (m *MockNetworkPolicyClient) CreateNetworkPolicy(arg0 *v11.NetworkPolicy) (*v11.NetworkPolicy, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "CreateNetworkPolicy", arg0)
+	ret0, _ := ret[0].(*v11.NetworkPolicy)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// CreateNetworkPolicy indicates an expected call of CreateNetworkPolicy.
+func (mr *MockNetworkPolicyClientMockRecorder) CreateNetworkPolicy(arg0 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateNetworkPolicy", reflect.TypeOf((*MockNetworkPolicyClient)(nil).CreateNetworkPolicy), arg0)
+}
+
+// DeleteNetworkPolicy mocks base method.
+func (m *MockNetworkPolicyClient) DeleteNetworkPolicy(namespace, name string, options *v13.DeleteOptions) error {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "DeleteNetworkPolicy", namespace, name, options)
+	ret0, _ := ret[0].(error)
+	return ret0
+}
+
+// DeleteNetworkPolicy indicates an expected call of DeleteNetworkPolicy.
+func (mr *MockNetworkPolicyClientMockRecorder) DeleteNetworkPolicy(namespace, name, options interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteNetworkPolicy", reflect.TypeOf((*MockNetworkPolicyClient)(nil).DeleteNetworkPolicy), namespace, name, options)
+}
+
+// GetNetworkPolicy mocks base method.
+func (m *MockNetworkPolicyClient) GetNetworkPolicy(namespace, name string) (*v11.NetworkPolicy, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetNetworkPolicy", namespace, name)
+	ret0, _ := ret[0].(*v11.NetworkPolicy)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// GetNetworkPolicy indicates an expected call of GetNetworkPolicy.
+func (mr *MockNetworkPolicyClientMockRecorder) GetNetworkPolicy(namespace, name interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNetworkPolicy", reflect.TypeOf((*MockNetworkPolicyClient)(nil).GetNetworkPolicy), namespace, name)
+}
+
+// UpdateNetworkPolicy mocks base method.
+func (m *MockNetworkPolicyClient) UpdateNetworkPolicy(modified *v11.NetworkPolicy) (*v11.NetworkPolicy, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "UpdateNetworkPolicy", modified)
+	ret0, _ := ret[0].(*v11.NetworkPolicy)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// UpdateNetworkPolicy indicates an expected call of UpdateNetworkPolicy.
+func (mr *MockNetworkPolicyClientMockRecorder) UpdateNetworkPolicy(modified interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateNetworkPolicy", reflect.TypeOf((*MockNetworkPolicyClient)(nil).UpdateNetworkPolicy), modified)
+}
diff --git a/pkg/lib/operatorlister/lister.go b/pkg/lib/operatorlister/lister.go
index 388f38dda..a6b94264f 100644
--- a/pkg/lib/operatorlister/lister.go
+++ b/pkg/lib/operatorlister/lister.go
@@ -3,6 +3,7 @@ package operatorlister
 import (
 	appsv1 "k8s.io/client-go/listers/apps/v1"
 	corev1 "k8s.io/client-go/listers/core/v1"
+	networkingv1 "k8s.io/client-go/listers/networking/v1"
 	rbacv1 "k8s.io/client-go/listers/rbac/v1"
 	"k8s.io/client-go/metadata/metadatalister"
 	aregv1 "k8s.io/kube-aggregator/pkg/client/listers/apiregistration/v1"
@@ -34,6 +35,7 @@ type OperatorLister interface {
 	AppsV1() AppsV1Lister
 	CoreV1() CoreV1Lister
 	RbacV1() RbacV1Lister
+	NetworkingV1() NetworkingV1Lister
 	APIRegistrationV1() APIRegistrationV1Lister
 	APIExtensionsV1() APIExtensionsV1Lister
 
@@ -79,6 +81,13 @@ type RbacV1Lister interface {
 	RoleBindingLister() rbacv1.RoleBindingLister
 }
 
+//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . RbacV1Lister
+type NetworkingV1Lister interface {
+	RegisterNetworkPolicyLister(namespace string, lister networkingv1.NetworkPolicyLister)
+
+	NetworkPolicyLister() networkingv1.NetworkPolicyLister
+}
+
 //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . APIRegistrationV1Lister
 type APIRegistrationV1Lister interface {
 	RegisterAPIServiceLister(lister aregv1.APIServiceLister)
@@ -165,6 +174,16 @@ func newRbacV1Lister() *rbacV1Lister {
 	}
 }
 
+type networkingV1Lister struct {
+	networkPolicyLister *UnionNetworkPolicyLister
+}
+
+func newNetworkingV1Lister() *networkingV1Lister {
+	return &networkingV1Lister{
+		networkPolicyLister: &UnionNetworkPolicyLister{},
+	}
+}
+
 type apiRegistrationV1Lister struct {
 	apiServiceLister *UnionAPIServiceLister
 }
@@ -228,6 +247,7 @@ type lister struct {
 	appsV1Lister            *appsV1Lister
 	coreV1Lister            *coreV1Lister
 	rbacV1Lister            *rbacV1Lister
+	networkingv1Lister      *networkingV1Lister
 	apiRegistrationV1Lister *apiRegistrationV1Lister
 	apiExtensionsV1Lister   *apiExtensionsV1Lister
 	operatorsV1alpha1Lister *operatorsV1alpha1Lister
@@ -247,6 +267,10 @@ func (l *lister) RbacV1() RbacV1Lister {
 	return l.rbacV1Lister
 }
 
+func (l *lister) NetworkingV1() NetworkingV1Lister {
+	return l.networkingv1Lister
+}
+
 func (l *lister) APIRegistrationV1() APIRegistrationV1Lister {
 	return l.apiRegistrationV1Lister
 }
@@ -273,6 +297,7 @@ func NewLister() OperatorLister {
 		appsV1Lister:            newAppsV1Lister(),
 		coreV1Lister:            newCoreV1Lister(),
 		rbacV1Lister:            newRbacV1Lister(),
+		networkingv1Lister:      newNetworkingV1Lister(),
 		apiRegistrationV1Lister: newAPIRegistrationV1Lister(),
 		apiExtensionsV1Lister:   newAPIExtensionsV1Lister(),
 		operatorsV1alpha1Lister: newOperatorsV1alpha1Lister(),
diff --git a/pkg/lib/operatorlister/networkpolicy.go b/pkg/lib/operatorlister/networkpolicy.go
new file mode 100644
index 000000000..0d7e3773a
--- /dev/null
+++ b/pkg/lib/operatorlister/networkpolicy.go
@@ -0,0 +1,94 @@
+package operatorlister
+
+import (
+	"fmt"
+	"sync"
+
+	networkingv1 "k8s.io/api/networking/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/labels"
+	"k8s.io/apimachinery/pkg/types"
+	networkingv1listers "k8s.io/client-go/listers/networking/v1"
+)
+
+type UnionNetworkPolicyLister struct {
+	networkPolicyListers map[string]networkingv1listers.NetworkPolicyLister
+	networkPolicyLock    sync.RWMutex
+}
+
+// List lists all NetworkPolicies in the indexer.
+func (unpl *UnionNetworkPolicyLister) List(selector labels.Selector) (ret []*networkingv1.NetworkPolicy, err error) {
+	unpl.networkPolicyLock.RLock()
+	defer unpl.networkPolicyLock.RUnlock()
+
+	set := make(map[types.UID]*networkingv1.NetworkPolicy)
+	for _, npl := range unpl.networkPolicyListers {
+		networkPolicies, err := npl.List(selector)
+		if err != nil {
+			return nil, err
+		}
+
+		for _, networkPolicy := range networkPolicies {
+			set[networkPolicy.GetUID()] = networkPolicy
+		}
+	}
+
+	for _, networkPolicy := range set {
+		ret = append(ret, networkPolicy)
+	}
+
+	return
+}
+
+// NetworkPolicies returns an object that can list and get NetworkPolicies.
+func (unpl *UnionNetworkPolicyLister) NetworkPolicies(namespace string) networkingv1listers.NetworkPolicyNamespaceLister {
+	unpl.networkPolicyLock.RLock()
+	defer unpl.networkPolicyLock.RUnlock()
+
+	// Check for specific namespace listers
+	if npl, ok := unpl.networkPolicyListers[namespace]; ok {
+		return npl.NetworkPolicies(namespace)
+	}
+
+	// Check for any namespace-all listers
+	if npl, ok := unpl.networkPolicyListers[metav1.NamespaceAll]; ok {
+		return npl.NetworkPolicies(namespace)
+	}
+
+	return &NullNetworkPolicyNamespaceLister{}
+}
+
+func (unpl *UnionNetworkPolicyLister) RegisterNetworkPolicyLister(namespace string, lister networkingv1listers.NetworkPolicyLister) {
+	unpl.networkPolicyLock.Lock()
+	defer unpl.networkPolicyLock.Unlock()
+
+	if unpl.networkPolicyListers == nil {
+		unpl.networkPolicyListers = make(map[string]networkingv1listers.NetworkPolicyLister)
+	}
+	unpl.networkPolicyListers[namespace] = lister
+}
+
+func (l *networkingV1Lister) RegisterNetworkPolicyLister(namespace string, lister networkingv1listers.NetworkPolicyLister) {
+	l.networkPolicyLister.RegisterNetworkPolicyLister(namespace, lister)
+}
+
+func (l *networkingV1Lister) NetworkPolicyLister() networkingv1listers.NetworkPolicyLister {
+	return l.networkPolicyLister
+}
+
+// NullNetworkPolicyNamespaceLister is an implementation of a null NetworkPolicyNamespaceLister. It is
+// used to prevent nil pointers when no NetworkPolicyNamespaceLister has been registered for a given
+// namespace.
+type NullNetworkPolicyNamespaceLister struct {
+	networkingv1listers.NetworkPolicyNamespaceLister
+}
+
+// List returns nil and an error explaining that this is a NullNetworkPolicyNamespaceLister.
+func (n *NullNetworkPolicyNamespaceLister) List(selector labels.Selector) (ret []*networkingv1.NetworkPolicy, err error) {
+	return nil, fmt.Errorf("cannot list NetworkPolicies with a NullNetworkPolicyNamespaceLister")
+}
+
+// Get returns nil and an error explaining that this is a NullNetworkPolicyNamespaceLister.
+func (n *NullNetworkPolicyNamespaceLister) Get(name string) (*networkingv1.NetworkPolicy, error) {
+	return nil, fmt.Errorf("cannot get NetworkPolicy with a NullNetworkPolicyNamespaceLister")
+}
diff --git a/pkg/lib/operatorlister/operatorlisterfakes/fake_operator_lister.go b/pkg/lib/operatorlister/operatorlisterfakes/fake_operator_lister.go
index e78608816..a74ce9021 100644
--- a/pkg/lib/operatorlister/operatorlisterfakes/fake_operator_lister.go
+++ b/pkg/lib/operatorlister/operatorlisterfakes/fake_operator_lister.go
@@ -48,6 +48,16 @@ type FakeOperatorLister struct {
 	coreV1ReturnsOnCall map[int]struct {
 		result1 operatorlister.CoreV1Lister
 	}
+	NetworkingV1Stub        func() operatorlister.NetworkingV1Lister
+	networkingV1Mutex       sync.RWMutex
+	networkingV1ArgsForCall []struct {
+	}
+	networkingV1Returns struct {
+		result1 operatorlister.NetworkingV1Lister
+	}
+	networkingV1ReturnsOnCall map[int]struct {
+		result1 operatorlister.NetworkingV1Lister
+	}
 	OperatorsV1Stub        func() operatorlister.OperatorsV1Lister
 	operatorsV1Mutex       sync.RWMutex
 	operatorsV1ArgsForCall []struct {
@@ -304,6 +314,59 @@ func (fake *FakeOperatorLister) CoreV1ReturnsOnCall(i int, result1 operatorliste
 	}{result1}
 }
 
+func (fake *FakeOperatorLister) NetworkingV1() operatorlister.NetworkingV1Lister {
+	fake.networkingV1Mutex.Lock()
+	ret, specificReturn := fake.networkingV1ReturnsOnCall[len(fake.networkingV1ArgsForCall)]
+	fake.networkingV1ArgsForCall = append(fake.networkingV1ArgsForCall, struct {
+	}{})
+	stub := fake.NetworkingV1Stub
+	fakeReturns := fake.networkingV1Returns
+	fake.recordInvocation("NetworkingV1", []interface{}{})
+	fake.networkingV1Mutex.Unlock()
+	if stub != nil {
+		return stub()
+	}
+	if specificReturn {
+		return ret.result1
+	}
+	return fakeReturns.result1
+}
+
+func (fake *FakeOperatorLister) NetworkingV1CallCount() int {
+	fake.networkingV1Mutex.RLock()
+	defer fake.networkingV1Mutex.RUnlock()
+	return len(fake.networkingV1ArgsForCall)
+}
+
+func (fake *FakeOperatorLister) NetworkingV1Calls(stub func() operatorlister.NetworkingV1Lister) {
+	fake.networkingV1Mutex.Lock()
+	defer fake.networkingV1Mutex.Unlock()
+	fake.NetworkingV1Stub = stub
+}
+
+func (fake *FakeOperatorLister) NetworkingV1Returns(result1 operatorlister.NetworkingV1Lister) {
+	fake.networkingV1Mutex.Lock()
+	defer fake.networkingV1Mutex.Unlock()
+	fake.NetworkingV1Stub = nil
+	fake.networkingV1Returns = struct {
+		result1 operatorlister.NetworkingV1Lister
+	}{result1}
+}
+
+func (fake *FakeOperatorLister) NetworkingV1ReturnsOnCall(i int, result1 operatorlister.NetworkingV1Lister) {
+	fake.networkingV1Mutex.Lock()
+	defer fake.networkingV1Mutex.Unlock()
+	fake.NetworkingV1Stub = nil
+	if fake.networkingV1ReturnsOnCall == nil {
+		fake.networkingV1ReturnsOnCall = make(map[int]struct {
+			result1 operatorlister.NetworkingV1Lister
+		})
+	}
+	fake.networkingV1ReturnsOnCall[i] = struct {
+		result1 operatorlister.NetworkingV1Lister
+	}{result1}
+}
+
 func (fake *FakeOperatorLister) OperatorsV1() operatorlister.OperatorsV1Lister {
 	fake.operatorsV1Mutex.Lock()
 	ret, specificReturn := fake.operatorsV1ReturnsOnCall[len(fake.operatorsV1ArgsForCall)]
@@ -527,6 +590,8 @@ func (fake *FakeOperatorLister) Invocations() map[string][][]interface{} {
 	defer fake.appsV1Mutex.RUnlock()
 	fake.coreV1Mutex.RLock()
 	defer fake.coreV1Mutex.RUnlock()
+	fake.networkingV1Mutex.RLock()
+	defer fake.networkingV1Mutex.RUnlock()
 	fake.operatorsV1Mutex.RLock()
 	defer fake.operatorsV1Mutex.RUnlock()
 	fake.operatorsV1alpha1Mutex.RLock()


Test patch:
diff --git a/pkg/controller/bundle/bundle_unpacker_test.go b/pkg/controller/bundle/bundle_unpacker_test.go
index d36bba773..b0502fc31 100644
--- a/pkg/controller/bundle/bundle_unpacker_test.go
+++ b/pkg/controller/bundle/bundle_unpacker_test.go
@@ -208,7 +208,7 @@ func TestConfigMapUnpacker(t *testing.T) {
 						ObjectMeta: metav1.ObjectMeta{
 							Name:      pathHash,
 							Namespace: "ns-a",
-							Labels:    map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue, bundleUnpackRefLabel: pathHash},
+							Labels:    map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue, BundleUnpackRefLabel: pathHash},
 							OwnerReferences: []metav1.OwnerReference{
 								{
 									APIVersion:         "v1",
@@ -225,8 +225,11 @@ func TestConfigMapUnpacker(t *testing.T) {
 							BackoffLimit:          &backoffLimit,
 							Template: corev1.PodTemplateSpec{
 								ObjectMeta: metav1.ObjectMeta{
-									Name:   pathHash,
-									Labels: map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue},
+									Name: pathHash,
+									Labels: map[string]string{
+										install.OLMManagedLabelKey: install.OLMManagedLabelValue,
+										BundleUnpackRefLabel:       pathHash,
+									},
 								},
 								Spec: corev1.PodSpec{
 									RestartPolicy:    corev1.RestartPolicyNever,
@@ -444,7 +447,7 @@ func TestConfigMapUnpacker(t *testing.T) {
 						ObjectMeta: metav1.ObjectMeta{
 							Name:      digestHash,
 							Namespace: "ns-a",
-							Labels:    map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue, bundleUnpackRefLabel: digestHash},
+							Labels:    map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue, BundleUnpackRefLabel: digestHash},
 							OwnerReferences: []metav1.OwnerReference{
 								{
 									APIVersion:         "v1",
@@ -460,8 +463,11 @@ func TestConfigMapUnpacker(t *testing.T) {
 							BackoffLimit:          &backoffLimit,
 							Template: corev1.PodTemplateSpec{
 								ObjectMeta: metav1.ObjectMeta{
-									Name:   digestHash,
-									Labels: map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue},
+									Name: digestHash,
+									Labels: map[string]string{
+										install.OLMManagedLabelKey: install.OLMManagedLabelValue,
+										BundleUnpackRefLabel:       digestHash,
+									},
 								},
 								Spec: corev1.PodSpec{
 									RestartPolicy: corev1.RestartPolicyNever,
@@ -718,7 +724,7 @@ func TestConfigMapUnpacker(t *testing.T) {
 						ObjectMeta: metav1.ObjectMeta{
 							Name:      digestHash,
 							Namespace: "ns-a",
-							Labels:    map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue, bundleUnpackRefLabel: digestHash},
+							Labels:    map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue, BundleUnpackRefLabel: digestHash},
 							OwnerReferences: []metav1.OwnerReference{
 								{
 									APIVersion:         "v1",
@@ -734,8 +740,11 @@ func TestConfigMapUnpacker(t *testing.T) {
 							BackoffLimit:          &backoffLimit,
 							Template: corev1.PodTemplateSpec{
 								ObjectMeta: metav1.ObjectMeta{
-									Name:   digestHash,
-									Labels: map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue},
+									Name: digestHash,
+									Labels: map[string]string{
+										install.OLMManagedLabelKey: install.OLMManagedLabelValue,
+										BundleUnpackRefLabel:       digestHash,
+									},
 								},
 								Spec: corev1.PodSpec{
 									RestartPolicy: corev1.RestartPolicyNever,
@@ -987,7 +996,7 @@ func TestConfigMapUnpacker(t *testing.T) {
 						ObjectMeta: metav1.ObjectMeta{
 							Name:      pathHash,
 							Namespace: "ns-a",
-							Labels:    map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue, bundleUnpackRefLabel: pathHash},
+							Labels:    map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue, BundleUnpackRefLabel: pathHash},
 							OwnerReferences: []metav1.OwnerReference{
 								{
 									APIVersion:         "v1",
@@ -1003,8 +1012,11 @@ func TestConfigMapUnpacker(t *testing.T) {
 							BackoffLimit:          &backoffLimit,
 							Template: corev1.PodTemplateSpec{
 								ObjectMeta: metav1.ObjectMeta{
-									Name:   pathHash,
-									Labels: map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue},
+									Name: pathHash,
+									Labels: map[string]string{
+										install.OLMManagedLabelKey: install.OLMManagedLabelValue,
+										BundleUnpackRefLabel:       pathHash,
+									},
 								},
 								Spec: corev1.PodSpec{
 									RestartPolicy: corev1.RestartPolicyNever,
@@ -1242,8 +1254,11 @@ func TestConfigMapUnpacker(t *testing.T) {
 							BackoffLimit:          &backoffLimit,
 							Template: corev1.PodTemplateSpec{
 								ObjectMeta: metav1.ObjectMeta{
-									Name:   pathHash,
-									Labels: map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue},
+									Name: pathHash,
+									Labels: map[string]string{
+										install.OLMManagedLabelKey: install.OLMManagedLabelValue,
+										BundleUnpackRefLabel:       pathHash,
+									},
 								},
 								Spec: corev1.PodSpec{
 									RestartPolicy: corev1.RestartPolicyNever,
@@ -1494,8 +1509,11 @@ func TestConfigMapUnpacker(t *testing.T) {
 							BackoffLimit:          &backoffLimit,
 							Template: corev1.PodTemplateSpec{
 								ObjectMeta: metav1.ObjectMeta{
-									Name:   pathHash,
-									Labels: map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue},
+									Name: pathHash,
+									Labels: map[string]string{
+										install.OLMManagedLabelKey: install.OLMManagedLabelValue,
+										BundleUnpackRefLabel:       pathHash,
+									},
 								},
 								Spec: corev1.PodSpec{
 									RestartPolicy: corev1.RestartPolicyNever,
@@ -1990,7 +2008,7 @@ func TestSortUnpackJobs(t *testing.T) {
 		return &batchv1.Job{
 			ObjectMeta: metav1.ObjectMeta{
 				Name:   name,
-				Labels: map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue, bundleUnpackRefLabel: "test"},
+				Labels: map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue, BundleUnpackRefLabel: "test"},
 			},
 			Status: batchv1.JobStatus{
 				Conditions: conditions,
@@ -2000,7 +2018,7 @@ func TestSortUnpackJobs(t *testing.T) {
 	nilConditionJob := &batchv1.Job{
 		ObjectMeta: metav1.ObjectMeta{
 			Name:   "nc",
-			Labels: map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue, bundleUnpackRefLabel: "test"},
+			Labels: map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue, BundleUnpackRefLabel: "test"},
 		},
 		Status: batchv1.JobStatus{
 			Conditions: nil,
diff --git a/pkg/controller/operators/catalog/operator_test.go b/pkg/controller/operators/catalog/operator_test.go
index e0e543b47..2a688dfb9 100644
--- a/pkg/controller/operators/catalog/operator_test.go
+++ b/pkg/controller/operators/catalog/operator_test.go
@@ -25,6 +25,7 @@ import (
 	"gopkg.in/yaml.v2"
 	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
+	networkingv1 "k8s.io/api/networking/v1"
 	rbacv1 "k8s.io/api/rbac/v1"
 	apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
 	apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
@@ -1276,6 +1277,11 @@ func TestSyncCatalogSources(t *testing.T) {
 				pod(t, *grpcCatalog),
 				service(grpcCatalog.GetName(), grpcCatalog.GetNamespace()),
 				serviceAccount(grpcCatalog.GetName(), grpcCatalog.GetNamespace(), "", objectReference("init secret")),
+				grpcServerNetworkPolicy(grpcCatalog, map[string]string{
+					reconciler.CatalogSourceLabelKey: grpcCatalog.GetName(),
+					install.OLMManagedLabelKey:       install.OLMManagedLabelValue,
+				}),
+				unpackBundlesNetworkPolicy(grpcCatalog),
 			},
 			existingSources: []sourceAddress{
 				{
@@ -2128,7 +2134,17 @@ func NewFakeOperator(ctx context.Context, namespace string, namespaces []string,
 	serviceInformer := factory.Core().V1().Services()
 	podInformer := factory.Core().V1().Pods()
 	configMapInformer := factory.Core().V1().ConfigMaps()
-	sharedInformers = append(sharedInformers, roleInformer.Informer(), roleBindingInformer.Informer(), serviceAccountInformer.Informer(), serviceInformer.Informer(), podInformer.Informer(), configMapInformer.Informer())
+	networkPolicyInformer := factory.Networking().V1().NetworkPolicies()
+
+	sharedInformers = append(sharedInformers,
+		roleInformer.Informer(),
+		roleBindingInformer.Informer(),
+		serviceAccountInformer.Informer(),
+		serviceInformer.Informer(),
+		podInformer.Informer(),
+		configMapInformer.Informer(),
+		networkPolicyInformer.Informer(),
+	)
 
 	lister.RbacV1().RegisterRoleLister(metav1.NamespaceAll, roleInformer.Lister())
 	lister.RbacV1().RegisterRoleBindingLister(metav1.NamespaceAll, roleBindingInformer.Lister())
@@ -2136,6 +2152,7 @@ func NewFakeOperator(ctx context.Context, namespace string, namespaces []string,
 	lister.CoreV1().RegisterServiceLister(metav1.NamespaceAll, serviceInformer.Lister())
 	lister.CoreV1().RegisterPodLister(metav1.NamespaceAll, podInformer.Lister())
 	lister.CoreV1().RegisterConfigMapLister(metav1.NamespaceAll, configMapInformer.Lister())
+	lister.NetworkingV1().RegisterNetworkPolicyLister(metav1.NamespaceAll, networkPolicyInformer.Lister())
 	logger := logrus.New()
 
 	// Create the new operator
@@ -2319,6 +2336,13 @@ func configMap(name, namespace string) *corev1.ConfigMap {
 	}
 }
 
+func grpcServerNetworkPolicy(catSrc *v1alpha1.CatalogSource, matchLabels map[string]string) *networkingv1.NetworkPolicy {
+	return reconciler.DesiredGRPCServerNetworkPolicy(catSrc, matchLabels)
+}
+func unpackBundlesNetworkPolicy(catSrc *v1alpha1.CatalogSource) *networkingv1.NetworkPolicy {
+	return reconciler.DesiredUnpackBundlesNetworkPolicy(catSrc)
+}
+
 func objectReference(name string) *corev1.ObjectReference {
 	if name == "" {
 		return &corev1.ObjectReference{}
diff --git a/pkg/controller/registry/reconciler/configmap_test.go b/pkg/controller/registry/reconciler/configmap_test.go
index a8c1dcb9d..f97326409 100644
--- a/pkg/controller/registry/reconciler/configmap_test.go
+++ b/pkg/controller/registry/reconciler/configmap_test.go
@@ -12,6 +12,7 @@ import (
 	"github.com/sirupsen/logrus"
 	"github.com/stretchr/testify/require"
 	corev1 "k8s.io/api/core/v1"
+	networkingv1 "k8s.io/api/networking/v1"
 	rbacv1 "k8s.io/api/rbac/v1"
 	"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
 	"k8s.io/apimachinery/pkg/api/meta"
@@ -83,6 +84,7 @@ func fakeReconcilerFactory(t *testing.T, stopc <-chan struct{}, options ...fakeR
 	serviceInformer := informerFactory.Core().V1().Services()
 	podInformer := informerFactory.Core().V1().Pods()
 	configMapInformer := informerFactory.Core().V1().ConfigMaps()
+	networkPolicyInformer := informerFactory.Networking().V1().NetworkPolicies()
 
 	registryInformers := []cache.SharedIndexInformer{
 		roleInformer.Informer(),
@@ -91,6 +93,7 @@ func fakeReconcilerFactory(t *testing.T, stopc <-chan struct{}, options ...fakeR
 		serviceInformer.Informer(),
 		podInformer.Informer(),
 		configMapInformer.Informer(),
+		networkPolicyInformer.Informer(),
 	}
 
 	lister := operatorlister.NewLister()
@@ -100,6 +103,7 @@ func fakeReconcilerFactory(t *testing.T, stopc <-chan struct{}, options ...fakeR
 	lister.CoreV1().RegisterServiceLister(testNamespace, serviceInformer.Lister())
 	lister.CoreV1().RegisterPodLister(testNamespace, podInformer.Lister())
 	lister.CoreV1().RegisterConfigMapLister(testNamespace, configMapInformer.Lister())
+	lister.NetworkingV1().RegisterNetworkPolicyLister(testNamespace, networkPolicyInformer.Lister())
 
 	rec := &registryReconcilerFactory{
 		now:                  config.now,
@@ -195,6 +199,8 @@ func objectsForCatalogSource(t *testing.T, catsrc *v1alpha1.CatalogSource) []run
 	switch catsrc.Spec.SourceType {
 	case v1alpha1.SourceTypeInternal, v1alpha1.SourceTypeConfigmap:
 		decorated := configMapCatalogSourceDecorator{catsrc, runAsUser}
+		grpcServerNetworkPolicy := decorated.GRPCServerNetworkPolicy()
+		unpackBundlesNetworkPolicy := decorated.UnpackBundlesNetworkPolicy()
 		service, err := decorated.Service()
 		if err != nil {
 			t.Fatal(err)
@@ -205,6 +211,8 @@ func objectsForCatalogSource(t *testing.T, catsrc *v1alpha1.CatalogSource) []run
 			t.Fatal(err)
 		}
 		objs = append(objs,
+			grpcServerNetworkPolicy,
+			unpackBundlesNetworkPolicy,
 			pod,
 			service,
 			serviceAccount,
@@ -212,6 +220,8 @@ func objectsForCatalogSource(t *testing.T, catsrc *v1alpha1.CatalogSource) []run
 	case v1alpha1.SourceTypeGrpc:
 		if catsrc.Spec.Image != "" {
 			decorated := grpcCatalogSourceDecorator{CatalogSource: catsrc, createPodAsUser: runAsUser, opmImage: ""}
+			grpcServerNetworkPolicy := decorated.GRPCServerNetworkPolicy()
+			unpackBundlesNetworkPolicy := decorated.UnpackBundlesNetworkPolicy()
 			serviceAccount := decorated.ServiceAccount()
 			service, err := decorated.Service()
 			if err != nil {
@@ -222,6 +232,8 @@ func objectsForCatalogSource(t *testing.T, catsrc *v1alpha1.CatalogSource) []run
 				t.Fatal(err)
 			}
 			objs = append(objs,
+				grpcServerNetworkPolicy,
+				unpackBundlesNetworkPolicy,
 				pod,
 				service,
 				serviceAccount,
@@ -342,6 +354,24 @@ func TestConfigMapRegistryReconciler(t *testing.T) {
 				},
 			},
 		},
+		{
+			testName: "ExistingRegistry/BadNetworkPolicies",
+			in: in{
+				cluster: cluster{
+					k8sObjs: append(setLabel(objectsForCatalogSource(t, validCatalogSource), &networkingv1.NetworkPolicy{}, CatalogSourceLabelKey, "wrongValue"), validConfigMap),
+				},
+				catsrc: validCatalogSource,
+			},
+			out: out{
+				status: &v1alpha1.RegistryServiceStatus{
+					CreatedAt:        now(),
+					Protocol:         "grpc",
+					ServiceName:      "cool-catalog",
+					ServiceNamespace: testNamespace,
+					Port:             "50051",
+				},
+			},
+		},
 		{
 			testName: "ExistingRegistry/BadServiceAccount",
 			in: in{
@@ -504,6 +534,16 @@ func TestConfigMapRegistryReconciler(t *testing.T) {
 			require.Equal(t, pod.GetLabels(), outPod.GetLabels())
 			require.Equal(t, pod.Spec, outPod.Spec)
 
+			grpcServerNetworkPolicy := decorated.GRPCServerNetworkPolicy()
+			outGrpcServerNetworkPolicy, err := client.KubernetesInterface().NetworkingV1().NetworkPolicies(grpcServerNetworkPolicy.GetNamespace()).Get(context.TODO(), grpcServerNetworkPolicy.GetName(), metav1.GetOptions{})
+			require.NoError(t, err)
+			require.Equal(t, grpcServerNetworkPolicy, outGrpcServerNetworkPolicy)
+
+			unpackBundlesNetworkPolicy := decorated.UnpackBundlesNetworkPolicy()
+			outUnpackBundlesNetworkPolicy, err := client.KubernetesInterface().NetworkingV1().NetworkPolicies(unpackBundlesNetworkPolicy.GetNamespace()).Get(context.TODO(), unpackBundlesNetworkPolicy.GetName(), metav1.GetOptions{})
+			require.NoError(t, err)
+			require.Equal(t, unpackBundlesNetworkPolicy, outUnpackBundlesNetworkPolicy)
+
 			service, err := decorated.Service()
 			require.NoError(t, err)
 			outService, err := client.KubernetesInterface().CoreV1().Services(service.GetNamespace()).Get(context.TODO(), service.GetName(), metav1.GetOptions{})
diff --git a/pkg/controller/registry/reconciler/grpc_test.go b/pkg/controller/registry/reconciler/grpc_test.go
index 37bd73aac..d528ea5b9 100644
--- a/pkg/controller/registry/reconciler/grpc_test.go
+++ b/pkg/controller/registry/reconciler/grpc_test.go
@@ -9,6 +9,7 @@ import (
 	"github.com/sirupsen/logrus"
 	"github.com/stretchr/testify/require"
 	corev1 "k8s.io/api/core/v1"
+	networkingv1 "k8s.io/api/networking/v1"
 	apierrors "k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/labels"
@@ -218,6 +219,24 @@ func TestGrpcRegistryReconciler(t *testing.T) {
 				},
 			},
 		},
+		{
+			testName: "Grpc/ExistingRegistry/BadNetworkPolicies",
+			in: in{
+				cluster: cluster{
+					k8sObjs: setLabel(objectsForCatalogSource(t, validGrpcCatalogSource("test-img", "")), &networkingv1.NetworkPolicy{}, CatalogSourceLabelKey, "wrongValue"),
+				},
+				catsrc: validGrpcCatalogSource("test-img", ""),
+			},
+			out: out{
+				status: &v1alpha1.RegistryServiceStatus{
+					CreatedAt:        now(),
+					Protocol:         "grpc",
+					ServiceName:      "img-catalog",
+					ServiceNamespace: testNamespace,
+					Port:             "50051",
+				},
+			},
+		},
 		{
 			testName: "Grpc/ExistingRegistry/BadService",
 			in: in{
@@ -388,6 +407,8 @@ func TestGrpcRegistryReconciler(t *testing.T) {
 
 			// Check for resource existence
 			decorated := grpcCatalogSourceDecorator{CatalogSource: tt.in.catsrc, createPodAsUser: runAsUser}
+			grpcServerNetworkPolicy := decorated.GRPCServerNetworkPolicy()
+			unpackBundlesNetworkPolicy := decorated.UnpackBundlesNetworkPolicy()
 			sa := decorated.ServiceAccount()
 			pod, err := decorated.Pod(sa, defaultPodSecurityConfig)
 			if err != nil {
@@ -398,6 +419,8 @@ func TestGrpcRegistryReconciler(t *testing.T) {
 				t.Fatal(err)
 			}
 			listOptions := metav1.ListOptions{LabelSelector: labels.SelectorFromSet(labels.Set{CatalogSourceLabelKey: tt.in.catsrc.GetName()}).String()}
+			outGRPCNetworkPolicy, grpcNPErr := client.KubernetesInterface().NetworkingV1().NetworkPolicies(grpcServerNetworkPolicy.GetNamespace()).Get(context.TODO(), grpcServerNetworkPolicy.GetName(), metav1.GetOptions{})
+			outUnpackBundlesNetworkPolicy, ubNPErr := client.KubernetesInterface().NetworkingV1().NetworkPolicies(unpackBundlesNetworkPolicy.GetNamespace()).Get(context.TODO(), unpackBundlesNetworkPolicy.GetName(), metav1.GetOptions{})
 			outPods, podErr := client.KubernetesInterface().CoreV1().Pods(pod.GetNamespace()).List(context.TODO(), listOptions)
 			outService, serviceErr := client.KubernetesInterface().CoreV1().Services(service.GetNamespace()).Get(context.TODO(), service.GetName(), metav1.GetOptions{})
 			outsa, saerr := client.KubernetesInterface().CoreV1().ServiceAccounts(sa.GetNamespace()).Get(context.TODO(), sa.GetName(), metav1.GetOptions{})
@@ -411,6 +434,10 @@ func TestGrpcRegistryReconciler(t *testing.T) {
 				require.Equal(t, pod.GetLabels(), outPod.GetLabels())
 				require.Equal(t, pod.GetAnnotations(), outPod.GetAnnotations())
 				require.Equal(t, pod.Spec, outPod.Spec)
+				require.NoError(t, grpcNPErr)
+				require.NoError(t, ubNPErr)
+				require.Equal(t, grpcServerNetworkPolicy, outGRPCNetworkPolicy)
+				require.Equal(t, unpackBundlesNetworkPolicy, outUnpackBundlesNetworkPolicy)
 				require.NoError(t, serviceErr)
 				require.Equal(t, service, outService)
 				require.NoError(t, saerr)
@@ -422,6 +449,8 @@ func TestGrpcRegistryReconciler(t *testing.T) {
 				require.NoError(t, podErr)
 				require.Len(t, outPods.Items, 0)
 				require.NoError(t, err)
+				require.True(t, apierrors.IsNotFound(grpcNPErr))
+				require.True(t, apierrors.IsNotFound(ubNPErr))
 				require.True(t, apierrors.IsNotFound(serviceErr))
 			}
 		})
@@ -539,6 +568,18 @@ func TestGrpcRegistryChecker(t *testing.T) {
 				healthy: false,
 			},
 		},
+		{
+			testName: "Grpc/ExistingRegistry/Image/BadNetworkPolicies",
+			in: in{
+				cluster: cluster{
+					k8sObjs: setLabel(objectsForCatalogSource(t, validGrpcCatalogSource("test-img", "")), &networkingv1.NetworkPolicy{}, CatalogSourceLabelKey, "wrongValue"),
+				},
+				catsrc: validGrpcCatalogSource("test-img", ""),
+			},
+			out: out{
+				healthy: false,
+			},
+		},
 		{
 			testName: "Grpc/ExistingRegistry/Image/BadService",
 			in: in{
diff --git a/test/e2e/catalog_e2e_test.go b/test/e2e/catalog_e2e_test.go
index 39fa0497d..3d03489b6 100644
--- a/test/e2e/catalog_e2e_test.go
+++ b/test/e2e/catalog_e2e_test.go
@@ -4,6 +4,8 @@ import (
 	"context"
 	"errors"
 	"fmt"
+	"k8s.io/apimachinery/pkg/util/intstr"
+
 	"net"
 	"path/filepath"
 	"strconv"
@@ -21,10 +23,12 @@ import (
 	. "github.com/onsi/gomega"
 	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
+	networkingv1 "k8s.io/api/networking/v1"
 	"k8s.io/apimachinery/pkg/api/meta"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/labels"
 	"k8s.io/apimachinery/pkg/types"
+	networkingv1ac "k8s.io/client-go/applyconfigurations/networking/v1"
 
 	"github.com/operator-framework/api/pkg/lib/version"
 	"github.com/operator-framework/api/pkg/operators/v1alpha1"
@@ -750,6 +754,136 @@ var _ = Describe("Starting CatalogSource e2e tests", Label("CatalogSource"), fun
 		Expect(registryPods.Items).To(HaveLen(1), "unexpected number of replacement registry pods found")
 	})
 
+	for _, npType := range []string{"grpc-server", "unpack-bundles"} {
+		It(fmt.Sprintf("delete registry %s network policy triggers recreation", npType), func() {
+			By("Creating CatalogSource using an external registry image (community-operators)")
+			source := &v1alpha1.CatalogSource{
+				TypeMeta: metav1.TypeMeta{
+					Kind:       v1alpha1.CatalogSourceKind,
+					APIVersion: v1alpha1.CatalogSourceCRDAPIVersion,
+				},
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      genName("catalog-"),
+					Namespace: generatedNamespace.GetName(),
+				},
+				Spec: v1alpha1.CatalogSourceSpec{
+					SourceType: v1alpha1.SourceTypeGrpc,
+					Image:      communityOperatorsImage,
+					GrpcPodConfig: &v1alpha1.GrpcPodConfig{
+						SecurityContextConfig: v1alpha1.Restricted,
+					},
+				},
+			}
+
+			source, err := crc.OperatorsV1alpha1().CatalogSources(source.GetNamespace()).Create(context.Background(), source, metav1.CreateOptions{})
+			Expect(err).ShouldNot(HaveOccurred())
+
+			npName := fmt.Sprintf("%s-%s", source.GetName(), npType)
+
+			var networkPolicy *networkingv1.NetworkPolicy
+			Eventually(func() error {
+				networkPolicy, err = c.KubernetesInterface().NetworkingV1().NetworkPolicies(source.GetNamespace()).Get(context.Background(), npName, metav1.GetOptions{})
+				return err
+			}, pollDuration, pollInterval).Should(Succeed())
+			Expect(networkPolicy).NotTo(BeNil())
+
+			By("Storing the UID for later comparison")
+			uid := networkPolicy.GetUID()
+
+			By("Deleting the network policy")
+			err = c.KubernetesInterface().NetworkingV1().NetworkPolicies(source.GetNamespace()).Delete(context.Background(), npName, metav1.DeleteOptions{})
+			Expect(err).ShouldNot(HaveOccurred())
+
+			By("Waiting for a new network policy be created")
+			Eventually(func() error {
+				networkPolicy, err = c.KubernetesInterface().NetworkingV1().NetworkPolicies(source.GetNamespace()).Get(context.Background(), npName, metav1.GetOptions{})
+				if err != nil {
+					if k8serror.IsNotFound(err) {
+						ctx.Ctx().Logf("waiting for new network policy to be created")
+					} else {
+						ctx.Ctx().Logf("error getting network policy %q: %v", npName, err)
+					}
+					return err
+				}
+				if networkPolicy.GetUID() == uid {
+					return fmt.Errorf("network policy with original uid still exists... (did the deletion somehow fail?)")
+				}
+				return nil
+			}, pollDuration, pollInterval).Should(Succeed())
+		})
+
+		It(fmt.Sprintf("change registry %s network policy triggers revert to desired", npType), func() {
+			By("Create CatalogSource using an external registry image (community-operators)")
+			source := &v1alpha1.CatalogSource{
+				TypeMeta: metav1.TypeMeta{
+					Kind:       v1alpha1.CatalogSourceKind,
+					APIVersion: v1alpha1.CatalogSourceCRDAPIVersion,
+				},
+				ObjectMeta: metav1.ObjectMeta{
+					Name:      genName("catalog-"),
+					Namespace: generatedNamespace.GetName(),
+				},
+				Spec: v1alpha1.CatalogSourceSpec{
+					SourceType: v1alpha1.SourceTypeGrpc,
+					Image:      communityOperatorsImage,
+					GrpcPodConfig: &v1alpha1.GrpcPodConfig{
+						SecurityContextConfig: v1alpha1.Restricted,
+					},
+				},
+			}
+
+			source, err := crc.OperatorsV1alpha1().CatalogSources(source.GetNamespace()).Create(context.Background(), source, metav1.CreateOptions{})
+			Expect(err).ShouldNot(HaveOccurred())
+
+			npName := fmt.Sprintf("%s-%s", source.GetName(), npType)
+
+			var networkPolicy *networkingv1.NetworkPolicy
+			Eventually(func() error {
+				networkPolicy, err = c.KubernetesInterface().NetworkingV1().NetworkPolicies(source.GetNamespace()).Get(context.Background(), npName, metav1.GetOptions{})
+				return err
+			}, pollDuration, pollInterval).Should(Succeed())
+			Expect(networkPolicy).NotTo(BeNil())
+
+			By("Patching the network policy with an undesirable egress policy")
+			npac := networkingv1ac.NetworkPolicy(npName, source.GetNamespace()).
+				WithSpec(networkingv1ac.NetworkPolicySpec().
+					WithEgress(networkingv1ac.NetworkPolicyEgressRule().
+						WithPorts(networkingv1ac.NetworkPolicyPort().
+							WithProtocol(corev1.ProtocolTCP).
+							WithPort(intstr.FromString("foobar")),
+						),
+					),
+				)
+			np, err := c.KubernetesInterface().NetworkingV1().NetworkPolicies(source.GetNamespace()).Apply(context.Background(), npac, metav1.ApplyOptions{FieldManager: "olm-e2e-test", Force: true})
+			Expect(err).ShouldNot(HaveOccurred())
+			Expect(np.Spec.Egress).To(HaveLen(1))
+
+			By("Waiting for the network policy be reverted")
+			Eventually(func() error {
+				np, err := c.KubernetesInterface().NetworkingV1().NetworkPolicies(source.GetNamespace()).Get(context.Background(), npName, metav1.GetOptions{})
+				if err != nil {
+					ctx.Ctx().Logf("error getting network policy %q: %v", npName, err)
+					return err
+				}
+
+				if needsRevert := func() bool {
+					for _, rule := range np.Spec.Egress {
+						for _, port := range rule.Ports {
+							if port.Port.String() == "foobar" {
+								return true
+							}
+						}
+					}
+					return false
+				}(); needsRevert {
+					ctx.Ctx().Logf("waiting for egress rule to be reverted")
+					return fmt.Errorf("extra network policy egress rule has not been reverted")
+				}
+				return nil
+			}, pollDuration, pollInterval).Should(Succeed())
+		})
+	}
+
 	It("configure gRPC registry pod to extract content", func() {
 
 		By("Create gRPC CatalogSource using an external registry image (community-operators)")