Skip to content
Merged
Changes from 1 commit
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
087b1c1
npm to cilium validator script
rayaisaiah Jan 28, 2025
eb5f727
added a check for services with target ports
rayaisaiah Feb 3, 2025
69a71be
Merge branch 'master' into isaiahraya/npm-cilium-migration-script
rayaisaiah Feb 3, 2025
843741b
update for lint errors with repeat imports and using slice of pointer…
rayaisaiah Feb 3, 2025
49fa49a
made a function to reuse for Ingress and egress ports
rayaisaiah Feb 4, 2025
079e7c0
added some unit tests except for service check and made print stateme…
rayaisaiah Feb 4, 2025
07690ae
updated engress policy check with egress allow all policy and added a…
rayaisaiah Feb 4, 2025
5b5d2a7
changed file path
rayaisaiah Feb 4, 2025
d6ec15e
added namedport checks and added port to ingress check
rayaisaiah Feb 4, 2025
dd25cc8
responded to service comments
rayaisaiah Feb 5, 2025
afa4e9d
added a check for ingress deny all and updated port check function to…
rayaisaiah Feb 5, 2025
7625ef5
updated to return lists and use pointers but still broken for services
rayaisaiah Feb 5, 2025
b9231e2
added pointers to service check functions
rayaisaiah Feb 5, 2025
2f7d338
fixed pointer logic and added unit tests for the checks except service
rayaisaiah Feb 6, 2025
cd15f4a
Merge branch 'master' into isaiahraya/npm-cilium-migration-script
rayaisaiah Feb 6, 2025
c8bd575
fixed all linter errors
rayaisaiah Feb 6, 2025
f2cba91
updated difference function with comment to use a set
rayaisaiah Feb 6, 2025
1b64afb
fixed linter problems induced by previous commit
rayaisaiah Feb 6, 2025
a2d413f
added complete UTs for GetEndportNetworkPolicies, GetCIDRNetworkPolic…
rayaisaiah Feb 6, 2025
c329191
added baseline service tests and updated logic for unsafe and noselec…
rayaisaiah Feb 6, 2025
f79188b
added more service uts for nodeport and organized scenarios
rayaisaiah Feb 7, 2025
593f29e
updated migration check to be less than 200 characters per line (lint…
rayaisaiah Feb 7, 2025
840feab
updated getExternalTrafficPolicyClusterServices to be less than 200 c…
rayaisaiah Feb 7, 2025
894da23
removed unused parameter and added edge case scenarios to UTs
rayaisaiah Feb 7, 2025
bbe17e6
simplified logic
rayaisaiah Feb 7, 2025
3ee1deb
updated port detection when policy just has a protocol and to flag al…
rayaisaiah Feb 7, 2025
c4676cf
resolved nit: pointer to slice is also a pointer to pointer comment
rayaisaiah Feb 7, 2025
c72b33c
responded to comments return false when either port or target port is…
rayaisaiah Feb 7, 2025
51e0d16
added readme, go mod, go sum, and comments saying why target port wil…
rayaisaiah Feb 7, 2025
ede206d
updated readme
rayaisaiah Feb 7, 2025
5805952
updated functions using pointers for arrays
rayaisaiah Feb 7, 2025
1689071
nit changes
rayaisaiah Feb 7, 2025
f35989c
updated with match expressions edgecase
rayaisaiah Feb 7, 2025
160fd47
added uts where target port matches to protocol and port is 0
rayaisaiah Feb 7, 2025
979a8b3
added Scenarios where there are LoadBalancer or NodePort services wit…
rayaisaiah Feb 8, 2025
eac2c66
add check for ip no port policies on loadbalancer and fixes label and…
rayaisaiah Feb 10, 2025
4312ba8
updated table to use tablewriter
rayaisaiah Feb 10, 2025
c1b4d4a
updated to parse cidr to check for load balancer ip
rayaisaiah Feb 10, 2025
c74511e
removed no selector services from getUnsafeExternalTrafficPolicyClust…
rayaisaiah Feb 11, 2025
dc2af8d
removed noselector services array
rayaisaiah Feb 11, 2025
6873113
Merge branch 'master' into isaiahraya/npm-cilium-migration-script
rayaisaiah Feb 11, 2025
246965d
added service selectors to the appended list instead to simplify logic
rayaisaiah Feb 11, 2025
dabc25e
Revert "added service selectors to the appended list instead to simpl…
rayaisaiah Feb 11, 2025
809fc90
moved checkPolicyMatchServiceLabels check to the top since every bloc…
rayaisaiah Feb 11, 2025
ee59a88
updated the load balancer health probe ip logic
rayaisaiah Feb 11, 2025
4fe7634
added unit tests and logic if nodeport ensure there is no from rules
rayaisaiah Feb 12, 2025
62df911
Merge branch 'master' into isaiahraya/npm-cilium-migration-script
rayaisaiah Feb 12, 2025
1140a70
removed health probe ip check for loadbalancer services
rayaisaiah Feb 13, 2025
118f98a
Merge branch 'master' into isaiahraya/npm-cilium-migration-script
rayaisaiah Feb 13, 2025
cd0c2d5
added named port check
rayaisaiah Feb 13, 2025
6cb46db
nit comment
rayaisaiah Feb 13, 2025
2c92609
Merge branch 'master' into isaiahraya/npm-cilium-migration-script
rayaisaiah Feb 18, 2025
e08e97e
reduced output verbosity
rayaisaiah Feb 18, 2025
012c963
print total number of policies per namespace
rayaisaiah Feb 18, 2025
f0f8aa7
added service and pod count and created a table
rayaisaiah Feb 19, 2025
0d80410
improved formatting
rayaisaiah Feb 19, 2025
b203bde
typo
rayaisaiah Feb 19, 2025
ce049e0
Merge branch 'master' into isaiahraya/npm-cilium-migration-script
rayaisaiah Feb 20, 2025
9b68cc0
Merge branch 'master' into isaiahraya/npm-cilium-migration-script
rayaisaiah Feb 20, 2025
c889e1d
Merge branch 'master' into isaiahraya/npm-cilium-migration-script
rayaisaiah Feb 20, 2025
5e9ae22
updated table format and started to add npm telemetry
rayaisaiah Feb 22, 2025
3c60e69
Merge branch 'master' into isaiahraya/npm-cilium-migration-script
rayaisaiah Feb 22, 2025
9f60f68
updated verbose flag name and reorganized and removed unused functions
rayaisaiah Feb 24, 2025
73ff864
updated readme
rayaisaiah Feb 24, 2025
ed71c9a
fixed table formatting
rayaisaiah Feb 24, 2025
6cec80a
added ai id and formated tables to be printed after telemetry is sent
rayaisaiah Feb 25, 2025
70556da
ran tidy
rayaisaiah Feb 25, 2025
9de5cb8
reduced noise from telemetry runs
rayaisaiah Feb 25, 2025
c244424
Merge branch 'master' into isaiahraya/npm-cilium-migration-script
rayaisaiah Feb 25, 2025
0295b63
Merge branch 'master' into isaiahraya/npm-cilium-migration-script
rayaisaiah Feb 25, 2025
3ee497b
added a const and prefix to metrics
rayaisaiah Feb 26, 2025
a11ffd9
Merge branch 'isaiahraya/npm-cilium-migration-script' of https://gith…
rayaisaiah Feb 26, 2025
2bb7a07
Merge branch 'master' into isaiahraya/npm-cilium-migration-script
rayaisaiah Feb 26, 2025
92b366e
updated imageVersion per comment
rayaisaiah Feb 26, 2025
01a7b51
Merge branch 'isaiahraya/npm-cilium-migration-script' of https://gith…
rayaisaiah Feb 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
397 changes: 397 additions & 0 deletions tools/azure-npm-to-cilium-validator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,397 @@
package main

import (
"context"
"flag"
"fmt"
"log"
"strings"

corev1 "k8s.io/api/core/v1"

Check failure on line 10 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.22.x, ubuntu-latest)

dupImport: package is imported 2 times under different aliases on lines 10 and 11 (gocritic)

Check failure on line 10 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.23.x, ubuntu-latest)

