From 4b8c40f63facb07ae384f3ab382030277980ac39 Mon Sep 17 00:00:00 2001 From: Tanya Date: Sun, 9 Jun 2024 17:57:30 +0300 Subject: [PATCH 01/10] Added nodes also for real peers which are not connected, in dot format (issue 362) --- pkg/netpol/connlist/connlist.go | 33 +++++++++--------- pkg/netpol/connlist/conns_formatter_dot.go | 40 ++++++++++++---------- 2 files changed, 38 insertions(+), 35 deletions(-) diff --git a/pkg/netpol/connlist/connlist.go b/pkg/netpol/connlist/connlist.go index 6c9a94c7..8ff969fd 100644 --- a/pkg/netpol/connlist/connlist.go +++ b/pkg/netpol/connlist/connlist.go @@ -47,6 +47,7 @@ type ConnlistAnalyzer struct { focusWorkload string outputFormat string muteErrsAndWarns bool + peersList []Peer } // The new interface @@ -240,7 +241,7 @@ func (ca *ConnlistAnalyzer) ConnlistFromK8sCluster(clientset *kubernetes.Clients // ConnectionsListToString returns a string of connections from list of Peer2PeerConnection objects in the required output format func (ca *ConnlistAnalyzer) ConnectionsListToString(conns []Peer2PeerConnection) (string, error) { - connsFormatter, err := getFormatter(ca.outputFormat) + connsFormatter, err := getFormatter(ca.outputFormat, ca.peersList) if err != nil { ca.errors = append(ca.errors, newResultFormattingError(err)) return "", err @@ -264,7 +265,7 @@ func ValidateOutputFormat(format string) error { } // returns the relevant formatter for the analyzer's outputFormat -func getFormatter(format string) (connsFormatter, error) { +func getFormatter(format string, peersList []Peer) (connsFormatter, error) { if err := ValidateOutputFormat(format); err != nil { return nil, err } @@ -274,7 +275,7 @@ func getFormatter(format string) (connsFormatter, error) { case output.TextFormat: return formatText{}, nil case output.DOTFormat: - return formatDOT{}, nil + return formatDOT{peersList: peersList}, nil case output.CSVFormat: return formatCSV{}, nil case output.MDFormat: @@ -368,15 +369,15 @@ func (ca *ConnlistAnalyzer) getConnectionsList(pe *eval.PolicyEngine, ia *ingres return nil, nil, err } // represent peerList as []connlist.Peer list to be returned - peers := make([]Peer, len(peerList)) + ca.peersList = make([]Peer, len(peerList)) for i, p := range peerList { - peers[i] = p + ca.peersList[i] = p } excludeIngressAnalysis := (ia == nil || ia.IsEmpty()) // if ca.focusWorkload is not empty, check if it exists in the peers before proceeding - existFocusWorkload, warningMsg := ca.existsFocusWorkload(peers, excludeIngressAnalysis) + existFocusWorkload, warningMsg := ca.existsFocusWorkload(excludeIngressAnalysis) if ca.focusWorkload != "" && !existFocusWorkload { ca.errors = append(ca.errors, newConnlistAnalyzerWarning(errors.New(warningMsg))) ca.logWarning(warningMsg) @@ -384,7 +385,7 @@ func (ca *ConnlistAnalyzer) getConnectionsList(pe *eval.PolicyEngine, ia *ingres } // compute connections between peers based on pe analysis of network policies - peersAllowedConns, err := ca.getConnectionsBetweenPeers(pe, peers) + peersAllowedConns, err := ca.getConnectionsBetweenPeers(pe) if err != nil { ca.errors = append(ca.errors, newResourceEvaluationError(err)) return nil, nil, err @@ -392,7 +393,7 @@ func (ca *ConnlistAnalyzer) getConnectionsList(pe *eval.PolicyEngine, ia *ingres connsRes = peersAllowedConns if excludeIngressAnalysis { - return connsRes, peers, nil + return connsRes, ca.peersList, nil } // analyze ingress connections - create connection objects for relevant ingress analyzer connections @@ -407,13 +408,13 @@ func (ca *ConnlistAnalyzer) getConnectionsList(pe *eval.PolicyEngine, ia *ingres ca.logWarning(netpolerrors.NoAllowedConnsWarning) } - return connsRes, peers, nil + return connsRes, ca.peersList, nil } // existsFocusWorkload checks if the provided focus workload is ingress-controller // or if it exists in the peers list from the parsed resources // if not returns a suitable warning message -func (ca *ConnlistAnalyzer) existsFocusWorkload(peers []Peer, excludeIngressAnalysis bool) (existFocusWorkload bool, warning string) { +func (ca *ConnlistAnalyzer) existsFocusWorkload(excludeIngressAnalysis bool) (existFocusWorkload bool, warning string) { if ca.focusWorkload == common.IngressPodName { if excludeIngressAnalysis { // if the ingress-analyzer is empty, // then no routes/k8s-ingress objects -> ingrss-controller pod will not be added @@ -423,7 +424,7 @@ func (ca *ConnlistAnalyzer) existsFocusWorkload(peers []Peer, excludeIngressAnal } // check if the focusworkload is in the peers - for _, peer := range peers { + for _, peer := range ca.peersList { if ca.focusWorkload == peer.Name() || ca.focusWorkload == getPeerNsNameFormat(peer) { return true, "" } @@ -432,12 +433,12 @@ func (ca *ConnlistAnalyzer) existsFocusWorkload(peers []Peer, excludeIngressAnal } // getConnectionsBetweenPeers returns connections list from PolicyEngine object -func (ca *ConnlistAnalyzer) getConnectionsBetweenPeers(pe *eval.PolicyEngine, peers []Peer) ([]Peer2PeerConnection, error) { +func (ca *ConnlistAnalyzer) getConnectionsBetweenPeers(pe *eval.PolicyEngine) ([]Peer2PeerConnection, error) { connsRes := make([]Peer2PeerConnection, 0) - for i := range peers { - srcPeer := peers[i] - for j := range peers { - dstPeer := peers[j] + for i := range ca.peersList { + srcPeer := ca.peersList[i] + for j := range ca.peersList { + dstPeer := ca.peersList[j] if !ca.includePairOfWorkloads(srcPeer, dstPeer) { continue } diff --git a/pkg/netpol/connlist/conns_formatter_dot.go b/pkg/netpol/connlist/conns_formatter_dot.go index 5f4a6e25..a8b1aa9c 100644 --- a/pkg/netpol/connlist/conns_formatter_dot.go +++ b/pkg/netpol/connlist/conns_formatter_dot.go @@ -22,6 +22,7 @@ const ( // formatDOT: implements the connsFormatter interface for dot output format type formatDOT struct { + peersList []Peer } // formats an edge line from a singleConnFields struct , to be used for dot graph @@ -46,6 +47,20 @@ func getPeerLine(peer Peer) (string, bool) { return fmt.Sprintf("\t%q [label=%q color=%q fontcolor=%q]", peer.String(), peerNameLabel, peerColor, peerColor), isExternalPeer } +func categorizeAndAddPeerLine(peer Peer, peersVisited map[string]bool, externalPeersLines []string, nsPeers map[string][]string) []string { + peerStr := peer.String() + if !peersVisited[peerStr] { + peersVisited[peerStr] = true + peerLine, isExternalPeer := getPeerLine(peer) + if isExternalPeer { // peer that does not belong to a cluster's namespace (i.e. ip/ ingress-controller) + externalPeersLines = append(externalPeersLines, peerLine) + } else { // add to Ns group + dotformatting.AddPeerToNsGroup(peer.Namespace(), peerLine, nsPeers) + } + } + return externalPeersLines +} + // returns a dot string form of connections from list of Peer2PeerConnection objects func (d formatDOT) writeOutput(conns []Peer2PeerConnection) (string, error) { nsPeers := make(map[string][]string) // map from namespace to its peers (grouping peers by namespaces) @@ -53,27 +68,14 @@ func (d formatDOT) writeOutput(conns []Peer2PeerConnection) (string, error) { edgeLines := make([]string, len(conns)) // list of edges lines peersVisited := make(map[string]bool, 0) // acts as a set for index := range conns { - srcStr, dstStr := conns[index].Src().String(), conns[index].Dst().String() edgeLines[index] = getEdgeLine(conns[index]) - if !peersVisited[srcStr] { - peersVisited[srcStr] = true - peerLine, isExternalPeer := getPeerLine(conns[index].Src()) - if isExternalPeer { // peer that does not belong to a cluster's namespace (i.e. ip/ ingress-controller) - externalPeersLines = append(externalPeersLines, peerLine) - } else { // add to Ns group - dotformatting.AddPeerToNsGroup(conns[index].Src().Namespace(), peerLine, nsPeers) - } - } - if !peersVisited[dstStr] { - peersVisited[dstStr] = true - peerLine, isExternalPeer := getPeerLine(conns[index].Dst()) - if isExternalPeer { - externalPeersLines = append(externalPeersLines, peerLine) - } else { - dotformatting.AddPeerToNsGroup(conns[index].Dst().Namespace(), peerLine, nsPeers) - } - } + externalPeersLines = categorizeAndAddPeerLine(conns[index].Src(), peersVisited, externalPeersLines, nsPeers) + externalPeersLines = categorizeAndAddPeerLine(conns[index].Dst(), peersVisited, externalPeersLines, nsPeers) } + for _, val := range d.peersList { + externalPeersLines = categorizeAndAddPeerLine(val, peersVisited, externalPeersLines, nsPeers) + } + // sort graph lines sort.Strings(edgeLines) sort.Strings(externalPeersLines) From 801c11561b4cdd95c83b41632b57786b25a32b05 Mon Sep 17 00:00:00 2001 From: Tanya Date: Sun, 16 Jun 2024 17:14:37 +0300 Subject: [PATCH 02/10] Not adding unreferenced IpBlock nodes to the dot graph. Changed some expected results --- pkg/netpol/connlist/conns_formatter_dot.go | 4 +++- ...ads_focus_workload_emailservice_connlist_output.dot | 10 ++++++++++ .../acs_security_frontend_demos_connlist_output.dot | 5 +++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/pkg/netpol/connlist/conns_formatter_dot.go b/pkg/netpol/connlist/conns_formatter_dot.go index a8b1aa9c..6d9e395c 100644 --- a/pkg/netpol/connlist/conns_formatter_dot.go +++ b/pkg/netpol/connlist/conns_formatter_dot.go @@ -73,7 +73,9 @@ func (d formatDOT) writeOutput(conns []Peer2PeerConnection) (string, error) { externalPeersLines = categorizeAndAddPeerLine(conns[index].Dst(), peersVisited, externalPeersLines, nsPeers) } for _, val := range d.peersList { - externalPeersLines = categorizeAndAddPeerLine(val, peersVisited, externalPeersLines, nsPeers) + if !val.IsPeerIPType() { + externalPeersLines = categorizeAndAddPeerLine(val, peersVisited, externalPeersLines, nsPeers) + } } // sort graph lines diff --git a/test_outputs/cli/onlineboutique_workloads_focus_workload_emailservice_connlist_output.dot b/test_outputs/cli/onlineboutique_workloads_focus_workload_emailservice_connlist_output.dot index a93f1036..59f90742 100644 --- a/test_outputs/cli/onlineboutique_workloads_focus_workload_emailservice_connlist_output.dot +++ b/test_outputs/cli/onlineboutique_workloads_focus_workload_emailservice_connlist_output.dot @@ -1,7 +1,17 @@ digraph { subgraph cluster_default { + "default/adservice[Deployment]" [label="adservice[Deployment]" color="blue" fontcolor="blue"] + "default/cartservice[Deployment]" [label="cartservice[Deployment]" color="blue" fontcolor="blue"] "default/checkoutservice[Deployment]" [label="checkoutservice[Deployment]" color="blue" fontcolor="blue"] + "default/currencyservice[Deployment]" [label="currencyservice[Deployment]" color="blue" fontcolor="blue"] "default/emailservice[Deployment]" [label="emailservice[Deployment]" color="blue" fontcolor="blue"] + "default/frontend[Deployment]" [label="frontend[Deployment]" color="blue" fontcolor="blue"] + "default/loadgenerator[Deployment]" [label="loadgenerator[Deployment]" color="blue" fontcolor="blue"] + "default/paymentservice[Deployment]" [label="paymentservice[Deployment]" color="blue" fontcolor="blue"] + "default/productcatalogservice[Deployment]" [label="productcatalogservice[Deployment]" color="blue" fontcolor="blue"] + "default/recommendationservice[Deployment]" [label="recommendationservice[Deployment]" color="blue" fontcolor="blue"] + "default/redis-cart[Deployment]" [label="redis-cart[Deployment]" color="blue" fontcolor="blue"] + "default/shippingservice[Deployment]" [label="shippingservice[Deployment]" color="blue" fontcolor="blue"] label="default" } "default/checkoutservice[Deployment]" -> "default/emailservice[Deployment]" [label="TCP 8080" color="gold2" fontcolor="darkgreen"] diff --git a/test_outputs/connlist/acs_security_frontend_demos_connlist_output.dot b/test_outputs/connlist/acs_security_frontend_demos_connlist_output.dot index 27f36df1..6b2002b2 100644 --- a/test_outputs/connlist/acs_security_frontend_demos_connlist_output.dot +++ b/test_outputs/connlist/acs_security_frontend_demos_connlist_output.dot @@ -1,2 +1,7 @@ digraph { + subgraph cluster_frontend { + "frontend/asset-cache[Deployment]" [label="asset-cache[Deployment]" color="blue" fontcolor="blue"] + "frontend/webapp[Deployment]" [label="webapp[Deployment]" color="blue" fontcolor="blue"] + label="frontend" + } } \ No newline at end of file From 411f14f19042698e0a477368ee81e48bbc388338 Mon Sep 17 00:00:00 2001 From: Adi Sosnovich <82078442+adisos@users.noreply.github.com> Date: Mon, 17 Jun 2024 08:43:39 +0300 Subject: [PATCH 03/10] update svg file (#366) Signed-off-by: adisos --- ...nd_netpol-analysis-example-minimal.dot.svg | 86 +++++++++---------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/test_outputs/diff/diff_between_netpol-diff-example-minimal_and_netpol-analysis-example-minimal.dot.svg b/test_outputs/diff/diff_between_netpol-diff-example-minimal_and_netpol-analysis-example-minimal.dot.svg index abeb61ff..93d53fee 100644 --- a/test_outputs/diff/diff_between_netpol-diff-example-minimal_and_netpol-analysis-example-minimal.dot.svg +++ b/test_outputs/diff/diff_between_netpol-diff-example-minimal_and_netpol-analysis-example-minimal.dot.svg @@ -1,22 +1,22 @@ - - - - + + + cluster_default - -default + +default cluster_legend - -Legend + +Legend @@ -27,97 +27,97 @@ default/frontend[Deployment] - -frontend[Deployment] + +frontend[Deployment] default/frontend[Deployment]->default/backend[Deployment] - - -TCP 9090,UDP 53 (ref1: TCP 9090) + + +TCP 9090,UDP 53 (dir1: TCP 9090) 0.0.0.0-255.255.255.255 - -0.0.0.0-255.255.255.255 + +0.0.0.0-255.255.255.255 default/frontend[Deployment]->0.0.0.0-255.255.255.255 - - -UDP 53 + + +UDP 53 0.0.0.0-255.255.255.255->default/backend[Deployment] - - -TCP 9090 + + +TCP 9090 0.0.0.0-255.255.255.255->default/frontend[Deployment] - - -TCP 8080 + + +TCP 8080 a->b - - -added connection + + +added connection c->d - - -removed connection + + +removed connection e->f - - -changed connection + + +changed connection g->h - - -unchanged connection + + +unchanged connection np - -new peer + +new peer lp - -lost peer + +lost peer pp - -persistent peer + +persistent peer From 5874cd2d4c92b565536f372c98d1a7d46a319b26 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jun 2024 06:43:57 +0000 Subject: [PATCH 04/10] Bump github/codeql-action from 3.25.7 to 3.25.10 (#367) --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 1d43335c..771b3826 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -45,7 +45,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@f079b8493333aace61c81488f8bd40919487bd9f + uses: github/codeql-action/init@23acc5c183826b7a8a97bce3cecc52db901f8251 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -56,7 +56,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@f079b8493333aace61c81488f8bd40919487bd9f + uses: github/codeql-action/autobuild@23acc5c183826b7a8a97bce3cecc52db901f8251 # ℹī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -70,4 +70,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f079b8493333aace61c81488f8bd40919487bd9f + uses: github/codeql-action/analyze@23acc5c183826b7a8a97bce3cecc52db901f8251 From 9b72af90ba38dfc7438b1f344219377d39f6272b Mon Sep 17 00:00:00 2001 From: Tanya Date: Tue, 18 Jun 2024 10:25:05 +0300 Subject: [PATCH 05/10] Adding unreferenced nodes to the dot graph only when no focusWorkload is given --- pkg/netpol/connlist/connlist.go | 6 +++--- pkg/netpol/connlist/conns_formatter_dot.go | 11 +++++++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/pkg/netpol/connlist/connlist.go b/pkg/netpol/connlist/connlist.go index 8ff969fd..9563a544 100644 --- a/pkg/netpol/connlist/connlist.go +++ b/pkg/netpol/connlist/connlist.go @@ -241,7 +241,7 @@ func (ca *ConnlistAnalyzer) ConnlistFromK8sCluster(clientset *kubernetes.Clients // ConnectionsListToString returns a string of connections from list of Peer2PeerConnection objects in the required output format func (ca *ConnlistAnalyzer) ConnectionsListToString(conns []Peer2PeerConnection) (string, error) { - connsFormatter, err := getFormatter(ca.outputFormat, ca.peersList) + connsFormatter, err := getFormatter(ca.outputFormat, ca.focusWorkload, ca.peersList) if err != nil { ca.errors = append(ca.errors, newResultFormattingError(err)) return "", err @@ -265,7 +265,7 @@ func ValidateOutputFormat(format string) error { } // returns the relevant formatter for the analyzer's outputFormat -func getFormatter(format string, peersList []Peer) (connsFormatter, error) { +func getFormatter(format string, focusWorkload string, peersList []Peer) (connsFormatter, error) { if err := ValidateOutputFormat(format); err != nil { return nil, err } @@ -275,7 +275,7 @@ func getFormatter(format string, peersList []Peer) (connsFormatter, error) { case output.TextFormat: return formatText{}, nil case output.DOTFormat: - return formatDOT{peersList: peersList}, nil + return formatDOT{focusWorkload: focusWorkload, peersList: peersList}, nil case output.CSVFormat: return formatCSV{}, nil case output.MDFormat: diff --git a/pkg/netpol/connlist/conns_formatter_dot.go b/pkg/netpol/connlist/conns_formatter_dot.go index 6d9e395c..6708826e 100644 --- a/pkg/netpol/connlist/conns_formatter_dot.go +++ b/pkg/netpol/connlist/conns_formatter_dot.go @@ -22,7 +22,8 @@ const ( // formatDOT: implements the connsFormatter interface for dot output format type formatDOT struct { - peersList []Peer + focusWorkload string + peersList []Peer } // formats an edge line from a singleConnFields struct , to be used for dot graph @@ -72,9 +73,11 @@ func (d formatDOT) writeOutput(conns []Peer2PeerConnection) (string, error) { externalPeersLines = categorizeAndAddPeerLine(conns[index].Src(), peersVisited, externalPeersLines, nsPeers) externalPeersLines = categorizeAndAddPeerLine(conns[index].Dst(), peersVisited, externalPeersLines, nsPeers) } - for _, val := range d.peersList { - if !val.IsPeerIPType() { - externalPeersLines = categorizeAndAddPeerLine(val, peersVisited, externalPeersLines, nsPeers) + if d.focusWorkload == "" { + for _, val := range d.peersList { + if !val.IsPeerIPType() { + externalPeersLines = categorizeAndAddPeerLine(val, peersVisited, externalPeersLines, nsPeers) + } } } From 0e55cf09c22ba57c48058381f85158fe850cb00f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jun 2024 08:14:15 +0000 Subject: [PATCH 06/10] Bump actions/checkout from 4.1.6 to 4.1.7 (#373) --- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/go-build.yml | 2 +- .github/workflows/golangci-lint.yml | 2 +- .github/workflows/make-release.yaml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 771b3826..8bd52da0 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -41,7 +41,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/go-build.yml b/.github/workflows/go-build.yml index 35c8dce7..36218b48 100644 --- a/.github/workflows/go-build.yml +++ b/.github/workflows/go-build.yml @@ -13,7 +13,7 @@ jobs: build-and-test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 - name: Set up Go uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index f7c6d5b6..a24183ac 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -11,7 +11,7 @@ jobs: name: golangci-lint runs-on: ubuntu-latest steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 - uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 with: go-version-file: ./go.mod diff --git a/.github/workflows/make-release.yaml b/.github/workflows/make-release.yaml index fae6d795..ddae929f 100644 --- a/.github/workflows/make-release.yaml +++ b/.github/workflows/make-release.yaml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out the repo - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 - name: Set up Go uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 From bcccefc9d1472bce864c68a840dcab64060cd672 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jun 2024 08:18:42 +0000 Subject: [PATCH 07/10] Bump github.com/spf13/cobra from 1.8.0 to 1.8.1 (#369) --- go.mod | 2 +- go.sum | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 7646e20c..4b595176 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/np-guard/models v0.3.2 github.com/openshift/api v0.0.0-20230502160752-c71432710382 - github.com/spf13/cobra v1.8.0 + github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 k8s.io/api v0.29.2 k8s.io/apimachinery v0.29.2 diff --git a/go.sum b/go.sum index ce8f600c..12909101 100644 --- a/go.sum +++ b/go.sum @@ -5,7 +5,7 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -113,8 +113,8 @@ github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncj github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= From 68742dfced663ec73fd9b0ac1df0fbbb23c1b403 Mon Sep 17 00:00:00 2001 From: Tanya Date: Tue, 18 Jun 2024 14:39:53 +0300 Subject: [PATCH 08/10] Fixed handling focusWorkload option in adding unreferenced nodes to the dot graph --- pkg/netpol/connlist/connlist.go | 33 +++++++++++-------- pkg/netpol/connlist/conns_formatter_dot.go | 11 +++---- ..._workload_emailservice_connlist_output.dot | 10 ------ 3 files changed, 24 insertions(+), 30 deletions(-) diff --git a/pkg/netpol/connlist/connlist.go b/pkg/netpol/connlist/connlist.go index 9563a544..0ab84677 100644 --- a/pkg/netpol/connlist/connlist.go +++ b/pkg/netpol/connlist/connlist.go @@ -241,7 +241,7 @@ func (ca *ConnlistAnalyzer) ConnlistFromK8sCluster(clientset *kubernetes.Clients // ConnectionsListToString returns a string of connections from list of Peer2PeerConnection objects in the required output format func (ca *ConnlistAnalyzer) ConnectionsListToString(conns []Peer2PeerConnection) (string, error) { - connsFormatter, err := getFormatter(ca.outputFormat, ca.focusWorkload, ca.peersList) + connsFormatter, err := getFormatter(ca.outputFormat, ca.peersList) if err != nil { ca.errors = append(ca.errors, newResultFormattingError(err)) return "", err @@ -265,7 +265,7 @@ func ValidateOutputFormat(format string) error { } // returns the relevant formatter for the analyzer's outputFormat -func getFormatter(format string, focusWorkload string, peersList []Peer) (connsFormatter, error) { +func getFormatter(format string, peersList []Peer) (connsFormatter, error) { if err := ValidateOutputFormat(format); err != nil { return nil, err } @@ -275,7 +275,7 @@ func getFormatter(format string, focusWorkload string, peersList []Peer) (connsF case output.TextFormat: return formatText{}, nil case output.DOTFormat: - return formatDOT{focusWorkload: focusWorkload, peersList: peersList}, nil + return formatDOT{peersList: peersList}, nil case output.CSVFormat: return formatCSV{}, nil case output.MDFormat: @@ -351,7 +351,7 @@ func getPeerNsNameFormat(peer eval.Peer) string { } func (ca *ConnlistAnalyzer) isPeerFocusWorkload(peer eval.Peer) bool { - return !peer.IsPeerIPType() && (peer.Name() == ca.focusWorkload || getPeerNsNameFormat(peer) == ca.focusWorkload) + return peer.Name() == ca.focusWorkload || getPeerNsNameFormat(peer) == ca.focusWorkload } // getConnectionsList returns connections list from PolicyEngine and ingressAnalyzer objects @@ -369,9 +369,16 @@ func (ca *ConnlistAnalyzer) getConnectionsList(pe *eval.PolicyEngine, ia *ingres return nil, nil, err } // represent peerList as []connlist.Peer list to be returned - ca.peersList = make([]Peer, len(peerList)) + peers := make([]Peer, len(peerList)) + ca.peersList = make([]Peer, 0, len(peerList)) + lastInd := 0 for i, p := range peerList { - ca.peersList[i] = p + peers[i] = p + if ca.focusWorkload == "" || ca.isPeerFocusWorkload(p) { + ca.peersList = ca.peersList[:lastInd+1] + ca.peersList[lastInd] = p + lastInd++ + } } excludeIngressAnalysis := (ia == nil || ia.IsEmpty()) @@ -385,7 +392,7 @@ func (ca *ConnlistAnalyzer) getConnectionsList(pe *eval.PolicyEngine, ia *ingres } // compute connections between peers based on pe analysis of network policies - peersAllowedConns, err := ca.getConnectionsBetweenPeers(pe) + peersAllowedConns, err := ca.getConnectionsBetweenPeers(pe, peers) if err != nil { ca.errors = append(ca.errors, newResourceEvaluationError(err)) return nil, nil, err @@ -425,7 +432,7 @@ func (ca *ConnlistAnalyzer) existsFocusWorkload(excludeIngressAnalysis bool) (ex // check if the focusworkload is in the peers for _, peer := range ca.peersList { - if ca.focusWorkload == peer.Name() || ca.focusWorkload == getPeerNsNameFormat(peer) { + if ca.isPeerFocusWorkload(peer) { return true, "" } } @@ -433,12 +440,12 @@ func (ca *ConnlistAnalyzer) existsFocusWorkload(excludeIngressAnalysis bool) (ex } // getConnectionsBetweenPeers returns connections list from PolicyEngine object -func (ca *ConnlistAnalyzer) getConnectionsBetweenPeers(pe *eval.PolicyEngine) ([]Peer2PeerConnection, error) { +func (ca *ConnlistAnalyzer) getConnectionsBetweenPeers(pe *eval.PolicyEngine, peers []Peer) ([]Peer2PeerConnection, error) { connsRes := make([]Peer2PeerConnection, 0) - for i := range ca.peersList { - srcPeer := ca.peersList[i] - for j := range ca.peersList { - dstPeer := ca.peersList[j] + for i := range peers { + srcPeer := peers[i] + for j := range peers { + dstPeer := peers[j] if !ca.includePairOfWorkloads(srcPeer, dstPeer) { continue } diff --git a/pkg/netpol/connlist/conns_formatter_dot.go b/pkg/netpol/connlist/conns_formatter_dot.go index 6708826e..6d9e395c 100644 --- a/pkg/netpol/connlist/conns_formatter_dot.go +++ b/pkg/netpol/connlist/conns_formatter_dot.go @@ -22,8 +22,7 @@ const ( // formatDOT: implements the connsFormatter interface for dot output format type formatDOT struct { - focusWorkload string - peersList []Peer + peersList []Peer } // formats an edge line from a singleConnFields struct , to be used for dot graph @@ -73,11 +72,9 @@ func (d formatDOT) writeOutput(conns []Peer2PeerConnection) (string, error) { externalPeersLines = categorizeAndAddPeerLine(conns[index].Src(), peersVisited, externalPeersLines, nsPeers) externalPeersLines = categorizeAndAddPeerLine(conns[index].Dst(), peersVisited, externalPeersLines, nsPeers) } - if d.focusWorkload == "" { - for _, val := range d.peersList { - if !val.IsPeerIPType() { - externalPeersLines = categorizeAndAddPeerLine(val, peersVisited, externalPeersLines, nsPeers) - } + for _, val := range d.peersList { + if !val.IsPeerIPType() { + externalPeersLines = categorizeAndAddPeerLine(val, peersVisited, externalPeersLines, nsPeers) } } diff --git a/test_outputs/cli/onlineboutique_workloads_focus_workload_emailservice_connlist_output.dot b/test_outputs/cli/onlineboutique_workloads_focus_workload_emailservice_connlist_output.dot index 59f90742..a93f1036 100644 --- a/test_outputs/cli/onlineboutique_workloads_focus_workload_emailservice_connlist_output.dot +++ b/test_outputs/cli/onlineboutique_workloads_focus_workload_emailservice_connlist_output.dot @@ -1,17 +1,7 @@ digraph { subgraph cluster_default { - "default/adservice[Deployment]" [label="adservice[Deployment]" color="blue" fontcolor="blue"] - "default/cartservice[Deployment]" [label="cartservice[Deployment]" color="blue" fontcolor="blue"] "default/checkoutservice[Deployment]" [label="checkoutservice[Deployment]" color="blue" fontcolor="blue"] - "default/currencyservice[Deployment]" [label="currencyservice[Deployment]" color="blue" fontcolor="blue"] "default/emailservice[Deployment]" [label="emailservice[Deployment]" color="blue" fontcolor="blue"] - "default/frontend[Deployment]" [label="frontend[Deployment]" color="blue" fontcolor="blue"] - "default/loadgenerator[Deployment]" [label="loadgenerator[Deployment]" color="blue" fontcolor="blue"] - "default/paymentservice[Deployment]" [label="paymentservice[Deployment]" color="blue" fontcolor="blue"] - "default/productcatalogservice[Deployment]" [label="productcatalogservice[Deployment]" color="blue" fontcolor="blue"] - "default/recommendationservice[Deployment]" [label="recommendationservice[Deployment]" color="blue" fontcolor="blue"] - "default/redis-cart[Deployment]" [label="redis-cart[Deployment]" color="blue" fontcolor="blue"] - "default/shippingservice[Deployment]" [label="shippingservice[Deployment]" color="blue" fontcolor="blue"] label="default" } "default/checkoutservice[Deployment]" -> "default/emailservice[Deployment]" [label="TCP 8080" color="gold2" fontcolor="darkgreen"] From e5a5b799bf1dd4ad30aaadd160c9733c3a700a9d Mon Sep 17 00:00:00 2001 From: Tanya Date: Tue, 18 Jun 2024 15:55:12 +0300 Subject: [PATCH 09/10] adding documentation --- pkg/netpol/connlist/connlist.go | 6 +++--- pkg/netpol/connlist/conns_formatter_dot.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/netpol/connlist/connlist.go b/pkg/netpol/connlist/connlist.go index 0ab84677..35311c93 100644 --- a/pkg/netpol/connlist/connlist.go +++ b/pkg/netpol/connlist/connlist.go @@ -47,7 +47,7 @@ type ConnlistAnalyzer struct { focusWorkload string outputFormat string muteErrsAndWarns bool - peersList []Peer + peersList []Peer // internally used peersList used in dot formatting; in case of focusWorkload option contains only relevant peers } // The new interface @@ -400,7 +400,7 @@ func (ca *ConnlistAnalyzer) getConnectionsList(pe *eval.PolicyEngine, ia *ingres connsRes = peersAllowedConns if excludeIngressAnalysis { - return connsRes, ca.peersList, nil + return connsRes, peers, nil } // analyze ingress connections - create connection objects for relevant ingress analyzer connections @@ -415,7 +415,7 @@ func (ca *ConnlistAnalyzer) getConnectionsList(pe *eval.PolicyEngine, ia *ingres ca.logWarning(netpolerrors.NoAllowedConnsWarning) } - return connsRes, ca.peersList, nil + return connsRes, peers, nil } // existsFocusWorkload checks if the provided focus workload is ingress-controller diff --git a/pkg/netpol/connlist/conns_formatter_dot.go b/pkg/netpol/connlist/conns_formatter_dot.go index 6d9e395c..e4f3a290 100644 --- a/pkg/netpol/connlist/conns_formatter_dot.go +++ b/pkg/netpol/connlist/conns_formatter_dot.go @@ -22,7 +22,7 @@ const ( // formatDOT: implements the connsFormatter interface for dot output format type formatDOT struct { - peersList []Peer + peersList []Peer // internally used peersList; in case of focusWorkload option contains only relevant peers } // formats an edge line from a singleConnFields struct , to be used for dot graph From 0aeb10cab882dfae06cab23055c2b7bb93640747 Mon Sep 17 00:00:00 2001 From: Tanya Date: Tue, 18 Jun 2024 16:23:27 +0300 Subject: [PATCH 10/10] Update pkg/netpol/connlist/connlist.go Co-authored-by: Adi Sosnovich <82078442+adisos@users.noreply.github.com> --- pkg/netpol/connlist/connlist.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pkg/netpol/connlist/connlist.go b/pkg/netpol/connlist/connlist.go index 35311c93..a1148082 100644 --- a/pkg/netpol/connlist/connlist.go +++ b/pkg/netpol/connlist/connlist.go @@ -371,13 +371,10 @@ func (ca *ConnlistAnalyzer) getConnectionsList(pe *eval.PolicyEngine, ia *ingres // represent peerList as []connlist.Peer list to be returned peers := make([]Peer, len(peerList)) ca.peersList = make([]Peer, 0, len(peerList)) - lastInd := 0 for i, p := range peerList { peers[i] = p if ca.focusWorkload == "" || ca.isPeerFocusWorkload(p) { - ca.peersList = ca.peersList[:lastInd+1] - ca.peersList[lastInd] = p - lastInd++ + ca.peersList = append(ca.peersList, p) } }