inferring application ports in case not configure so that they
can be used for linkerd authorization.
This commit is contained in:
parent
2066aad656
commit
ee8c0a2204
@ -2,12 +2,14 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
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"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type Cluster struct {
|
||||
@ -93,11 +95,35 @@ func (c *Cluster) IsLinkerdEnabled(application *Application) bool {
|
||||
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.
|
||||
func (c *Cluster) PortNumbers(application *Application) []Port {
|
||||
if !c.IsLinkerdEnabled(application) {
|
||||
return nil
|
||||
}
|
||||
tcpPorts := make(map[int]Port)
|
||||
udpPorts := make(map[int]Port)
|
||||
for _, pod := range c.Pods(application) {
|
||||
for _, container := range pod.Spec.Containers {
|
||||
for _, port := range container.Ports {
|
||||
switch port.Protocol {
|
||||
case "TCP":
|
||||
tcpPorts[int(port.ContainerPort)] = Port{
|
||||
Port: strconv.Itoa(int(port.ContainerPort)),
|
||||
Protocol: string(port.Protocol),
|
||||
}
|
||||
case "UDP":
|
||||
udpPorts[int(port.ContainerPort)] = Port{
|
||||
Port: strconv.Itoa(int(port.ContainerPort)),
|
||||
Protocol: string(port.Protocol),
|
||||
}
|
||||
|
||||
default:
|
||||
panic(fmt.Sprintf("Unknown port type for pod %s/%s: %s",
|
||||
pod.Namespace, pod.Name, port.Protocol))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
res := MapValues(tcpPorts)
|
||||
res = append(res, MapValues(udpPorts)...)
|
||||
return res
|
||||
}
|
||||
|
@ -6,9 +6,11 @@ import (
|
||||
"fmt"
|
||||
"github.com/goccy/go-yaml"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"slices"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var PREDEFINED_APPS = []string{"apiserver"}
|
||||
@ -180,11 +182,18 @@ func (c Config) GetApplication(name string) (*Application, *Network, string) {
|
||||
return nil, nil, ""
|
||||
}
|
||||
|
||||
func (c *Config) Infer(resolver func(application *Application) []string) {
|
||||
func (c *Config) Infer(resolver Resolver) {
|
||||
for _, ns := range c.Namespaces {
|
||||
for _, app := range ns.Applications {
|
||||
if len(app.ServiceAccounts) == 0 {
|
||||
app.ServiceAccounts = resolver(app)
|
||||
app.ServiceAccounts = resolver.ServiceAccounts(app)
|
||||
log.Printf("Inferred service accounts: %s/%s: %v", app.Namespace.Name, app.Name,
|
||||
app.ServiceAccounts)
|
||||
}
|
||||
if len(app.Ports) == 0 && !strings.HasPrefix(ns.Name, "linkerd") {
|
||||
app.Ports = resolver.PortNumbers(app)
|
||||
log.Printf("Inferred ports: %s/%s: %v", app.Namespace.Name, app.Name,
|
||||
app.Ports)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import (
|
||||
"iter"
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"log"
|
||||
"maps"
|
||||
"os"
|
||||
"slices"
|
||||
@ -21,6 +20,11 @@ const (
|
||||
Error
|
||||
)
|
||||
|
||||
type Resolver interface {
|
||||
ServiceAccounts(application *Application) []string
|
||||
PortNumbers(application *Application) []Port
|
||||
}
|
||||
|
||||
func LogValidationMsg(level ValidationLevel, msg string, v ...any) {
|
||||
fmt.Fprintf(os.Stderr, "NOTICE: "+msg+"\n", v...)
|
||||
}
|
||||
@ -36,6 +40,9 @@ func IterToSlice[K any](i iter.Seq[K]) []K {
|
||||
func MapKeys[K comparable, V any](m map[K]V) []K {
|
||||
return IterToSlice(maps.Keys(m))
|
||||
}
|
||||
func MapValues[K comparable, V any](m map[K]V) []V {
|
||||
return IterToSlice(maps.Values(m))
|
||||
}
|
||||
|
||||
func validate(files []string, options *Options) error {
|
||||
clientset, _ := GetKubernetesConnection()
|
||||
@ -49,12 +56,7 @@ func validate(files []string, options *Options) error {
|
||||
return err
|
||||
}
|
||||
|
||||
config.Infer(func(application *Application) []string {
|
||||
res := cluster.ServiceAccounts(application)
|
||||
log.Printf("Inferred service accounts: %s/%s: %v", application.Namespace.Name, application.Name,
|
||||
res)
|
||||
return res
|
||||
})
|
||||
config.Infer(cluster)
|
||||
|
||||
// map applname1 -> appname2 where appname1 is in an open namespace and app2 is in a closed namespace.
|
||||
// Exclusing when 'from' side is a CIDR.
|
||||
|
Loading…
Reference in New Issue
Block a user