dupImport: package is imported 2 times under different aliases on lines 10 and 11 (gocritic)

Check failure on line 10 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.22.x, windows-latest)

dupImport: package is imported 2 times under different aliases on lines 10 and 11 (gocritic)

Check failure on line 10 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.23.x, windows-latest)

dupImport: package is imported 2 times under different aliases on lines 10 and 11 (gocritic)
v1 "k8s.io/api/core/v1"

Check failure on line 11 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.22.x, ubuntu-latest)

dupImport: package is imported 2 times under different aliases on lines 10 and 11 (gocritic)

Check failure on line 11 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.23.x, ubuntu-latest)

dupImport: package is imported 2 times under different aliases on lines 10 and 11 (gocritic)

Check failure on line 11 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.22.x, windows-latest)

dupImport: package is imported 2 times under different aliases on lines 10 and 11 (gocritic)

Check failure on line 11 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.23.x, windows-latest)

dupImport: package is imported 2 times under different aliases on lines 10 and 11 (gocritic)
networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
)

// Use this tool to validate if your cluster is ready to migrate from Azure Network Policy Manager (NPM) to Cilium.
// go run azure-npm-to-cilium-validator.go --kubeconfig ~/.kube/config

func main() {
// Parse the kubeconfig flag
kubeconfig := flag.String("kubeconfig", "~/.kube/config", "absolute path to the kubeconfig file")
flag.Parse()

// Build the Kubernetes client config
config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
if err != nil {
log.Fatalf("Error building kubeconfig: %v", err)
}

// Create a Kubernetes client
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
log.Fatalf("Error creating Kubernetes client: %v", err)
}

