open-> closed check not takingin to account annotation and filtering out
cases where the From is already a CIDR.
This commit is contained in:
		
							parent
							
								
									b7a0b6a557
								
							
						
					
					
						commit
						2066aad656
					
				
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							| @ -17,7 +17,7 @@ build: vet | ||||
| 	mkdir -p bin | ||||
| 	go build -o bin ./cmd/... | ||||
| 
 | ||||
| install:  | ||||
| install: build | ||||
| 	go install ./... | ||||
| 
 | ||||
| test: build | ||||
|  | ||||
							
								
								
									
										103
									
								
								cmd/policygen/cluster.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								cmd/policygen/cluster.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,103 @@ | ||||
| package main | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	v1 "k8s.io/api/core/v1" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"k8s.io/apimachinery/pkg/labels" | ||||
| 	"k8s.io/client-go/kubernetes" | ||||
| 	"log" | ||||
| 	"slices" | ||||
| ) | ||||
| 
 | ||||
| type Cluster struct { | ||||
| 	namespaces map[string]v1.Namespace | ||||
| 	clientset  *kubernetes.Clientset | ||||
| 	// map of namespace to list of all pods
 | ||||
| 	pods map[string][]v1.Pod | ||||
| } | ||||
| 
 | ||||
| func NewCluster(clientset *kubernetes.Clientset) (*Cluster, error) { | ||||
| 	cluster := &Cluster{ | ||||
| 		clientset:  clientset, | ||||
| 		namespaces: make(map[string]v1.Namespace), | ||||
| 		pods:       make(map[string][]v1.Pod), | ||||
| 	} | ||||
| 	nslist, err := cluster.clientset.CoreV1().Namespaces().List(context.Background(), metav1.ListOptions{}) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	for _, ns := range nslist.Items { | ||||
| 		cluster.namespaces[ns.Name] = ns | ||||
| 		podList, err := cluster.clientset.CoreV1().Pods(ns.Name).List(context.Background(), metav1.ListOptions{}) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		cluster.pods[ns.Name] = podList.Items | ||||
| 	} | ||||
| 	return cluster, nil | ||||
| } | ||||
| 
 | ||||
| func (c *Cluster) Pods(application *Application) []v1.Pod { | ||||
| 	selector, err := metav1.LabelSelectorAsSelector(application.Selector()) | ||||
| 	if err != nil { | ||||
| 		log.Fatalf("Error creating selector: %v", err) | ||||
| 	} | ||||
| 	pods := c.pods[application.Namespace.Name] | ||||
| 	pods = slices.DeleteFunc(slices.Clone(pods), func(pod v1.Pod) bool { | ||||
| 		return !selector.Matches(labels.Set(pod.Labels)) | ||||
| 	}) | ||||
| 	return pods | ||||
| } | ||||
| 
 | ||||
| func (c *Cluster) ServiceAccounts(application *Application) []string { | ||||
| 	var res []string | ||||
| 	for _, pod := range c.Pods(application) { | ||||
| 		if !slices.Contains(res, pod.Spec.ServiceAccountName) { | ||||
| 			res = append(res, pod.Spec.ServiceAccountName) | ||||
| 		} | ||||
| 	} | ||||
| 	return res | ||||
| } | ||||
| 
 | ||||
