Skip to content

Commit 7625ef5

Browse files
committed
updated to return lists and use pointers but still broken for services
1 parent afa4e9d commit 7625ef5

File tree

1 file changed

+145
-105
lines changed

1 file changed

+145
-105
lines changed

tools/azure-npm-to-cilium-validator/azure-npm-to-cilium-validator.go

Lines changed: 145 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@ import (
1919
// go run azure-npm-to-cilium-validator.go --kubeconfig ~/.kube/config
2020

2121
func main() {
22-
// Remove timestamp from log
23-
log.SetFlags(0)
24-
2522
// Parse the kubeconfig flag
2623
kubeconfig := flag.String("kubeconfig", "~/.kube/config", "absolute path to the kubeconfig file")
2724
flag.Parse()
@@ -73,31 +70,48 @@ func main() {
7370
servicesByNamespace[ns.Name] = services.Items
7471
}
7572

73+
// Print the migration summary
74+
printMigrationSummary(namespaces, &policiesByNamespace, &servicesByNamespace)
75+
}
76+
77+
func printMigrationSummary(namespaces *corev1.NamespaceList, policiesByNamespace *map[string][]networkingv1.NetworkPolicy, servicesByNamespace *map[string][]corev1.Service) {
7678
fmt.Println("Migration Summary:")
7779
fmt.Println("+------------------------------+-------------------------------+")
7880
fmt.Printf("%-30s | %-30s \n", "Breaking Change", "No Policy Changes Needed")
7981
fmt.Println("+------------------------------+-------------------------------+")
8082

8183
// Check the endports of the network policies
82-
foundEnportNetworkPolicy := checkEndportNetworkPolicies(policiesByNamespace)
84+
ingressEndportNetworkPolicy, egressEndportNetworkPolicy := checkEndportNetworkPolicies(policiesByNamespace)
85+
86+
// Print the network policies with endport
87+
printPoliciesWithEndport(&ingressEndportNetworkPolicy, &egressEndportNetworkPolicy)
8388

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

8691
// Check the cidr of the network policies
87-
foundCIDRNetworkPolicy := checkCIDRNetworkPolicies(policiesByNamespace)
92+
ingressPoliciesWithCIDR, egressPoliciesWithCIDR := checkCIDRNetworkPolicies(policiesByNamespace)
93+
94+
// Print the network policies with CIDR
95+
printPoliciesWithCIDR(&ingressPoliciesWithCIDR, &egressPoliciesWithCIDR)
8896

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

9199
// Check the egress of the network policies
92-
foundEgressPolicy := checkForEgressPolicies(policiesByNamespace)
100+
egressPolicies := checkForEgressPolicies(policiesByNamespace)
101+
102+
// Print the network policies with egress
103+
printEgressPolicies(&egressPolicies)
93104

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

96107
// Check services that have externalTrafficPolicy!=Local
97-
foundServiceDispruption := checkExternalTrafficPolicyServices(namespaces, servicesByNamespace, policiesByNamespace)
108+
unsafeServices, noSelectorServices := checkExternalTrafficPolicyServices(namespaces, servicesByNamespace, policiesByNamespace)
109+
110+
// Print the services that are at risk
111+
printUnsafeServices(&unsafeServices, &noSelectorServices)
98112

99113
fmt.Println("+------------------------------+-------------------------------+")
100-
if foundEnportNetworkPolicy || foundCIDRNetworkPolicy || foundEgressPolicy || foundServiceDispruption {
114+
if len(ingressEndportNetworkPolicy) > 0 || len(egressEndportNetworkPolicy) > 0 || len(ingressPoliciesWithCIDR) > 0 || len(egressPoliciesWithCIDR) > 0 || len(egressPolicies) > 0 || len(unsafeServices) > 0 {
101115
fmt.Println("\033[31m✘ Review above issues before migration.\033[0m")
102116
fmt.Println("Please see \033[32maka.ms/azurenpmtocilium\033[0m for instructions on how to evaluate/assess the above warnings marked by ❌.")
103117
fmt.Println("NOTE: rerun this script if any modifications (create/update/delete) are made to services or policies.")
@@ -107,125 +121,177 @@ func main() {
107121
}
108122
}
109123

110-
func checkEndportNetworkPolicies(policiesByNamespace map[string][]networkingv1.NetworkPolicy) bool {
111-
foundNetworkPolicyWithEndport := false
112-
for namespace, policies := range policiesByNamespace {
124+
func printPoliciesWithEndport(ingressEndportNetworkPolicy *[]string, egressEndportNetworkPolicy *[]string) {
125+
if len(*ingressEndportNetworkPolicy) == 0 && len(*egressEndportNetworkPolicy) == 0 {
126+
fmt.Printf("%-30s | %-30s \n", "NetworkPolicy with endport", "✅")
127+
} else {
128+
fmt.Printf("%-30s | %-30s \n", "NetworkPolicy with endport", "❌")
129+
fmt.Println("Policies affected:")
130+
for _, policy := range *ingressEndportNetworkPolicy {
131+
policyNamespace := strings.Split(policy, "/")[0]
132+
policyName := strings.Split(policy, "/")[1]
133+
fmt.Printf("❌ Found NetworkPolicy: \033[31m%s\033[0m with ingress endPort field in namespace: \033[31m%s\033[0m\n", policyName, policyNamespace)
134+
}
135+
for _, policy := range *egressEndportNetworkPolicy {
136+
policyNamespace := strings.Split(policy, "/")[0]
137+
policyName := strings.Split(policy, "/")[1]
138+
fmt.Printf("❌ Found NetworkPolicy: \033[31m%s\033[0m with engress endPort field in namespace: \033[31m%s\033[0m\n", policyName, policyNamespace)
139+
}
140+
}
141+
}
142+
143+
func printPoliciesWithCIDR(ingressPoliciesWithCIDR *[]string, egressPoliciesWithCIDR *[]string) {
144+
if len(*ingressPoliciesWithCIDR) == 0 && len(*egressPoliciesWithCIDR) == 0 {
145+
fmt.Printf("%-30s | %-30s \n", "NetworkPolicy with CIDR", "✅")
146+
} else {
147+
fmt.Printf("%-30s | %-30s \n", "NetworkPolicy with CIDR", "❌")
148+
fmt.Println("Policies affected:")
149+
for _, policy := range *ingressPoliciesWithCIDR {
150+
policyNamespace := strings.Split(policy, "/")[0]
151+
policyName := strings.Split(policy, "/")[1]
152+
fmt.Printf("❌ Found NetworkPolicy: \033[31m%s\033[0m with ingress CIDR field in namespace: \033[31m%s\033[0m\n", policyName, policyNamespace)
153+
}
154+
for _, policy := range *egressPoliciesWithCIDR {
155+
policyNamespace := strings.Split(policy, "/")[0]
156+
policyName := strings.Split(policy, "/")[1]
157+
fmt.Printf("❌ Found NetworkPolicy: \033[31m%s\033[0m with egress CIDR field in namespace: \033[31m%s\033[0m\n", policyName, policyNamespace)
158+
}
159+
}
160+
}
161+
162+
func printEgressPolicies(egressPolicies *[]string) {
163+
if len(*egressPolicies) == 0 {
164+
fmt.Printf("%-30s | %-30s \n", "NetworkPolicy with egress", "✅")
165+
} else {
166+
fmt.Printf("%-30s | %-30s \n", "NetworkPolicy with egress", "❌")
167+
fmt.Printf("%-30s | %-30s \n", "(Not allow all egress)", "")
168+
fmt.Println("Policies affected:")
169+
for _, policy := range *egressPolicies {
170+
policyNamespace := strings.Split(policy, "/")[0]
171+
policyName := strings.Split(policy, "/")[1]
172+
fmt.Printf("❌ Found NetworkPolicy: \033[31m%s\033[0m with egress field (non-allow all) in namespace: \033[31m%s\033[0m\n", policyName, policyNamespace)
173+
}
174+
}
175+
}
176+
177+
func printUnsafeServices(unsafeServices *[]string, noSelectorServices *[]string) {
178+
// If there is no unsafe services then migration is safe for services with extranalTrafficPolicy=Cluster
179+
if len(*unsafeServices) == 0 {
180+
fmt.Printf("%-30s | %-30s \n", "Disruption for some", "✅")
181+
fmt.Printf("%-30s | %-30s \n", "Services with", "")
182+
fmt.Printf("%-30s | %-30s \n", "externalTrafficPolicy=Cluster", "")
183+
} else {
184+
fmt.Printf("%-30s | %-30s \n", "Disruption for some", "❌")
185+
fmt.Printf("%-30s | %-30s \n", "Services with", "")
186+
fmt.Printf("%-30s | %-30s \n", "externalTrafficPolicy=Cluster", "")
187+
fmt.Println("Services affected:")
188+
// If there are any no selector services or unsafe services then print them as they could be impacted by migration
189+
if len(*noSelectorServices) > 0 {
190+
for _, service := range *noSelectorServices {
191+
serviceName := strings.Split(service, "/")[1]
192+
serviceNamespace := strings.Split(service, "/")[0]
193+
fmt.Printf("❌ Found Service: \033[31m%s\033[0m without selectors in namespace: \033[31m%s\033[0m\n", serviceName, serviceNamespace)
194+
}
195+
}
196+
if len(*unsafeServices) > 0 {
197+
for _, service := range *unsafeServices {
198+
serviceName := strings.Split(service, "/")[1]
199+
serviceNamespace := strings.Split(service, "/")[0]
200+
fmt.Printf("❌ Found Service: \033[31m%s\033[0m with selectors in namespace: \033[31m%s\033[0m\n", serviceName, serviceNamespace)
201+
}
202+
}
203+
fmt.Println("Manual investigation is required to evaluate if ingress is allowed to the service's backend Pods.")
204+
fmt.Println("Please evaluate if these services would be impacted by migration.")
205+
}
206+
}
207+
208+
func checkEndportNetworkPolicies(policiesByNamespace *map[string][]networkingv1.NetworkPolicy) ([]string, []string) {
209+
var ingressPoliciesWithEndport []string
210+
var egressPoliciesWithEndport []string
211+
for namespace, policies := range *policiesByNamespace {
113212
for _, policy := range policies {
114213
// Check the ingress field for endport
115214
for _, ingress := range policy.Spec.Ingress {
116-
foundEndPort := checkEndportInPolicyRules(ingress.Ports, policy.Name, namespace, "ingress", foundNetworkPolicyWithEndport)
215+
foundEndPort := checkEndportInPolicyRules(&ingress.Ports)
117216
if foundEndPort {
118-
foundNetworkPolicyWithEndport = true
217+
ingressPoliciesWithEndport = append(ingressPoliciesWithEndport, fmt.Sprintf("%s/%s", namespace, policy.Name))
119218
break
120219
}
121220
}
122221
for _, egress := range policy.Spec.Egress {
123-
foundEndPort := checkEndportInPolicyRules(egress.Ports, policy.Name, namespace, "egress", foundNetworkPolicyWithEndport)
222+
foundEndPort := checkEndportInPolicyRules(&egress.Ports)
124223
if foundEndPort {
125-
foundNetworkPolicyWithEndport = true
224+
egressPoliciesWithEndport = append(egressPoliciesWithEndport, fmt.Sprintf("%s/%s", namespace, policy.Name))
126225
break
127226
}
128227
}
129228
}
130229
}
131-
// Print no impact if no network policy has endport
132-
if !foundNetworkPolicyWithEndport {
133-
log.Printf("%-30s | %-30s \n", "NetworkPolicy with endPort", "✅")
134-
return false
135-
}
136-
return true
230+
return ingressPoliciesWithEndport, egressPoliciesWithEndport
137231
}
138232

139-
func checkEndportInPolicyRules(ports []networkingv1.NetworkPolicyPort, policyName, namespace string, direction string, foundNetworkPolicyWithEndport bool) bool {
140-
foundEndPort := false
141-
for _, port := range ports {
233+
func checkEndportInPolicyRules(ports *[]networkingv1.NetworkPolicyPort) bool {
234+
for _, port := range *ports {
142235
if port.EndPort != nil {
143-
foundEndPort = true
144-
if !foundNetworkPolicyWithEndport {
145-
log.Printf("%-30s | %-30s \n", "NetworkPolicy with endPort", "❌")
146-
log.Println("Policies affected:")
147-
}
148-
log.Printf("❌ Found NetworkPolicy: \033[31m%s\033[0m with %s endPort field in namespace: \033[31m%s\033[0m\n", policyName, direction, namespace)
149-
break
236+
return true
150237
}
151238
}
152-
return foundEndPort
239+
return false
153240
}
154241

155-
func checkCIDRNetworkPolicies(policiesByNamespace map[string][]networkingv1.NetworkPolicy) bool {
156-
foundNetworkPolicyWithCIDR := false
157-
for namespace, policies := range policiesByNamespace {
242+
func checkCIDRNetworkPolicies(policiesByNamespace *map[string][]networkingv1.NetworkPolicy) ([]string, []string) {
243+
var ingressPoliciesWithCIDR []string
244+
var egressPoliciesWithCIDR []string
245+
for namespace, policies := range *policiesByNamespace {
158246
for _, policy := range policies {
159247
// Check the ingress field for cidr
160248
for _, ingress := range policy.Spec.Ingress {
161-
foundCIDRIngress := checkCIDRInPolicyRules(ingress.From, policy.Name, namespace, "ingress", foundNetworkPolicyWithCIDR)
249+
foundCIDRIngress := checkCIDRInPolicyRules(&ingress.From)
162250
if foundCIDRIngress {
163-
foundNetworkPolicyWithCIDR = true
251+
ingressPoliciesWithCIDR = append(ingressPoliciesWithCIDR, fmt.Sprintf("%s/%s", namespace, policy.Name))
164252
break
165253
}
166254
}
167255
// Check the egress field for cidr
168256
for _, egress := range policy.Spec.Egress {
169-
foundCIDREgress := checkCIDRInPolicyRules(egress.To, policy.Name, namespace, "egress", foundNetworkPolicyWithCIDR)
257+
foundCIDREgress := checkCIDRInPolicyRules(&egress.To)
170258
if foundCIDREgress {
171-
foundNetworkPolicyWithCIDR = true
259+
egressPoliciesWithCIDR = append(egressPoliciesWithCIDR, fmt.Sprintf("%s/%s", namespace, policy.Name))
172260
break
173261
}
174262
}
175263
}
176264
}
177-
// Print no impact if no network policy has cidr
178-
if !foundNetworkPolicyWithCIDR {
179-
log.Printf("%-30s | %-30s \n", "NetworkPolicy with cidr", "✅")
180-
return false
181-
}
182-
return true
265+
return ingressPoliciesWithCIDR, egressPoliciesWithCIDR
183266
}
184267

185268
// Check for CIDR in ingress or egress rules
186-
func checkCIDRInPolicyRules(rules []networkingv1.NetworkPolicyPeer, policyName, namespace string, direction string, foundNetworkPolicyWithCIDR bool) bool {
187-
foundCIDR := false
188-
for _, rule := range rules {
269+
func checkCIDRInPolicyRules(rules *[]networkingv1.NetworkPolicyPeer) bool {
270+
for _, rule := range *rules {
189271
if rule.IPBlock != nil && rule.IPBlock.CIDR != "" {
190-
foundCIDR = true
191-
if !foundNetworkPolicyWithCIDR {
192-
log.Printf("%-30s | %-30s \n", "NetworkPolicy with cidr", "❌")
193-
log.Println("Policies affected:")
194-
}
195-
log.Printf("❌ Found NetworkPolicy: \033[31m%s\033[0m with %s cidr field in namespace: \033[31m%s\033[0m\n", policyName, direction, namespace)
196-
break
272+
return true
197273
}
198274
}
199-
return foundCIDR
275+
return false
200276
}
201277

202-
func checkForEgressPolicies(policiesByNamespace map[string][]networkingv1.NetworkPolicy) bool {
203-
foundNetworkPolicyWithEgress := false
204-
for namespace, policies := range policiesByNamespace {
278+
func checkForEgressPolicies(policiesByNamespace *map[string][]networkingv1.NetworkPolicy) []string {
279+
var egressPolicies []string
280+
for namespace, policies := range *policiesByNamespace {
205281
for _, policy := range policies {
206282
for _, egress := range policy.Spec.Egress {
207283
// If the policy has a egress field thats not an egress allow all flag it
208284
if len(egress.To) > 0 || len(egress.Ports) > 0 {
209-
if !foundNetworkPolicyWithEgress {
210-
log.Printf("%-30s | %-30s \n", "NetworkPolicy with egress", "❌")
211-
log.Printf("%-30s | %-30s \n", "(Not allow all egress)", "")
212-
log.Println("Policies affected:")
213-
foundNetworkPolicyWithEgress = true
214-
}
215-
log.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)
285+
egressPolicies = append(egressPolicies, fmt.Sprintf("%s/%s", namespace, policy.Name))
216286
break
217287
}
218288
}
219289
}
220290
}
221-
if !foundNetworkPolicyWithEgress {
222-
log.Printf("%-30s | %-30s \n", "NetworkPolicy with egress", "✅")
223-
return false
224-
}
225-
return true
291+
return egressPolicies
226292
}
227293

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

231297
for _, namespace := range namespaces.Items {
@@ -260,42 +326,12 @@ func checkExternalTrafficPolicyServices(namespaces *corev1.NamespaceList, servic
260326
// Get the services that are at risk but not in the safe services or no selector services lists
261327
unsafeServices := difference(servicesAtRisk, safeServices, noSelectorServices)
262328

263-
// If there is no unsafe services then migration is safe for services with extranalTrafficPolicy=Cluster
264-
if len(unsafeServices) == 0 {
265-
fmt.Printf("%-30s | %-30s \n", "Disruption for some", "✅")
266-
fmt.Printf("%-30s | %-30s \n", "Services with", "")
267-
fmt.Printf("%-30s | %-30s \n", "externalTrafficPolicy=Cluster", "")
268-
return false
269-
} else {
270-
fmt.Printf("%-30s | %-30s \n", "Disruption for some", "❌")
271-
fmt.Printf("%-30s | %-30s \n", "Services with", "")
272-
fmt.Printf("%-30s | %-30s \n", "externalTrafficPolicy=Cluster", "")
273-
fmt.Println("Services affected:")
274-
// If there are any no selector services or unsafe services then print them as they could be impacted by migration
275-
if len(noSelectorServices) > 0 {
276-
for _, service := range noSelectorServices {
277-
serviceName := strings.Split(service, "/")[1]
278-
serviceNamespace := strings.Split(service, "/")[0]
279-
fmt.Printf("❌ Found Service: \033[31m%s\033[0m without selectors in namespace: \033[31m%s\033[0m\n", serviceName, serviceNamespace)
280-
}
281-
}
282-
if len(unsafeServices) > 0 {
283-
for _, service := range unsafeServices {
284-
serviceName := strings.Split(service, "/")[1]
285-
serviceNamespace := strings.Split(service, "/")[0]
286-
fmt.Printf("❌ Found Service: \033[31m%s\033[0m with selectors in namespace: \033[31m%s\033[0m\n", serviceName, serviceNamespace)
287-
}
288-
}
289-
fmt.Println("Manual investigation is required to evaluate if ingress is allowed to the service's backend Pods.")
290-
fmt.Println("Please evaluate if these services would be impacted by migration.")
291-
return true
292-
}
293-
329+
return unsafeServices, noSelectorServices
294330
}
295331

296-
func hasIngressPolicies(policies []networkingv1.NetworkPolicy) bool {
332+
func hasIngressPolicies(policies *[]networkingv1.NetworkPolicy) bool {
297333
// Check if any policy is ingress (including allow all and deny all)
298-
for _, policy := range policies {
334+
for _, policy := range *policies {
299335
for _, policyType := range policy.Spec.PolicyTypes {
300336
if policyType == networkingv1.PolicyTypeIngress {
301337
return true
@@ -375,6 +411,10 @@ func checkServiceTargetPortMatchPolicyPorts(servicePorts []corev1.ServicePort, p
375411
// Check if all the services target ports are in the policies ingress ports
376412
serviceTargetPortPolicyPort := false
377413
for _, policyPort := range policyPorts {
414+
// Check if the policys port exists
415+
if policyPort.Port == nil {
416+
return false
417+
}
378418
if servicePort.TargetPort.IntValue() == int(policyPort.Port.IntVal) && string(servicePort.Protocol) == string(*policyPort.Protocol) {
379419
serviceTargetPortPolicyPort = true
380420
break

0 commit comments

Comments
 (0)