// Get namespaces
namespaces, err := clientset.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{})
if err != nil {
log.Fatalf("Error getting namespaces: %v\n", err)
}

// Store network policies and services in maps
policiesByNamespace := make(map[string][]networkingv1.NetworkPolicy)
servicesByNamespace := make(map[string][]corev1.Service)

// Iterate over namespaces and store policies/services
for _, ns := range namespaces.Items {

Check failure on line 49 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.22.x, ubuntu-latest)

rangeValCopy: each iteration copies 328 bytes (consider pointers or indexing) (gocritic)

Check failure on line 49 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.23.x, ubuntu-latest)

rangeValCopy: each iteration copies 328 bytes (consider pointers or indexing) (gocritic)

Check failure on line 49 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.22.x, windows-latest)

rangeValCopy: each iteration copies 328 bytes (consider pointers or indexing) (gocritic)

Check failure on line 49 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.23.x, windows-latest)

rangeValCopy: each iteration copies 328 bytes (consider pointers or indexing) (gocritic)
fmt.Printf("Writing policies and services for namespace %s...\n", ns.Name)

// Get network policies
networkPolicies, err := clientset.NetworkingV1().NetworkPolicies(ns.Name).List(context.TODO(), metav1.ListOptions{})
if err != nil {
fmt.Printf("Error getting network policies in namespace %s: %v\n", ns.Name, err)
continue
}
policiesByNamespace[ns.Name] = networkPolicies.Items

// Get services
services, err := clientset.CoreV1().Services(ns.Name).List(context.TODO(), metav1.ListOptions{})
if err != nil {
fmt.Printf("Error getting services in namespace %s: %v\n", ns.Name, err)
continue
}
servicesByNamespace[ns.Name] = services.Items
}

fmt.Println("Migration Summary:")
fmt.Println("+------------------------------+-------------------------------+")
fmt.Printf("%-30s | %-30s \n", "Breaking Change", "No Impact / Safe to Migrate")
fmt.Println("+------------------------------+-------------------------------+")

// Check the endports of the network policies
foundEnportNetworkPolicy := checkEndportNetworkPolicies(policiesByNamespace)

fmt.Println("+------------------------------+-------------------------------+")

// Check the cidr of the network policies
foundCIDRNetworkPolicy := checkCIDRNetworkPolicies(policiesByNamespace)

fmt.Println("+------------------------------+-------------------------------+")

// Check the egress of the network policies
foundEgressPolicy := checkForEgressPolicies(policiesByNamespace)

fmt.Println("+------------------------------+-------------------------------+")

// Check services that have externalTrafficPolicy!=Local
foundServiceDispruption := checkExternalTrafficPolicyServices(namespaces, servicesByNamespace, policiesByNamespace)

