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