| func (c *Cluster) OwnerReferences(application *Application) []string { | ||||
| 	var ownerReferences []string | ||||
| 	for _, pod := range c.Pods(application) { | ||||
| 		//log.Printf("  %s %v", pod.Name, pod.OwnerReferences)
 | ||||
| 		for _, ownerReference := range pod.OwnerReferences { | ||||
| 			owner := ownerReference.Kind + "/" + ownerReference.Name | ||||
| 			if !slices.Contains(ownerReferences, owner) { | ||||
| 				ownerReferences = append(ownerReferences, owner) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return ownerReferences | ||||
| } | ||||
| 
 | ||||
| func (c *Cluster) IsLinkerdEnabled(application *Application) bool { | ||||
| 	pods := c.Pods(application) | ||||
| 
 | ||||
| 	ndisabled := 0 | ||||
| 	for _, pod := range pods { | ||||
| 		if pod.Annotations["linkerd.io/inject"] == "enabled" { | ||||
| 			return true | ||||
| 		} | ||||
| 		if pod.Annotations["linkerd.io/inject"] == "disabled" { | ||||
| 			ndisabled++ | ||||
| 		} | ||||
| 	} | ||||
| 	if ndisabled == len(pods) { | ||||
| 		return false | ||||
| 	} | ||||
| 	ns := c.namespaces[application.Namespace.Name] | ||||
| 	return ns.Annotations["linkerd.io/inject"] == "enabled" | ||||
| } | ||||
| 
 | ||||
| func (c *Cluster) Ports(application *Application, nameBased bool) []Port { | ||||
| 	// gather unique ports based on name
 | ||||
| 	// or based on number.
 | ||||
| 	// Warning: same name different ports
 | ||||
| 	//          same port different names.
 | ||||
| 	// Can occur if the selector matches multiple replicasets.
 | ||||
| 	return nil | ||||
| } | ||||
| @ -70,6 +70,13 @@ type Application struct { | ||||
| 	Namespace        *Namespace                        `yaml:"-" validate:"-"` | ||||
| } | ||||
| 
 | ||||
| func (a Application) Selector() *metav1.LabelSelector { | ||||
| 	return &metav1.LabelSelector{ | ||||
| 		MatchLabels:      a.MatchLabels, | ||||
| 		MatchExpressions: a.MatchExpressions, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| type Namespace struct { | ||||
| 	Name         string         `yaml:"name"` | ||||
| 	Open         bool           `yaml:"open"` | ||||
|  | ||||
| @ -6,7 +6,6 @@ import ( | ||||
| 	"iter" | ||||
| 	"k8s.io/api/core/v1" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"k8s.io/client-go/kubernetes" | ||||
| 	"log" | ||||
| 	"maps" | ||||
| 	"os" | ||||
| @ -44,14 +43,14 @@ func validate(files []string, options *Options) error { | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	cluster, err := NewCluster(clientset) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	config.Infer(func(application *Application) []string { | ||||
| 		pods := FindPods(application, clientset) | ||||
| 		var res []string | ||||
| 		for _, pod := range pods { | ||||
| 			if !slices.Contains(res, pod.Spec.ServiceAccountName) { | ||||
| 				res = append(res, pod.Spec.ServiceAccountName) | ||||
| 			} | ||||
| 		} | ||||
| 		res := cluster.ServiceAccounts(application) | ||||
| 		log.Printf("Inferred service accounts: %s/%s: %v", application.Namespace.Name, application.Name, | ||||
| 			res) | ||||
| 		return res | ||||
| @ -75,21 +74,15 @@ func validate(files []string, options *Options) error { | ||||
| 		serviceAccountMap := make(map[string][]string) | ||||
| 
 | ||||
| 		for _, application := range ns.Applications { | ||||
| 			pods := FindPods(application, clientset) | ||||
| 			pods := cluster.Pods(application) | ||||
| 			applicationPods[application.Name] = pods | ||||
| 			//log.Printf(namespace + "/" + application.Name)
 | ||||
| 			if len(pods) == 0 { | ||||
| 				LogValidationMsg(Error, "application %s: no running pods found", application.Name) | ||||
| 			} | ||||
| 			ownerReferences := make(map[string]bool) | ||||
| 			for _, pod := range pods { | ||||
| 				//log.Printf("  %s %v", pod.Name, pod.OwnerReferences)
 | ||||
| 				for _, ownerReference := range pod.OwnerReferences { | ||||
| 					ownerReferences[ownerReference.Kind+"/"+ownerReference.Name] = true | ||||
| 				} | ||||
| 			} | ||||
| 			ownerReferences := cluster.OwnerReferences(application) | ||||
| 			if len(ownerReferences) > 1 { | ||||
| 				LogValidationMsg(Error, "Application %s: multiple owners found:  %v. The application definition can possibly be made more fine-grain", application.Name, MapKeys(ownerReferences)) | ||||
| 				LogValidationMsg(Error, "Application %s: multiple owners found:  %v. The application definition can possibly be made more fine-grain", application.Name, ownerReferences) | ||||
| 			} | ||||
| 			// check ports
 | ||||
| 			for _, port := range application.Ports { | ||||
| @ -153,7 +146,7 @@ func validate(files []string, options *Options) error { | ||||
| 				continue | ||||
| 			} | ||||
| 			for _, port := range communication.Ports { | ||||
| 				pods := FindPods(application, clientset) | ||||
| 				pods := cluster.Pods(application) | ||||
| 				for _, pod := range pods { | ||||
| 					if !HasPort(pod, port) { | ||||
| 						LogValidationMsg(Error, "communication %v -> %v: port %v is not configured in pod %s/%s", | ||||
| @ -187,7 +180,7 @@ func validate(files []string, options *Options) error { | ||||
| 						if applicationFrom != nil && !applicationFrom.Namespace.Open { | ||||
| 							continue | ||||
| 						} | ||||
| 						if networkFrom == nil { | ||||
| 						if networkFrom == nil && cluster.IsLinkerdEnabled(application) { | ||||
| 							openToClosedAccess[applicationNameFrom] = applicationName | ||||
| 						} | ||||
| 					} | ||||
| @ -204,24 +197,6 @@ func validate(files []string, options *Options) error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func FindPods(application *Application, clientset *kubernetes.Clientset) []v1.Pod { | ||||
| 	labelSelector := &metav1.LabelSelector{ | ||||
| 		MatchLabels:      application.MatchLabels, | ||||
| 		MatchExpressions: application.MatchExpressions, | ||||
| 	} | ||||
| 	selector, err := metav1.LabelSelectorAsSelector(labelSelector) | ||||
| 	if err != nil { | ||||
| 		log.Fatalf("Error creating selector: %v", err) | ||||
| 	} | ||||
| 	pods, err := clientset.CoreV1().Pods(application.Namespace.Name).List(context.TODO(), metav1.ListOptions{ | ||||
| 		LabelSelector: selector.String(), | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		log.Fatalf("Error listing pods: %v", err) | ||||
| 	} | ||||
| 	return pods.Items | ||||
| } | ||||
| 
 | ||||
| func HasPort(pod v1.Pod, port Port) bool { | ||||
| 	if port.Protocol == "" { | ||||
| 		port.Protocol = "TCP" | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user