fmt.Println("+------------------------------+-------------------------------+")
if foundEnportNetworkPolicy || foundCIDRNetworkPolicy || foundEgressPolicy || foundServiceDispruption {
fmt.Println("\033[31m✘ Review above issues before migration.\033[0m")
fmt.Println("Please see \033[32maka.ms/azurenpmtocilium\033[0m for instructions on how to evaluate/assess the above warnings marked by ❌.")
fmt.Println("NOTE: rerun this script if any modifications (create/update/delete) are made to services or policies.")
} else {
fmt.Println("\033[32m✔ Safe to migrate this cluster.\033[0m")
fmt.Println("For more details please see \033[32maka.ms/azurenpmtocilium\033[0m.")
}
}

func checkEndportNetworkPolicies(policiesByNamespace map[string][]networkingv1.NetworkPolicy) bool {
networkPolicyWithEndport := false
for namespace, policies := range policiesByNamespace {
for _, policy := range policies {

Check failure on line 106 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.22.x, ubuntu-latest)

rangeValCopy: each iteration copies 368 bytes (consider pointers or indexing) (gocritic)

Check failure on line 106 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.23.x, ubuntu-latest)

rangeValCopy: each iteration copies 368 bytes (consider pointers or indexing) (gocritic)

Check failure on line 106 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.22.x, windows-latest)

rangeValCopy: each iteration copies 368 bytes (consider pointers or indexing) (gocritic)

Check failure on line 106 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.23.x, windows-latest)

rangeValCopy: each iteration copies 368 bytes (consider pointers or indexing) (gocritic)
foundEndPort := false
for _, egress := range policy.Spec.Egress {
for _, port := range egress.Ports {
if port.EndPort != nil {
foundEndPort = true
if !networkPolicyWithEndport {
fmt.Printf("%-30s | %-30s \n", "NetworkPolicy with endPort", "❌")
fmt.Println("Policies affected:")
networkPolicyWithEndport = true
}
fmt.Printf("❌ Found NetworkPolicy: \033[31m%s\033[0m with endPort field in namespace: \033[31m%s\033[0m\n", policy.Name, namespace)
// Exit egress.port loop
break
}
}
if foundEndPort {
// Exit egress loop
break
}
}
}
}
// Print no impact if no network policy has endport
if !networkPolicyWithEndport {
fmt.Printf("%-30s | %-30s \n", "NetworkPolicy with endPort", "✅")
return false
}
return true
}

func checkCIDRNetworkPolicies(policiesByNamespace map[string][]networkingv1.NetworkPolicy) bool {
networkPolicyWithCIDR := false
for namespace, policies := range policiesByNamespace {
for _, policy := range policies {

Check failure on line 140 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.22.x, ubuntu-latest)

rangeValCopy: each iteration copies 368 bytes (consider pointers or indexing) (gocritic)

Check failure on line 140 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.23.x, ubuntu-latest)

rangeValCopy: each iteration copies 368 bytes (consider pointers or indexing) (gocritic)

Check failure on line 140 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.22.x, windows-latest)

rangeValCopy: each iteration copies 368 bytes (consider pointers or indexing) (gocritic)

Check failure on line 140 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.23.x, windows-latest)

