diff --git a/pkg/netpol/connlist/connlist.go b/pkg/netpol/connlist/connlist.go
index e929dde7..1c76d304 100644
--- a/pkg/netpol/connlist/connlist.go
+++ b/pkg/netpol/connlist/connlist.go
@@ -363,7 +363,7 @@ func GetConnectionSetFromP2PConnection(c Peer2PeerConnection) *common.Connection
//////////////////////////////////////////////////////////////////////////////////////////////
-func (ca *ConnlistAnalyzer) includePairOfWorkloads(pe *eval.PolicyEngine, src, dst eval.Peer) bool {
+func (ca *ConnlistAnalyzer) includePairOfWorkloads(pe *eval.PolicyEngine, src, dst Peer) bool {
if src.IsPeerIPType() && dst.IsPeerIPType() {
return false
}
@@ -376,14 +376,12 @@ func (ca *ConnlistAnalyzer) includePairOfWorkloads(pe *eval.PolicyEngine, src, d
if ca.exposureAnalysis && !ca.includePairWithRepresentativePeer(pe, src, dst) {
return false
}
- if ca.focusWorkload == "" {
- return true
- }
- // at least one of src/dst should be the focus workload
+
+ // no focusworkload or at least one of src/dst should be the focus workload
return ca.isPeerFocusWorkload(src) || ca.isPeerFocusWorkload(dst)
}
-func (ca *ConnlistAnalyzer) includePairWithRepresentativePeer(pe *eval.PolicyEngine, src, dst eval.Peer) bool {
+func (ca *ConnlistAnalyzer) includePairWithRepresentativePeer(pe *eval.PolicyEngine, src, dst Peer) bool {
isRepSrc := pe.IsRepresentativePeer(src)
isRepDst := pe.IsRepresentativePeer(dst)
// cases when at least one of the peers is representative peer; when not to include the peers pair:
@@ -403,12 +401,15 @@ func (ca *ConnlistAnalyzer) includePairWithRepresentativePeer(pe *eval.PolicyEng
return true
}
-func getPeerNsNameFormat(peer eval.Peer) string {
+func getPeerNsNameFormat(peer Peer) string {
return types.NamespacedName{Namespace: peer.Namespace(), Name: peer.Name()}.String()
}
-func (ca *ConnlistAnalyzer) isPeerFocusWorkload(peer eval.Peer) bool {
- return !peer.IsPeerIPType() && (peer.Name() == ca.focusWorkload || getPeerNsNameFormat(peer) == ca.focusWorkload)
+// isPeerFocusWorkload returns true if focus-workload flag is not used (each peer is included),
+// or if the focus-workload is equal to peer's name
+func (ca *ConnlistAnalyzer) isPeerFocusWorkload(peer Peer) bool {
+ return ca.focusWorkload == "" ||
+ (!peer.IsPeerIPType() && (peer.Name() == ca.focusWorkload || getPeerNsNameFormat(peer) == ca.focusWorkload))
}
func convertEvalPeersToConnlistPeer(peers []eval.Peer) []Peer {
@@ -500,7 +501,7 @@ func (ca *ConnlistAnalyzer) existsFocusWorkload(peers []Peer, excludeIngressAnal
// check if the focusworkload is in the peers
for _, peer := range peers {
- if ca.focusWorkload == peer.Name() || ca.focusWorkload == getPeerNsNameFormat(peer) {
+ if ca.isPeerFocusWorkload(peer) {
return true, ""
}
}
@@ -531,7 +532,7 @@ func (ca *ConnlistAnalyzer) getConnectionsBetweenPeers(pe *eval.PolicyEngine, pe
return nil, nil, err
}
if ca.exposureAnalysis {
- err = updatePeersGeneralExposureData(pe, srcPeer, dstPeer, ingressSet, egressSet, exposureMaps)
+ err = ca.updatePeersGeneralExposureData(pe, srcPeer, dstPeer, ingressSet, egressSet, exposureMaps)
if err != nil {
return nil, nil, err
}
@@ -641,7 +642,8 @@ func createConnectionObject(allowedConnections common.Connection, src, dst Peer)
}
// updatePeersGeneralExposureData updates src and dst connections to entire world/cluster on the exposures map
-func updatePeersGeneralExposureData(pe *eval.PolicyEngine, src, dst Peer, ingressSet, egressSet map[Peer]bool, exMaps *exposureMaps) error {
+func (ca *ConnlistAnalyzer) updatePeersGeneralExposureData(pe *eval.PolicyEngine, src, dst Peer, ingressSet, egressSet map[Peer]bool,
+ exMaps *exposureMaps) error {
// when computing allowed conns between the peers,(even on first time)
// if a workload peer is not protected by netpols this was definitely detected;
// also exposure to entire cluster was definitely computed for src or/and dst (if its a workload peer)
@@ -652,7 +654,7 @@ func updatePeersGeneralExposureData(pe *eval.PolicyEngine, src, dst Peer, ingres
// (e.g. only one peer with one netpol exposing the peer to entire cluster, no netpols)
var err error
// 1. only on first time : add general exposure data for the src peer (on egress)
- if !src.IsPeerIPType() && !pe.IsRepresentativePeer(src) && !egressSet[src] {
+ if ca.shouldAddPeerGeneralExposureData(pe, src, egressSet) {
err = exMaps.addPeerGeneralExposure(pe, src, false)
if err != nil {
return err
@@ -660,9 +662,20 @@ func updatePeersGeneralExposureData(pe *eval.PolicyEngine, src, dst Peer, ingres
}
egressSet[src] = true
// 2. only on first time : add general exposure data for the dst peer (on ingress)
- if !dst.IsPeerIPType() && !pe.IsRepresentativePeer(dst) && !ingressSet[dst] {
+ if ca.shouldAddPeerGeneralExposureData(pe, dst, ingressSet) {
err = exMaps.addPeerGeneralExposure(pe, dst, true)
}
ingressSet[dst] = true
return err
}
+
+// shouldAddPeerGeneralExposureData returns whether should add given peer's general
+// exposure data to the exposure results.
+// returns true if :
+// - the peer is not IP type
+// - the peer is not representative peer
+// - focus-workload flag is not used or the peer is the focus-workload
+// - it is first time the peer is visited
+func (ca *ConnlistAnalyzer) shouldAddPeerGeneralExposureData(pe *eval.PolicyEngine, peer Peer, xgressSet map[Peer]bool) bool {
+ return !peer.IsPeerIPType() && !pe.IsRepresentativePeer(peer) && !xgressSet[peer] && ca.isPeerFocusWorkload(peer)
+}
diff --git a/pkg/netpol/connlist/connlist_test.go b/pkg/netpol/connlist/connlist_test.go
index bfef2314..79bef84f 100644
--- a/pkg/netpol/connlist/connlist_test.go
+++ b/pkg/netpol/connlist/connlist_test.go
@@ -760,6 +760,20 @@ var goodPathTests = []struct {
exposureAnalysis: true,
outputFormats: ExposureValidFormats,
},
+ {
+ testDirName: "acs-security-demos",
+ exposureAnalysis: true,
+ // test with focus-workload that appears in exposure-analysis result
+ focusWorkload: "frontend/webapp",
+ outputFormats: ExposureValidFormats,
+ },
+ {
+ testDirName: "acs-security-demos",
+ exposureAnalysis: true,
+ // test with focus-workload that does not appear in exposure-analysis result
+ focusWorkload: "backend/catalog",
+ outputFormats: ExposureValidFormats,
+ },
{
testDirName: "test_allow_all",
exposureAnalysis: true,
@@ -785,6 +799,12 @@ var goodPathTests = []struct {
exposureAnalysis: true,
outputFormats: ExposureValidFormats,
},
+ {
+ testDirName: "test_matched_and_unmatched_rules",
+ exposureAnalysis: true,
+ focusWorkload: "hello-world/workload-a",
+ outputFormats: ExposureValidFormats,
+ },
{
testDirName: "test_only_matched_rules",
exposureAnalysis: true,
@@ -870,9 +890,27 @@ var goodPathTests = []struct {
exposureAnalysis: true,
outputFormats: ExposureValidFormats,
},
+ {
+ testDirName: "onlineboutique_workloads",
+ exposureAnalysis: true,
+ focusWorkload: "default/loadgenerator",
+ outputFormats: ExposureValidFormats,
+ },
{
testDirName: "k8s_ingress_test_new",
exposureAnalysis: true,
outputFormats: ExposureValidFormats,
},
+ {
+ testDirName: "k8s_ingress_test_new",
+ exposureAnalysis: true,
+ focusWorkload: "details-v1-79f774bdb9",
+ outputFormats: ExposureValidFormats,
+ },
+ {
+ testDirName: "k8s_ingress_test",
+ exposureAnalysis: true,
+ focusWorkload: "ratings-v1-b6994bb9",
+ outputFormats: ExposureValidFormats,
+ },
}
diff --git a/pkg/netpol/connlist/conns_formatter.go b/pkg/netpol/connlist/conns_formatter.go
index b6a97ce3..980cd8c5 100644
--- a/pkg/netpol/connlist/conns_formatter.go
+++ b/pkg/netpol/connlist/conns_formatter.go
@@ -74,8 +74,8 @@ func formExposureItemAsSingleConnFiled(peerStr string, exposureItem XgressExposu
if exposureItem.IsExposedToEntireCluster() {
return formSingleExposureConn(peerStr, entireCluster, exposureItem.PotentialConnectivity(), isIngress)
}
- repPeerStr := getRepresentativeNamespaceString(exposureItem.NamespaceLabels()) + "/" +
- getRepresentativePodString(exposureItem.PodLabels())
+ repPeerStr := getRepresentativeNamespaceString(exposureItem.NamespaceLabels(), true) + "/" +
+ getRepresentativePodString(exposureItem.PodLabels(), true)
return formSingleExposureConn(peerStr, repPeerStr, exposureItem.PotentialConnectivity(), isIngress)
}
@@ -85,27 +85,42 @@ func convertLabelsMapToString(labelsMap map[string]string) string {
}
const (
- mapOpen = "{"
- mapClose = "}"
+ stringInBrackets = "[%s]"
+ mapOpen = "{"
+ mapClose = "}"
)
-// getRepresentativeNamespaceString returns a string representation of a potential peer with namespace labels
-func getRepresentativeNamespaceString(nsLabels map[string]string) string {
+// getRepresentativeNamespaceString returns a string representation of a potential peer with namespace labels.
+// if namespace with multiple words adds [] , in case of textual (non-graphical) output
+func getRepresentativeNamespaceString(nsLabels map[string]string, txtOutFlag bool) string {
nsName, ok := nsLabels[common.K8sNsNameLabelKey]
if len(nsLabels) == 1 && ok {
return nsName
}
+ res := ""
if len(nsLabels) > 0 {
- return "namespace with " + mapOpen + convertLabelsMapToString(nsLabels) + mapClose
+ res += "namespace with " + mapOpen + convertLabelsMapToString(nsLabels) + mapClose
+ } else {
+ res += allNamespacesLbl
}
- return allNamespacesLbl
+ if txtOutFlag {
+ return fmt.Sprintf(stringInBrackets, res)
+ }
+ return res
}
// getRepresentativePodString returns a string representation of potential peer with pod labels
-// or all pods string for empty pod labels map (which indicates all pods)
-func getRepresentativePodString(podLabels map[string]string) string {
+// or all pods string for empty pod labels map (which indicates all pods).
+// adds [] in case of textual (non-graphical) output
+func getRepresentativePodString(podLabels map[string]string, txtOutFlag bool) string {
+ res := ""
if len(podLabels) == 0 {
- return allPeersLbl
+ res += allPeersLbl
+ } else {
+ res += "pod with " + mapOpen + convertLabelsMapToString(podLabels) + mapClose
+ }
+ if txtOutFlag {
+ return fmt.Sprintf(stringInBrackets, res)
}
- return "pod with " + mapOpen + convertLabelsMapToString(podLabels) + mapClose
+ return res
}
diff --git a/pkg/netpol/connlist/conns_formatter_dot.go b/pkg/netpol/connlist/conns_formatter_dot.go
index 20ed2af6..73c564e9 100644
--- a/pkg/netpol/connlist/conns_formatter_dot.go
+++ b/pkg/netpol/connlist/conns_formatter_dot.go
@@ -150,17 +150,17 @@ func getXgressExposureEdges(exposedPeerStr string, xgressExpData []XgressExposur
data.PotentialConnectivity().(*common.ConnectionSet)))
continue // if a data contains exposure to entire cluster it does not specify labels
}
- nsRepLabel := getRepresentativeNamespaceString(data.NamespaceLabels())
- repPeerLabel := getRepresentativePodString(data.PodLabels())
+ nsRepLabel := getRepresentativeNamespaceString(data.NamespaceLabels(), false)
+ repPeerLabel := getRepresentativePodString(data.PodLabels(), false)
repPeersStr := repPeerLabel + "_in_" + nsRepLabel // to get a unique string name of the peer node
if !representativeVisited[repPeersStr] {
representativeVisited[repPeersStr] = true
peerLine := getRepPeerLine(repPeersStr, repPeerLabel)
// ns label maybe a name of an existing namespace, so check where to add the peer
if _, ok := nsPeers[nsRepLabel]; ok { // in real ns
- dotformatting.AddPeerToNsGroup(getRepresentativeNamespaceString(data.NamespaceLabels()), peerLine, nsPeers)
+ dotformatting.AddPeerToNsGroup(nsRepLabel, peerLine, nsPeers)
} else { // in a representative ns
- dotformatting.AddPeerToNsGroup(getRepresentativeNamespaceString(data.NamespaceLabels()), peerLine, nsRepPeers)
+ dotformatting.AddPeerToNsGroup(nsRepLabel, peerLine, nsRepPeers)
}
}
xgressEdges = append(xgressEdges, getExposureEdgeLine(exposedPeerStr, repPeersStr, isIngress,
diff --git a/test_outputs/connlist/exposure_acs-security-demos_focus_workload_backend_catalog_connlist_output.dot b/test_outputs/connlist/exposure_acs-security-demos_focus_workload_backend_catalog_connlist_output.dot
new file mode 100644
index 00000000..93a4e6d3
--- /dev/null
+++ b/test_outputs/connlist/exposure_acs-security-demos_focus_workload_backend_catalog_connlist_output.dot
@@ -0,0 +1,12 @@
+digraph {
+ subgraph "cluster_backend" {
+ color="black"
+ fontcolor="black"
+ "backend/catalog[Deployment]" [label="catalog[Deployment]" color="blue" fontcolor="blue"]
+ "backend/recommendation[Deployment]" [label="recommendation[Deployment]" color="blue" fontcolor="blue"]
+ "backend/reports[Deployment]" [label="reports[Deployment]" color="blue" fontcolor="blue"]
+ label="backend"
+ }
+ "backend/recommendation[Deployment]" -> "backend/catalog[Deployment]" [label="TCP 8080" color="gold2" fontcolor="darkgreen"]
+ "backend/reports[Deployment]" -> "backend/catalog[Deployment]" [label="TCP 8080" color="gold2" fontcolor="darkgreen"]
+}
\ No newline at end of file
diff --git a/test_outputs/connlist/exposure_acs-security-demos_focus_workload_backend_catalog_connlist_output.dot.png b/test_outputs/connlist/exposure_acs-security-demos_focus_workload_backend_catalog_connlist_output.dot.png
new file mode 100644
index 00000000..c5c1861c
Binary files /dev/null and b/test_outputs/connlist/exposure_acs-security-demos_focus_workload_backend_catalog_connlist_output.dot.png differ
diff --git a/test_outputs/connlist/exposure_acs-security-demos_focus_workload_backend_catalog_connlist_output.dot.svg b/test_outputs/connlist/exposure_acs-security-demos_focus_workload_backend_catalog_connlist_output.dot.svg
new file mode 100644
index 00000000..a7f669e3
--- /dev/null
+++ b/test_outputs/connlist/exposure_acs-security-demos_focus_workload_backend_catalog_connlist_output.dot.svg
@@ -0,0 +1,49 @@
+
+
+
+
+
diff --git a/test_outputs/connlist/exposure_acs-security-demos_focus_workload_backend_catalog_connlist_output.txt b/test_outputs/connlist/exposure_acs-security-demos_focus_workload_backend_catalog_connlist_output.txt
new file mode 100644
index 00000000..6be687c7
--- /dev/null
+++ b/test_outputs/connlist/exposure_acs-security-demos_focus_workload_backend_catalog_connlist_output.txt
@@ -0,0 +1,2 @@
+backend/recommendation[Deployment] => backend/catalog[Deployment] : TCP 8080
+backend/reports[Deployment] => backend/catalog[Deployment] : TCP 8080
\ No newline at end of file
diff --git a/test_outputs/connlist/exposure_acs-security-demos_focus_workload_frontend_webapp_connlist_output.dot b/test_outputs/connlist/exposure_acs-security-demos_focus_workload_frontend_webapp_connlist_output.dot
new file mode 100644
index 00000000..9547ce51
--- /dev/null
+++ b/test_outputs/connlist/exposure_acs-security-demos_focus_workload_frontend_webapp_connlist_output.dot
@@ -0,0 +1,26 @@
+digraph {
+ subgraph "cluster_backend" {
+ color="black"
+ fontcolor="black"
+ "backend/checkout[Deployment]" [label="checkout[Deployment]" color="blue" fontcolor="blue"]
+ "backend/recommendation[Deployment]" [label="recommendation[Deployment]" color="blue" fontcolor="blue"]
+ "backend/reports[Deployment]" [label="reports[Deployment]" color="blue" fontcolor="blue"]
+ "backend/shipping[Deployment]" [label="shipping[Deployment]" color="blue" fontcolor="blue"]
+ label="backend"
+ }
+ subgraph "cluster_frontend" {
+ color="black"
+ fontcolor="black"
+ "frontend/webapp[Deployment]" [label="webapp[Deployment]" color="blue" fontcolor="blue"]
+ label="frontend"
+ }
+ "entire-cluster" [label="entire-cluster" color="red2" fontcolor="red2" shape=diamond]
+ "{ingress-controller}" [label="{ingress-controller}" color="blue" fontcolor="blue"]
+ "entire-cluster" -> "frontend/webapp[Deployment]" [label="TCP 8080" color="gold2" fontcolor="darkgreen"]
+ "frontend/webapp[Deployment]" -> "backend/checkout[Deployment]" [label="TCP 8080" color="gold2" fontcolor="darkgreen"]
+ "frontend/webapp[Deployment]" -> "backend/recommendation[Deployment]" [label="TCP 8080" color="gold2" fontcolor="darkgreen"]
+ "frontend/webapp[Deployment]" -> "backend/reports[Deployment]" [label="TCP 8080" color="gold2" fontcolor="darkgreen"]
+ "frontend/webapp[Deployment]" -> "backend/shipping[Deployment]" [label="TCP 8080" color="gold2" fontcolor="darkgreen"]
+ "frontend/webapp[Deployment]" -> "entire-cluster" [label="UDP 5353" color="gold2" fontcolor="darkgreen"]
+ "{ingress-controller}" -> "frontend/webapp[Deployment]" [label="TCP 8080" color="gold2" fontcolor="darkgreen"]
+}
\ No newline at end of file
diff --git a/test_outputs/connlist/exposure_acs-security-demos_focus_workload_frontend_webapp_connlist_output.dot.png b/test_outputs/connlist/exposure_acs-security-demos_focus_workload_frontend_webapp_connlist_output.dot.png
new file mode 100644
index 00000000..b4067d6f
Binary files /dev/null and b/test_outputs/connlist/exposure_acs-security-demos_focus_workload_frontend_webapp_connlist_output.dot.png differ
diff --git a/test_outputs/connlist/exposure_acs-security-demos_focus_workload_frontend_webapp_connlist_output.dot.svg b/test_outputs/connlist/exposure_acs-security-demos_focus_workload_frontend_webapp_connlist_output.dot.svg
new file mode 100644
index 00000000..f0d5cd40
--- /dev/null
+++ b/test_outputs/connlist/exposure_acs-security-demos_focus_workload_frontend_webapp_connlist_output.dot.svg
@@ -0,0 +1,113 @@
+
+
+
+
+
diff --git a/test_outputs/connlist/exposure_acs-security-demos_focus_workload_frontend_webapp_connlist_output.txt b/test_outputs/connlist/exposure_acs-security-demos_focus_workload_frontend_webapp_connlist_output.txt
new file mode 100644
index 00000000..6097ddd4
--- /dev/null
+++ b/test_outputs/connlist/exposure_acs-security-demos_focus_workload_frontend_webapp_connlist_output.txt
@@ -0,0 +1,12 @@
+frontend/webapp[Deployment] => backend/checkout[Deployment] : TCP 8080
+frontend/webapp[Deployment] => backend/recommendation[Deployment] : TCP 8080
+frontend/webapp[Deployment] => backend/reports[Deployment] : TCP 8080
+frontend/webapp[Deployment] => backend/shipping[Deployment] : TCP 8080
+{ingress-controller} => frontend/webapp[Deployment] : TCP 8080
+
+Exposure Analysis Result:
+Egress Exposure:
+frontend/webapp[Deployment] => entire-cluster : UDP 5353
+
+Ingress Exposure:
+frontend/webapp[Deployment] <= entire-cluster : TCP 8080
diff --git a/test_outputs/connlist/exposure_k8s_ingress_test_focus_workload_ratings-v1-b6994bb9_connlist_output.dot b/test_outputs/connlist/exposure_k8s_ingress_test_focus_workload_ratings-v1-b6994bb9_connlist_output.dot
new file mode 100644
index 00000000..5a522bf6
--- /dev/null
+++ b/test_outputs/connlist/exposure_k8s_ingress_test_focus_workload_ratings-v1-b6994bb9_connlist_output.dot
@@ -0,0 +1,29 @@
+digraph {
+ subgraph "cluster_default" {
+ color="black"
+ fontcolor="black"
+ "default/details-v1-79f774bdb9[ReplicaSet]" [label="details-v1-79f774bdb9[ReplicaSet]" color="blue" fontcolor="blue"]
+ "default/productpage-v1-6b746f74dc[ReplicaSet]" [label="productpage-v1-6b746f74dc[ReplicaSet]" color="blue" fontcolor="blue"]
+ "default/ratings-v1-b6994bb9[ReplicaSet]" [label="ratings-v1-b6994bb9[ReplicaSet]" color="blue" fontcolor="blue"]
+ "default/reviews-v1-545db77b95[ReplicaSet]" [label="reviews-v1-545db77b95[ReplicaSet]" color="blue" fontcolor="blue"]
+ "default/reviews-v2-7bf8c9648f[ReplicaSet]" [label="reviews-v2-7bf8c9648f[ReplicaSet]" color="blue" fontcolor="blue"]
+ "default/reviews-v3-84779c7bbc[ReplicaSet]" [label="reviews-v3-84779c7bbc[ReplicaSet]" color="blue" fontcolor="blue"]
+ label="default"
+ }
+ "0.0.0.0-255.255.255.255" [label="0.0.0.0-255.255.255.255" color="red2" fontcolor="red2"]
+ "entire-cluster" [label="entire-cluster" color="red2" fontcolor="red2" shape=diamond]
+ "0.0.0.0-255.255.255.255" -> "default/ratings-v1-b6994bb9[ReplicaSet]" [label="All Connections" color="gold2" fontcolor="darkgreen"]
+ "default/details-v1-79f774bdb9[ReplicaSet]" -> "default/ratings-v1-b6994bb9[ReplicaSet]" [label="All Connections" color="gold2" fontcolor="darkgreen"]
+ "default/productpage-v1-6b746f74dc[ReplicaSet]" -> "default/ratings-v1-b6994bb9[ReplicaSet]" [label="All Connections" color="gold2" fontcolor="darkgreen"]
+ "default/ratings-v1-b6994bb9[ReplicaSet]" -> "0.0.0.0-255.255.255.255" [label="All Connections" color="gold2" fontcolor="darkgreen"]
+ "default/ratings-v1-b6994bb9[ReplicaSet]" -> "default/details-v1-79f774bdb9[ReplicaSet]" [label="All Connections" color="gold2" fontcolor="darkgreen"]
+ "default/ratings-v1-b6994bb9[ReplicaSet]" -> "default/productpage-v1-6b746f74dc[ReplicaSet]" [label="All Connections" color="gold2" fontcolor="darkgreen"]
+ "default/ratings-v1-b6994bb9[ReplicaSet]" -> "default/reviews-v1-545db77b95[ReplicaSet]" [label="All Connections" color="gold2" fontcolor="darkgreen"]
+ "default/ratings-v1-b6994bb9[ReplicaSet]" -> "default/reviews-v2-7bf8c9648f[ReplicaSet]" [label="All Connections" color="gold2" fontcolor="darkgreen"]
+ "default/ratings-v1-b6994bb9[ReplicaSet]" -> "default/reviews-v3-84779c7bbc[ReplicaSet]" [label="All Connections" color="gold2" fontcolor="darkgreen"]
+ "default/ratings-v1-b6994bb9[ReplicaSet]" -> "entire-cluster" [label="All Connections" color="gold2" fontcolor="darkgreen"]
+ "default/reviews-v1-545db77b95[ReplicaSet]" -> "default/ratings-v1-b6994bb9[ReplicaSet]" [label="All Connections" color="gold2" fontcolor="darkgreen"]
+ "default/reviews-v2-7bf8c9648f[ReplicaSet]" -> "default/ratings-v1-b6994bb9[ReplicaSet]" [label="All Connections" color="gold2" fontcolor="darkgreen"]
+ "default/reviews-v3-84779c7bbc[ReplicaSet]" -> "default/ratings-v1-b6994bb9[ReplicaSet]" [label="All Connections" color="gold2" fontcolor="darkgreen"]
+ "entire-cluster" -> "default/ratings-v1-b6994bb9[ReplicaSet]" [label="All Connections" color="gold2" fontcolor="darkgreen"]
+}
\ No newline at end of file
diff --git a/test_outputs/connlist/exposure_k8s_ingress_test_focus_workload_ratings-v1-b6994bb9_connlist_output.dot.png b/test_outputs/connlist/exposure_k8s_ingress_test_focus_workload_ratings-v1-b6994bb9_connlist_output.dot.png
new file mode 100644
index 00000000..c06fa245
Binary files /dev/null and b/test_outputs/connlist/exposure_k8s_ingress_test_focus_workload_ratings-v1-b6994bb9_connlist_output.dot.png differ
diff --git a/test_outputs/connlist/exposure_k8s_ingress_test_focus_workload_ratings-v1-b6994bb9_connlist_output.dot.svg b/test_outputs/connlist/exposure_k8s_ingress_test_focus_workload_ratings-v1-b6994bb9_connlist_output.dot.svg
new file mode 100644
index 00000000..c7f26094
--- /dev/null
+++ b/test_outputs/connlist/exposure_k8s_ingress_test_focus_workload_ratings-v1-b6994bb9_connlist_output.dot.svg
@@ -0,0 +1,163 @@
+
+
+
+
+
diff --git a/test_outputs/connlist/exposure_k8s_ingress_test_focus_workload_ratings-v1-b6994bb9_connlist_output.txt b/test_outputs/connlist/exposure_k8s_ingress_test_focus_workload_ratings-v1-b6994bb9_connlist_output.txt
new file mode 100644
index 00000000..8c2be6bb
--- /dev/null
+++ b/test_outputs/connlist/exposure_k8s_ingress_test_focus_workload_ratings-v1-b6994bb9_connlist_output.txt
@@ -0,0 +1,25 @@
+0.0.0.0-255.255.255.255 => default/ratings-v1-b6994bb9[ReplicaSet] : All Connections
+default/details-v1-79f774bdb9[ReplicaSet] => default/ratings-v1-b6994bb9[ReplicaSet] : All Connections
+default/productpage-v1-6b746f74dc[ReplicaSet] => default/ratings-v1-b6994bb9[ReplicaSet] : All Connections
+default/ratings-v1-b6994bb9[ReplicaSet] => 0.0.0.0-255.255.255.255 : All Connections
+default/ratings-v1-b6994bb9[ReplicaSet] => default/details-v1-79f774bdb9[ReplicaSet] : All Connections
+default/ratings-v1-b6994bb9[ReplicaSet] => default/productpage-v1-6b746f74dc[ReplicaSet] : All Connections
+default/ratings-v1-b6994bb9[ReplicaSet] => default/reviews-v1-545db77b95[ReplicaSet] : All Connections
+default/ratings-v1-b6994bb9[ReplicaSet] => default/reviews-v2-7bf8c9648f[ReplicaSet] : All Connections
+default/ratings-v1-b6994bb9[ReplicaSet] => default/reviews-v3-84779c7bbc[ReplicaSet] : All Connections
+default/reviews-v1-545db77b95[ReplicaSet] => default/ratings-v1-b6994bb9[ReplicaSet] : All Connections
+default/reviews-v2-7bf8c9648f[ReplicaSet] => default/ratings-v1-b6994bb9[ReplicaSet] : All Connections
+default/reviews-v3-84779c7bbc[ReplicaSet] => default/ratings-v1-b6994bb9[ReplicaSet] : All Connections
+
+Exposure Analysis Result:
+Egress Exposure:
+default/ratings-v1-b6994bb9[ReplicaSet] => 0.0.0.0-255.255.255.255 : All Connections
+default/ratings-v1-b6994bb9[ReplicaSet] => entire-cluster : All Connections
+
+Ingress Exposure:
+default/ratings-v1-b6994bb9[ReplicaSet] <= 0.0.0.0-255.255.255.255 : All Connections
+default/ratings-v1-b6994bb9[ReplicaSet] <= entire-cluster : All Connections
+
+Workloads not protected by network policies:
+default/ratings-v1-b6994bb9[ReplicaSet] is not protected on Egress
+default/ratings-v1-b6994bb9[ReplicaSet] is not protected on Ingress
diff --git a/test_outputs/connlist/exposure_k8s_ingress_test_new_focus_workload_details-v1-79f774bdb9_connlist_output.dot b/test_outputs/connlist/exposure_k8s_ingress_test_new_focus_workload_details-v1-79f774bdb9_connlist_output.dot
new file mode 100644
index 00000000..e007e982
--- /dev/null
+++ b/test_outputs/connlist/exposure_k8s_ingress_test_new_focus_workload_details-v1-79f774bdb9_connlist_output.dot
@@ -0,0 +1,14 @@
+digraph {
+ subgraph "cluster_default" {
+ color="black"
+ fontcolor="black"
+ "default/details-v1-79f774bdb9[ReplicaSet]" [label="details-v1-79f774bdb9[ReplicaSet]" color="blue" fontcolor="blue"]
+ "default/unicorn[Deployment]" [label="unicorn[Deployment]" color="blue" fontcolor="blue"]
+ label="default"
+ }
+ "entire-cluster" [label="entire-cluster" color="red2" fontcolor="red2" shape=diamond]
+ "{ingress-controller}" [label="{ingress-controller}" color="blue" fontcolor="blue"]
+ "default/unicorn[Deployment]" -> "default/details-v1-79f774bdb9[ReplicaSet]" [label="TCP 9080" color="gold2" fontcolor="darkgreen"]
+ "entire-cluster" -> "default/details-v1-79f774bdb9[ReplicaSet]" [label="TCP 9080" color="gold2" fontcolor="darkgreen"]
+ "{ingress-controller}" -> "default/details-v1-79f774bdb9[ReplicaSet]" [label="TCP 9080" color="gold2" fontcolor="darkgreen"]
+}
\ No newline at end of file
diff --git a/test_outputs/connlist/exposure_k8s_ingress_test_new_focus_workload_details-v1-79f774bdb9_connlist_output.dot.png b/test_outputs/connlist/exposure_k8s_ingress_test_new_focus_workload_details-v1-79f774bdb9_connlist_output.dot.png
new file mode 100644
index 00000000..4da90981
Binary files /dev/null and b/test_outputs/connlist/exposure_k8s_ingress_test_new_focus_workload_details-v1-79f774bdb9_connlist_output.dot.png differ
diff --git a/test_outputs/connlist/exposure_k8s_ingress_test_new_focus_workload_details-v1-79f774bdb9_connlist_output.dot.svg b/test_outputs/connlist/exposure_k8s_ingress_test_new_focus_workload_details-v1-79f774bdb9_connlist_output.dot.svg
new file mode 100644
index 00000000..3a9a05d6
--- /dev/null
+++ b/test_outputs/connlist/exposure_k8s_ingress_test_new_focus_workload_details-v1-79f774bdb9_connlist_output.dot.svg
@@ -0,0 +1,62 @@
+
+
+
+
+
diff --git a/test_outputs/connlist/exposure_k8s_ingress_test_new_focus_workload_details-v1-79f774bdb9_connlist_output.txt b/test_outputs/connlist/exposure_k8s_ingress_test_new_focus_workload_details-v1-79f774bdb9_connlist_output.txt
new file mode 100644
index 00000000..4ba5bc78
--- /dev/null
+++ b/test_outputs/connlist/exposure_k8s_ingress_test_new_focus_workload_details-v1-79f774bdb9_connlist_output.txt
@@ -0,0 +1,7 @@
+default/unicorn[Deployment] => default/details-v1-79f774bdb9[ReplicaSet] : TCP 9080
+{ingress-controller} => default/details-v1-79f774bdb9[ReplicaSet] : TCP 9080
+
+Exposure Analysis Result:
+
+Ingress Exposure:
+default/details-v1-79f774bdb9[ReplicaSet] <= entire-cluster : TCP 9080
diff --git a/test_outputs/connlist/exposure_onlineboutique_workloads_connlist_output.txt b/test_outputs/connlist/exposure_onlineboutique_workloads_connlist_output.txt
index 6789be78..cee8e4a3 100644
--- a/test_outputs/connlist/exposure_onlineboutique_workloads_connlist_output.txt
+++ b/test_outputs/connlist/exposure_onlineboutique_workloads_connlist_output.txt
@@ -18,10 +18,10 @@ default/redis-cart[Deployment] => 0.0.0.0-255.255.255.255 : All Connections
Exposure Analysis Result:
Egress Exposure:
-default/checkoutservice[Deployment] => all namespaces/pod with {k8s-app=kube-dns} : UDP 53
-default/frontend[Deployment] => all namespaces/pod with {k8s-app=kube-dns} : UDP 53
-default/loadgenerator[Deployment] => all namespaces/pod with {k8s-app=kube-dns} : UDP 53
-default/recommendationservice[Deployment] => all namespaces/pod with {k8s-app=kube-dns} : UDP 53
+default/checkoutservice[Deployment] => [all namespaces]/[pod with {k8s-app=kube-dns}] : UDP 53
+default/frontend[Deployment] => [all namespaces]/[pod with {k8s-app=kube-dns}] : UDP 53
+default/loadgenerator[Deployment] => [all namespaces]/[pod with {k8s-app=kube-dns}] : UDP 53
+default/recommendationservice[Deployment] => [all namespaces]/[pod with {k8s-app=kube-dns}] : UDP 53
default/redis-cart[Deployment] => 0.0.0.0-255.255.255.255 : All Connections
default/redis-cart[Deployment] => entire-cluster : All Connections
diff --git a/test_outputs/connlist/exposure_onlineboutique_workloads_focus_workload_default_loadgenerator_connlist_output.dot b/test_outputs/connlist/exposure_onlineboutique_workloads_focus_workload_default_loadgenerator_connlist_output.dot
new file mode 100644
index 00000000..9ea42352
--- /dev/null
+++ b/test_outputs/connlist/exposure_onlineboutique_workloads_focus_workload_default_loadgenerator_connlist_output.dot
@@ -0,0 +1,17 @@
+digraph {
+ subgraph "cluster_default" {
+ color="black"
+ fontcolor="black"
+ "default/frontend[Deployment]" [label="frontend[Deployment]" color="blue" fontcolor="blue"]
+ "default/loadgenerator[Deployment]" [label="loadgenerator[Deployment]" color="blue" fontcolor="blue"]
+ label="default"
+ }
+ subgraph "cluster_all namespaces" {
+ color="red2"
+ fontcolor="red2"
+ "pod with {k8s-app=kube-dns}_in_all namespaces" [label="pod with {k8s-app=kube-dns}" color="red2" fontcolor="red2"]
+ label="all namespaces"
+ }
+ "default/loadgenerator[Deployment]" -> "default/frontend[Deployment]" [label="TCP 8080" color="gold2" fontcolor="darkgreen"]
+ "default/loadgenerator[Deployment]" -> "pod with {k8s-app=kube-dns}_in_all namespaces" [label="UDP 53" color="gold2" fontcolor="darkgreen"]
+}
\ No newline at end of file
diff --git a/test_outputs/connlist/exposure_onlineboutique_workloads_focus_workload_default_loadgenerator_connlist_output.dot.png b/test_outputs/connlist/exposure_onlineboutique_workloads_focus_workload_default_loadgenerator_connlist_output.dot.png
new file mode 100644
index 00000000..5662aa08
Binary files /dev/null and b/test_outputs/connlist/exposure_onlineboutique_workloads_focus_workload_default_loadgenerator_connlist_output.dot.png differ
diff --git a/test_outputs/connlist/exposure_onlineboutique_workloads_focus_workload_default_loadgenerator_connlist_output.dot.svg b/test_outputs/connlist/exposure_onlineboutique_workloads_focus_workload_default_loadgenerator_connlist_output.dot.svg
new file mode 100644
index 00000000..9f141f1a
--- /dev/null
+++ b/test_outputs/connlist/exposure_onlineboutique_workloads_focus_workload_default_loadgenerator_connlist_output.dot.svg
@@ -0,0 +1,54 @@
+
+
+
+
+
diff --git a/test_outputs/connlist/exposure_onlineboutique_workloads_focus_workload_default_loadgenerator_connlist_output.txt b/test_outputs/connlist/exposure_onlineboutique_workloads_focus_workload_default_loadgenerator_connlist_output.txt
new file mode 100644
index 00000000..51f71091
--- /dev/null
+++ b/test_outputs/connlist/exposure_onlineboutique_workloads_focus_workload_default_loadgenerator_connlist_output.txt
@@ -0,0 +1,5 @@
+default/loadgenerator[Deployment] => default/frontend[Deployment] : TCP 8080
+
+Exposure Analysis Result:
+Egress Exposure:
+default/loadgenerator[Deployment] => [all namespaces]/[pod with {k8s-app=kube-dns}] : UDP 53
diff --git a/test_outputs/connlist/exposure_test_conn_to_all_pods_in_a_new_ns_connlist_output.txt b/test_outputs/connlist/exposure_test_conn_to_all_pods_in_a_new_ns_connlist_output.txt
index b07bde9e..777caec2 100644
--- a/test_outputs/connlist/exposure_test_conn_to_all_pods_in_a_new_ns_connlist_output.txt
+++ b/test_outputs/connlist/exposure_test_conn_to_all_pods_in_a_new_ns_connlist_output.txt
@@ -3,4 +3,4 @@ Egress Exposure:
hello-world/workload-a[Deployment] => entire-cluster : All Connections
Ingress Exposure:
-hello-world/workload-a[Deployment] <= backend/all pods : TCP 8050
+hello-world/workload-a[Deployment] <= backend/[all pods] : TCP 8050
diff --git a/test_outputs/connlist/exposure_test_conn_with_new_pod_selector_and_ns_selector_connlist_output.txt b/test_outputs/connlist/exposure_test_conn_with_new_pod_selector_and_ns_selector_connlist_output.txt
index b8a54337..5d6eb70e 100644
--- a/test_outputs/connlist/exposure_test_conn_with_new_pod_selector_and_ns_selector_connlist_output.txt
+++ b/test_outputs/connlist/exposure_test_conn_with_new_pod_selector_and_ns_selector_connlist_output.txt
@@ -6,7 +6,7 @@ hello-world/workload-a[Deployment] => 0.0.0.0-255.255.255.255 : All Connection
hello-world/workload-a[Deployment] => entire-cluster : All Connections
Ingress Exposure:
-hello-world/workload-a[Deployment] <= namespace with {effect=NoSchedule}/pod with {role=monitoring} : TCP 8050
+hello-world/workload-a[Deployment] <= [namespace with {effect=NoSchedule}]/[pod with {role=monitoring}] : TCP 8050
Workloads not protected by network policies:
hello-world/workload-a[Deployment] is not protected on Egress
diff --git a/test_outputs/connlist/exposure_test_conn_with_only_pod_selector_connlist_output.txt b/test_outputs/connlist/exposure_test_conn_with_only_pod_selector_connlist_output.txt
index 5a409a23..f094e98f 100644
--- a/test_outputs/connlist/exposure_test_conn_with_only_pod_selector_connlist_output.txt
+++ b/test_outputs/connlist/exposure_test_conn_with_only_pod_selector_connlist_output.txt
@@ -6,7 +6,7 @@ hello-world/workload-a[Deployment] => 0.0.0.0-255.255.255.255 : All Connection
hello-world/workload-a[Deployment] => entire-cluster : All Connections
Ingress Exposure:
-hello-world/workload-a[Deployment] <= hello-world/pod with {role=monitoring} : TCP 8050
+hello-world/workload-a[Deployment] <= hello-world/[pod with {role=monitoring}] : TCP 8050
Workloads not protected by network policies:
hello-world/workload-a[Deployment] is not protected on Egress
diff --git a/test_outputs/connlist/exposure_test_conn_with_pod_selector_in_any_ns_connlist_output.txt b/test_outputs/connlist/exposure_test_conn_with_pod_selector_in_any_ns_connlist_output.txt
index 93a758b6..c40e6ffd 100644
--- a/test_outputs/connlist/exposure_test_conn_with_pod_selector_in_any_ns_connlist_output.txt
+++ b/test_outputs/connlist/exposure_test_conn_with_pod_selector_in_any_ns_connlist_output.txt
@@ -6,7 +6,7 @@ hello-world/workload-a[Deployment] => 0.0.0.0-255.255.255.255 : All Connection
hello-world/workload-a[Deployment] => entire-cluster : All Connections
Ingress Exposure:
-hello-world/workload-a[Deployment] <= all namespaces/pod with {role=monitoring} : TCP 8050
+hello-world/workload-a[Deployment] <= [all namespaces]/[pod with {role=monitoring}] : TCP 8050
Workloads not protected by network policies:
hello-world/workload-a[Deployment] is not protected on Egress
diff --git a/test_outputs/connlist/exposure_test_egress_exposure_with_named_port_connlist_output.txt b/test_outputs/connlist/exposure_test_egress_exposure_with_named_port_connlist_output.txt
index 1fd11ac6..a930e260 100644
--- a/test_outputs/connlist/exposure_test_egress_exposure_with_named_port_connlist_output.txt
+++ b/test_outputs/connlist/exposure_test_egress_exposure_with_named_port_connlist_output.txt
@@ -1,6 +1,6 @@
Exposure Analysis Result:
Egress Exposure:
-hello-world/workload-a[Deployment] => namespace with {foo.com/managed-state=managed}/all pods : TCP http
+hello-world/workload-a[Deployment] => [namespace with {foo.com/managed-state=managed}]/[all pods] : TCP http
Ingress Exposure:
hello-world/workload-a[Deployment] <= entire-cluster : TCP 8000
diff --git a/test_outputs/connlist/exposure_test_exposure_to_namespace_with_multiple_labels_connlist_output.txt b/test_outputs/connlist/exposure_test_exposure_to_namespace_with_multiple_labels_connlist_output.txt
index 0f62de93..3a3ee313 100644
--- a/test_outputs/connlist/exposure_test_exposure_to_namespace_with_multiple_labels_connlist_output.txt
+++ b/test_outputs/connlist/exposure_test_exposure_to_namespace_with_multiple_labels_connlist_output.txt
@@ -6,7 +6,7 @@ hello-world/workload-a[Deployment] => 0.0.0.0-255.255.255.255 : All Connection
hello-world/workload-a[Deployment] => entire-cluster : All Connections
Ingress Exposure:
-hello-world/workload-a[Deployment] <= namespace with {effect=NoSchedule,release=stable}/all pods : TCP 8050
+hello-world/workload-a[Deployment] <= [namespace with {effect=NoSchedule,release=stable}]/[all pods] : TCP 8050
Workloads not protected by network policies:
hello-world/workload-a[Deployment] is not protected on Egress
diff --git a/test_outputs/connlist/exposure_test_matched_and_unmatched_rules_focus_workload_hello-world_workload-a_connlist_output.dot b/test_outputs/connlist/exposure_test_matched_and_unmatched_rules_focus_workload_hello-world_workload-a_connlist_output.dot
new file mode 100644
index 00000000..fe340f76
--- /dev/null
+++ b/test_outputs/connlist/exposure_test_matched_and_unmatched_rules_focus_workload_hello-world_workload-a_connlist_output.dot
@@ -0,0 +1,16 @@
+digraph {
+ subgraph "cluster_hello_world" {
+ color="black"
+ fontcolor="black"
+ "hello-world/workload-a[Deployment]" [label="workload-a[Deployment]" color="blue" fontcolor="blue"]
+ "hello-world/workload-b[Deployment]" [label="workload-b[Deployment]" color="blue" fontcolor="blue"]
+ label="hello-world"
+ }
+ "0.0.0.0-255.255.255.255" [label="0.0.0.0-255.255.255.255" color="red2" fontcolor="red2"]
+ "entire-cluster" [label="entire-cluster" color="red2" fontcolor="red2" shape=diamond]
+ "entire-cluster" -> "hello-world/workload-a[Deployment]" [label="TCP 8050" color="gold2" fontcolor="darkgreen"]
+ "hello-world/workload-a[Deployment]" -> "0.0.0.0-255.255.255.255" [label="All Connections" color="gold2" fontcolor="darkgreen"]
+ "hello-world/workload-a[Deployment]" -> "entire-cluster" [label="All Connections" color="gold2" fontcolor="darkgreen"]
+ "hello-world/workload-a[Deployment]" -> "hello-world/workload-b[Deployment]" [label="All Connections" color="gold2" fontcolor="darkgreen"]
+ "hello-world/workload-b[Deployment]" -> "hello-world/workload-a[Deployment]" [label="All Connections" color="gold2" fontcolor="darkgreen"]
+}
\ No newline at end of file
diff --git a/test_outputs/connlist/exposure_test_matched_and_unmatched_rules_focus_workload_hello-world_workload-a_connlist_output.dot.png b/test_outputs/connlist/exposure_test_matched_and_unmatched_rules_focus_workload_hello-world_workload-a_connlist_output.dot.png
new file mode 100644
index 00000000..385744ba
Binary files /dev/null and b/test_outputs/connlist/exposure_test_matched_and_unmatched_rules_focus_workload_hello-world_workload-a_connlist_output.dot.png differ
diff --git a/test_outputs/connlist/exposure_test_matched_and_unmatched_rules_focus_workload_hello-world_workload-a_connlist_output.dot.svg b/test_outputs/connlist/exposure_test_matched_and_unmatched_rules_focus_workload_hello-world_workload-a_connlist_output.dot.svg
new file mode 100644
index 00000000..7e6893e6
--- /dev/null
+++ b/test_outputs/connlist/exposure_test_matched_and_unmatched_rules_focus_workload_hello-world_workload-a_connlist_output.dot.svg
@@ -0,0 +1,76 @@
+
+
+
+
+
diff --git a/test_outputs/connlist/exposure_test_matched_and_unmatched_rules_focus_workload_hello-world_workload-a_connlist_output.txt b/test_outputs/connlist/exposure_test_matched_and_unmatched_rules_focus_workload_hello-world_workload-a_connlist_output.txt
new file mode 100644
index 00000000..d90a3cb8
--- /dev/null
+++ b/test_outputs/connlist/exposure_test_matched_and_unmatched_rules_focus_workload_hello-world_workload-a_connlist_output.txt
@@ -0,0 +1,14 @@
+hello-world/workload-a[Deployment] => 0.0.0.0-255.255.255.255 : All Connections
+hello-world/workload-a[Deployment] => hello-world/workload-b[Deployment] : All Connections
+hello-world/workload-b[Deployment] => hello-world/workload-a[Deployment] : All Connections
+
+Exposure Analysis Result:
+Egress Exposure:
+hello-world/workload-a[Deployment] => 0.0.0.0-255.255.255.255 : All Connections
+hello-world/workload-a[Deployment] => entire-cluster : All Connections
+
+Ingress Exposure:
+hello-world/workload-a[Deployment] <= entire-cluster : TCP 8050
+
+Workloads not protected by network policies:
+hello-world/workload-a[Deployment] is not protected on Egress
diff --git a/test_outputs/connlist/exposure_test_multiple_unmatched_rules_connlist_output.txt b/test_outputs/connlist/exposure_test_multiple_unmatched_rules_connlist_output.txt
index 5bc39272..8d627c6d 100644
--- a/test_outputs/connlist/exposure_test_multiple_unmatched_rules_connlist_output.txt
+++ b/test_outputs/connlist/exposure_test_multiple_unmatched_rules_connlist_output.txt
@@ -6,9 +6,9 @@ hello-world/workload-a[Deployment] => 0.0.0.0-255.255.255.255 : All Connection
hello-world/workload-a[Deployment] => entire-cluster : All Connections
Ingress Exposure:
-hello-world/workload-a[Deployment] <= namespace with {effect=NoSchedule}/all pods : TCP 8050
-hello-world/workload-a[Deployment] <= namespace with {foo.com/managed-state=managed}/all pods : TCP 8050
-hello-world/workload-a[Deployment] <= namespace with {release=stable}/all pods : All Connections
+hello-world/workload-a[Deployment] <= [namespace with {effect=NoSchedule}]/[all pods] : TCP 8050
+hello-world/workload-a[Deployment] <= [namespace with {foo.com/managed-state=managed}]/[all pods] : TCP 8050
+hello-world/workload-a[Deployment] <= [namespace with {release=stable}]/[all pods] : All Connections
Workloads not protected by network policies:
hello-world/workload-a[Deployment] is not protected on Egress
diff --git a/test_outputs/connlist/exposure_test_new_namespace_conn_and_entire_cluster_connlist_output.txt b/test_outputs/connlist/exposure_test_new_namespace_conn_and_entire_cluster_connlist_output.txt
index 777f0a14..44e20775 100644
--- a/test_outputs/connlist/exposure_test_new_namespace_conn_and_entire_cluster_connlist_output.txt
+++ b/test_outputs/connlist/exposure_test_new_namespace_conn_and_entire_cluster_connlist_output.txt
@@ -12,8 +12,8 @@ hello-world/workload-b[Deployment] => 0.0.0.0-255.255.255.255 : All Connection
hello-world/workload-b[Deployment] => entire-cluster : All Connections
Ingress Exposure:
+hello-world/workload-a[Deployment] <= [namespace with {foo.com/managed-state=managed}]/[all pods] : TCP 8050,8090
hello-world/workload-a[Deployment] <= entire-cluster : TCP 8050
-hello-world/workload-a[Deployment] <= namespace with {foo.com/managed-state=managed}/all pods : TCP 8050,8090
hello-world/workload-b[Deployment] <= 0.0.0.0-255.255.255.255 : All Connections
hello-world/workload-b[Deployment] <= entire-cluster : All Connections
diff --git a/test_outputs/connlist/exposure_test_pod_exposed_only_to_representative_peers_connlist_output.txt b/test_outputs/connlist/exposure_test_pod_exposed_only_to_representative_peers_connlist_output.txt
index dc6799b5..353d593d 100644
--- a/test_outputs/connlist/exposure_test_pod_exposed_only_to_representative_peers_connlist_output.txt
+++ b/test_outputs/connlist/exposure_test_pod_exposed_only_to_representative_peers_connlist_output.txt
@@ -5,12 +5,12 @@ Exposure Analysis Result:
Egress Exposure:
hello-world/workload-a[Deployment] => 0.0.0.0-255.255.255.255 : All Connections
hello-world/workload-a[Deployment] => entire-cluster : All Connections
-hello-world/workload-b[Deployment] => namespace with {foo.com/managed-state=managed}/all pods : TCP 8050
+hello-world/workload-b[Deployment] => [namespace with {foo.com/managed-state=managed}]/[all pods] : TCP 8050
Ingress Exposure:
hello-world/workload-a[Deployment] <= 0.0.0.0-255.255.255.255 : All Connections
hello-world/workload-a[Deployment] <= entire-cluster : All Connections
-hello-world/workload-b[Deployment] <= namespace with {foo.com/managed-state=managed}/all pods : TCP 8050
+hello-world/workload-b[Deployment] <= [namespace with {foo.com/managed-state=managed}]/[all pods] : TCP 8050
Workloads not protected by network policies:
hello-world/workload-a[Deployment] is not protected on Egress
diff --git a/test_outputs/connlist/exposure_test_same_unmatched_rule_in_ingress_egress_connlist_output.txt b/test_outputs/connlist/exposure_test_same_unmatched_rule_in_ingress_egress_connlist_output.txt
index 9d844f36..ce914035 100644
--- a/test_outputs/connlist/exposure_test_same_unmatched_rule_in_ingress_egress_connlist_output.txt
+++ b/test_outputs/connlist/exposure_test_same_unmatched_rule_in_ingress_egress_connlist_output.txt
@@ -1,7 +1,7 @@
Exposure Analysis Result:
Egress Exposure:
-hello-world/workload-a[Deployment] => namespace with {foo.com/managed-state=managed}/all pods : TCP 8050
+hello-world/workload-a[Deployment] => [namespace with {foo.com/managed-state=managed}]/[all pods] : TCP 8050
Ingress Exposure:
+hello-world/workload-a[Deployment] <= [namespace with {foo.com/managed-state=managed}]/[all pods] : TCP 8000,8090
hello-world/workload-a[Deployment] <= entire-cluster : TCP 8000
-hello-world/workload-a[Deployment] <= namespace with {foo.com/managed-state=managed}/all pods : TCP 8000,8090