rangeValCopy: each iteration copies 368 bytes (consider pointers or indexing) (gocritic)
foundCIDRIngress := false
foundCIDREgress := false
// Check the ingress field for cidr
for _, ingress := range policy.Spec.Ingress {
for _, from := range ingress.From {
if from.IPBlock != nil {
if from.IPBlock.CIDR != "" {
foundCIDRIngress = true
// Print the network policy if it has an ingress cidr
if !networkPolicyWithCIDR {
fmt.Printf("%-30s | %-30s \n", "NetworkPolicy with cidr", "❌")
fmt.Println("Policies affected:")
networkPolicyWithCIDR = true
}
fmt.Printf("❌ Found NetworkPolicy: \033[31m%s\033[0m with ingress cidr field in namespace: \033[31m%s\033[0m\n", policy.Name, namespace)

// Exit ingress.from.ipBlock loop
break
}
}
}
if foundCIDRIngress {
// Exit ingress loop
break
}
}
// Check the egress field for cidr
for _, egress := range policy.Spec.Egress {
for _, to := range egress.To {
if to.IPBlock != nil {
if to.IPBlock.CIDR != "" {
foundCIDREgress = true
// Print the network policy if it has an egress cidr
if !networkPolicyWithCIDR {
fmt.Printf("%-30s | %-30s \n", "NetworkPolicy with cidr", "❌")
fmt.Println("Policies affected:")
networkPolicyWithCIDR = true
}
fmt.Printf("❌ Found NetworkPolicy: \033[31m%s\033[0m with egress cidr field in namespace: \033[31m%s\033[0m\n", policy.Name, namespace)

// Exit egress.to.ipBlock loop
break
}
}
}
if foundCIDREgress {
// Exit egress loop
break
}
}
}
}
// Print no impact if no network policy has cidr
if !networkPolicyWithCIDR {
fmt.Printf("%-30s | %-30s \n", "NetworkPolicy with cidr", "✅")
return false
}
return true
}

func checkForEgressPolicies(policiesByNamespace map[string][]networkingv1.NetworkPolicy) bool {
networkPolicyWithEgress := false
for namespace, policies := range policiesByNamespace {
for _, policy := range policies {

Check failure on line 204 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.22.x, ubuntu-latest)

rangeValCopy: each iteration copies 368 bytes (consider pointers or indexing) (gocritic)

Check failure on line 204 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.23.x, ubuntu-latest)

rangeValCopy: each iteration copies 368 bytes (consider pointers or indexing) (gocritic)

Check failure on line 204 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.22.x, windows-latest)

rangeValCopy: each iteration copies 368 bytes (consider pointers or indexing) (gocritic)

Check failure on line 204 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.23.x, windows-latest)

rangeValCopy: each iteration copies 368 bytes (consider pointers or indexing) (gocritic)
for _, egress := range policy.Spec.Egress {
// If the policy has a egress field thats not an egress allow all flag it
if len(egress.To) > 0 || len(egress.Ports) > 0 {
if !networkPolicyWithEgress {
fmt.Printf("%-30s | %-30s \n", "NetworkPolicy with egress", "❌")
fmt.Printf("%-30s | %-30s \n", "(Not allow all egress)", "")
fmt.Println("Policies affected:")
networkPolicyWithEgress = true
}
fmt.Printf("❌ Found NetworkPolicy: \033[31m%s\033[0m with egress field (non-allow all) in namespace: \033[31m%s\033[0m\n", policy.Name, namespace)

// Exit egress loop
break
}
}
}
}
if !networkPolicyWithEgress {
fmt.Printf("%-30s | %-30s \n", "NetworkPolicy with egress", "✅")
return false
}
return true
}

func checkExternalTrafficPolicyServices(namespaces *corev1.NamespaceList, servicesByNamespace map[string][]corev1.Service, policiesByNamespace map[string][]networkingv1.NetworkPolicy) bool {
var servicesAtRisk, noSelectorServices, safeServices []string

for _, namespace := range namespaces.Items {

Check failure on line 232 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.22.x, ubuntu-latest)

rangeValCopy: each iteration copies 328 bytes (consider pointers or indexing) (gocritic)

Check failure on line 232 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.23.x, ubuntu-latest)

rangeValCopy: each iteration copies 328 bytes (consider pointers or indexing) (gocritic)

Check failure on line 232 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.22.x, windows-latest)

rangeValCopy: each iteration copies 328 bytes (consider pointers or indexing) (gocritic)

Check failure on line 232 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.23.x, windows-latest)

rangeValCopy: each iteration copies 328 bytes (consider pointers or indexing) (gocritic)
// Check if are there ingress policies in the namespace if not skip
if !hasIngressPolicies(policiesByNamespace[namespace.Name]) {
continue
}
serviceListAtNamespace := servicesByNamespace[namespace.Name]

// Check if are there services with externalTrafficPolicy=Cluster (applicable if Type=NodePort or Type=LoadBalancer)
for _, service := range serviceListAtNamespace {

Check failure on line 240 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.22.x, ubuntu-latest)

rangeValCopy: each iteration copies 592 bytes (consider pointers or indexing) (gocritic)

Check failure on line 240 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.23.x, ubuntu-latest)

rangeValCopy: each iteration copies 592 bytes (consider pointers or indexing) (gocritic)

Check failure on line 240 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.22.x, windows-latest)

rangeValCopy: each iteration copies 592 bytes (consider pointers or indexing) (gocritic)

Check failure on line 240 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.23.x, windows-latest)

rangeValCopy: each iteration copies 592 bytes (consider pointers or indexing) (gocritic)
if service.Spec.Type == v1.ServiceTypeLoadBalancer || service.Spec.Type == v1.ServiceTypeNodePort {
servicePorts := []string{}
// get the Port and Protocol of the service
for _, port := range service.Spec.Ports {
servicePorts = append(servicePorts, fmt.Sprintf("%d/%s", port.Port, port.Protocol))
}
externalTrafficPolicy := service.Spec.ExternalTrafficPolicy
// If the service has externalTrafficPolicy is set to "Cluster" add it to the servicesAtRisk list (ExternalTrafficPolicy: "" defaults to Cluster)
if externalTrafficPolicy != v1.ServiceExternalTrafficPolicyTypeLocal {
// Any service with externalTrafficPolicy=Cluster is at risk so need to elimate any services that are incorrectly flagged
servicesAtRisk = append(servicesAtRisk, fmt.Sprintf("%s/%s", namespace.Name, service.Name))
// If the service has no selector add it to the noSelectorServices list
if service.Spec.Selector == nil {
noSelectorServices = append(noSelectorServices, fmt.Sprintf("%s/%s", namespace.Name, service.Name))
} else {
// Check if are there services with selector that match the network policy
safeServices = checkServiceRisk(service, namespace.Name, servicePorts, policiesByNamespace[namespace.Name], safeServices)
}
}
}
}
}

// Get the services that are at risk but not in the safe services or no selector services lists
unsafeServices := difference(servicesAtRisk, safeServices, noSelectorServices)

// If there is no unsafe services then migration is safe for services with extranalTrafficPolicy=Cluster
if len(unsafeServices) == 0 {
fmt.Printf("%-30s | %-30s \n", "Disruption for some", "✅")
fmt.Printf("%-30s | %-30s \n", "Services with", "")
fmt.Printf("%-30s | %-30s \n", "externalTrafficPolicy=Cluster", "")
return false
} else {
fmt.Printf("%-30s | %-30s \n", "Disruption for some", "❌")
fmt.Printf("%-30s | %-30s \n", "Services with", "")
fmt.Printf("%-30s | %-30s \n", "externalTrafficPolicy=Cluster", "")
fmt.Println("Services affected:")
// If there are any no selector services or unsafe services then print them as they could be impacted by migration
if len(noSelectorServices) > 0 {
for _, service := range noSelectorServices {
serviceName := strings.Split(service, "/")[1]
serviceNamespace := strings.Split(service, "/")[0]
fmt.Printf("❌ Found Service: \033[31m%s\033[0m without selectors in namespace: \033[31m%s\033[0m\n", serviceName, serviceNamespace)
}
}
if len(unsafeServices) > 0 {
for _, service := range unsafeServices {
serviceName := strings.Split(service, "/")[1]
serviceNamespace := strings.Split(service, "/")[0]
fmt.Printf("❌ Found Service: \033[31m%s\033[0m with selectors in namespace: \033[31m%s\033[0m\n", serviceName, serviceNamespace)
}
}
fmt.Println("Manual investigation is required to evaluate if ingress is allowed to the service's backend Pods.")
fmt.Println("Please evaluate if these services would be impacted by migration.")
return true
}

}

func hasIngressPolicies(policies []networkingv1.NetworkPolicy) bool {
// Check if any policy is ingress
for _, policy := range policies {

Check failure on line 302 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.22.x, ubuntu-latest)

rangeValCopy: each iteration copies 368 bytes (consider pointers or indexing) (gocritic)

Check failure on line 302 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.23.x, ubuntu-latest)

rangeValCopy: each iteration copies 368 bytes (consider pointers or indexing) (gocritic)

Check failure on line 302 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.22.x, windows-latest)

rangeValCopy: each iteration copies 368 bytes (consider pointers or indexing) (gocritic)

Check failure on line 302 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.23.x, windows-latest)

rangeValCopy: each iteration copies 368 bytes (consider pointers or indexing) (gocritic)
for _, ingress := range policy.Spec.Ingress {
if len(ingress.From) > 0 {
return true
}
}
}
return false
}

func checkServiceRisk(service v1.Service, namespace string, servicePorts []string, policiesListAtNamespace []networkingv1.NetworkPolicy, safeServices []string) []string {
for _, policy := range policiesListAtNamespace {

Check failure on line 313 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.22.x, ubuntu-latest)

rangeValCopy: each iteration copies 368 bytes (consider pointers or indexing) (gocritic)

Check failure on line 313 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.23.x, ubuntu-latest)

rangeValCopy: each iteration copies 368 bytes (consider pointers or indexing) (gocritic)

Check failure on line 313 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.22.x, windows-latest)

rangeValCopy: each iteration copies 368 bytes (consider pointers or indexing) (gocritic)

Check failure on line 313 in tools/azure-npm-to-cilium-validator.go

View workflow job for this annotation

GitHub Actions / Lint (1.23.x, windows-latest)

rangeValCopy: each iteration copies 368 bytes (consider pointers or indexing) (gocritic)
for _, ingress := range policy.Spec.Ingress {
// Check if there is an allow all ingress policy that matches labels the service is safe
if len(ingress.From) == 0 && len(ingress.Ports) == 0 {
// Check if there is an allow all ingress policy with empty selectors return true as the policy allows all services in the namespace
if len(policy.Spec.PodSelector.MatchLabels) == 0 {
fmt.Printf("found an allow all ingress policy: %s with empty selectors so service %s in the namespace %s is safe\n", policy.Name, service.Name, namespace)
safeServices = append(safeServices, fmt.Sprintf("%s/%s", namespace, service.Name))
return safeServices
}
// Check if there is an allow all ingress policy that matches the service labels
if checkPolicyMatchServiceLabels(service.Spec.Selector, policy.Spec.PodSelector.MatchLabels) {
fmt.Printf("found an allow all ingress policy: %s with matching selectors so service %s in the namespace %s is safe\n", policy.Name, service.Name, namespace)
safeServices = append(safeServices, fmt.Sprintf("%s/%s", namespace, service.Name))
return safeServices
}
}
// Check if all the labels in
// // If there are no ingress from but there are ports in the policy; check if the service is safe
// if len(ingress.From) == 0 && len(ingress.Ports) > 0 {
// if matchAllServiceSelector(&metav1.LabelSelector{MatchLabels: service.Spec.Selector}, &policy.Spec.PodSelector) {
// matchingPorts := []string{}
// for _, port := range ingress.Ports {
// matchingPorts = append(matchingPorts, fmt.Sprintf("%d/%s", port.Port.IntVal, string(*port.Protocol)))
// }
// for _, sevicePort := range servicePorts {
// if contains(matchingPorts, sevicePort) {
// safeServices = append(safeServices, fmt.Sprintf("%s/%s", namespace, service.Name))
// return
// }
// }
// }
// }
}
}
return safeServices
}

func checkPolicyMatchServiceLabels(serviceLabels, policyLabels map[string]string) bool {
// Return false if the policy has more labels than the service
if len(policyLabels) > len(serviceLabels) {
return false
}

// Check for each policy label that that label is present in the service labels
for policyKey, policyValue := range policyLabels {
matchedPolicyLabelToServiceLabel := false
for serviceKey, serviceValue := range serviceLabels {
if policyKey == serviceKey && policyValue == serviceValue {
matchedPolicyLabelToServiceLabel = true
break
}
}
if !matchedPolicyLabelToServiceLabel {
return false
}
}
return true
}

func contains(slice []string, item string) bool {
for _, s := range slice {
if s == item {
return true
}
}
return false
}

func difference(slice1, slice2, slice3 []string) []string {
m := make(map[string]bool)
for _, s := range slice2 {
m[s] = true
}
for _, s := range slice3 {
m[s] = true
}
var diff []string
for _, s := range slice1 {
if !m[s] {
diff = append(diff, s)
}
}
return diff
}
Loading