From ef99ad61e86b1dccd8a55195f33d6fb025f1fd4b Mon Sep 17 00:00:00 2001 From: Erik Brakkee Date: Sun, 19 Jan 2025 19:51:25 +0100 Subject: [PATCH] linkerd in progress. Network authentications generated. --- cmd/policygen/config.go | 4 +- cmd/policygen/generator.go | 8 ++- cmd/policygen/linkerd_generator.go | 55 +++++++++++++++++++ cmd/policygen/main.go | 32 ++++++++++- cmd/policygen/netpol_generator.go | 10 +++- .../application/network-authentication.yaml | 17 ++++++ cmd/policygen/validator.go | 2 +- 7 files changed, 119 insertions(+), 9 deletions(-) create mode 100644 cmd/policygen/linkerd_generator.go create mode 100644 cmd/policygen/templates/linkerd/application/network-authentication.yaml diff --git a/cmd/policygen/config.go b/cmd/policygen/config.go index fee8b65..e8a3494 100644 --- a/cmd/policygen/config.go +++ b/cmd/policygen/config.go @@ -49,7 +49,7 @@ type Port struct { // Network represents each network entry in the YAML type Network struct { - Name string `yaml:"name" validate:"required,applicationName"` + Name string `yaml:"name" validate:"required,applicationName,hostname"` CIDR CIDR `yaml:"cidr"` Except []CIDR `yaml:"except,omitempty" validate:"dive,required"` Ports []Port `yaml:"ports,omitempty" validate:"dive,required"` @@ -62,7 +62,7 @@ type MatchExpression struct { } type Application struct { - Name string `yaml:"name" validate:"required,applicationName"` + Name string `yaml:"name" validate:"required,applicationName,hostname"` Ports []Port `yaml:"ports,omitempty"` MatchLabels map[string]string `yaml:"matchLabels"` //MatchExpressions []MatchExpression `yaml:"matchExpressions" validate:"omitempty,dive"` diff --git a/cmd/policygen/generator.go b/cmd/policygen/generator.go index 76fd082..3b0da7a 100644 --- a/cmd/policygen/generator.go +++ b/cmd/policygen/generator.go @@ -6,6 +6,7 @@ import ( ) type Generator interface { + Init(write io.Writer) error GenerateNamespace(writer io.Writer, namespace *Namespace) error GenerateCommunicationRule(writer io.Writer, app *Application, ingress *Ingress, egress *Egress) error } @@ -66,8 +67,13 @@ type Egress struct { } func Generate(writer io.Writer, generator Generator, config *Config) error { + err := generator.Init(writer) + if err != nil { + return err + } + for _, ns := range config.Namespaces { - err := generator.GenerateNamespace(os.Stdout, ns) + err = generator.GenerateNamespace(os.Stdout, ns) if err != nil { return err } diff --git a/cmd/policygen/linkerd_generator.go b/cmd/policygen/linkerd_generator.go new file mode 100644 index 0000000..611ebdf --- /dev/null +++ b/cmd/policygen/linkerd_generator.go @@ -0,0 +1,55 @@ +package main + +import ( + "fmt" + "io" + "os" +) + +type LinkerdPolicyGenerator struct { + config *Config + policyTemplates *PolicyTemplates +} + +func (g LinkerdPolicyGenerator) Init(writer io.Writer) error { + // start by generating network authentications + for _, network := range g.config.Networks { + fmt.Fprintf(os.Stderr, "NetworkAuthentication default/%s\n", network.Name) + template := g.policyTemplates.PredefineApplicationPolicyTemplate("linkerd", "network-authentication") + if template == nil { + return fmt.Errorf("Linkerd template for network authentication not found") + } + err := template.Execute(writer, network) + if err != nil { + return fmt.Errorf("Error executing network authentication template for %s", network.Name) + } + } + return nil +} + +func (g LinkerdPolicyGenerator) GenerateNamespace(writer io.Writer, namespace *Namespace) error { + // and then the meshTLSAuthentications + for _, app := range namespace.Applications { + fmt.Fprintf(os.Stderr, "MeshTLSAuthentication %s/%s %v\n", + namespace.Name, app.Name, app.ServiceAccounts) + } + return nil +} + +func (g LinkerdPolicyGenerator) GenerateCommunicationRule( + writer io.Writer, + app *Application, + ingress *Ingress, + egress *Egress) error { + + if len(ingress.Applications)+ + len(ingress.Networks)+ + len(egress.Applications)+ + len(egress.Networks) > 0 { + // non-trivial regular network policy + + // TODO + } + + return nil +} diff --git a/cmd/policygen/main.go b/cmd/policygen/main.go index 5dac714..1696f91 100644 --- a/cmd/policygen/main.go +++ b/cmd/policygen/main.go @@ -42,7 +42,7 @@ func generateNetworkPolicy(files []string, options *Options) error { return err } var generator Generator - generator = NetworkPolicyGenerrator{ + generator = NetworkPolicyGenerator{ config: config, policyTemplates: policyTemplates, } @@ -55,7 +55,35 @@ func generateNetworkPolicy(files []string, options *Options) error { } func generateLinkerdPolicies(files []string, options *Options) error { - return fmt.Errorf(("Not yet implemented")) + if len(files) == 0 { + return fmt.Errorf("File expected") + } + config, err := readConfig(files) + if err != nil { + return err + } + clientset, _ := GetKubernetesConnection() + cluster, err := NewCluster(clientset) + if err != nil { + return err + } + config.Infer(cluster) + + policyTemplates, err := NewPolicyTemplates() + if err != nil { + return err + } + var generator Generator + generator = LinkerdPolicyGenerator{ + config: config, + policyTemplates: policyTemplates, + } + err = Generate(os.Stdout, generator, config) + if err != nil { + return err + } + + return nil } func main() { diff --git a/cmd/policygen/netpol_generator.go b/cmd/policygen/netpol_generator.go index 939d2c8..67543d4 100644 --- a/cmd/policygen/netpol_generator.go +++ b/cmd/policygen/netpol_generator.go @@ -7,12 +7,16 @@ import ( "slices" ) -type NetworkPolicyGenerrator struct { +type NetworkPolicyGenerator struct { config *Config policyTemplates *PolicyTemplates } -func (g NetworkPolicyGenerrator) GenerateNamespace(writer io.Writer, namespace *Namespace) error { +func (g NetworkPolicyGenerator) Init(writer io.Writer) error { + return nil +} + +func (g NetworkPolicyGenerator) GenerateNamespace(writer io.Writer, namespace *Namespace) error { fmt.Fprintf(os.Stderr, "Namespace %s\n", namespace.Name) templates := g.policyTemplates.NamespaceTemplates("netpol", namespace.Capabilities) @@ -26,7 +30,7 @@ func (g NetworkPolicyGenerrator) GenerateNamespace(writer io.Writer, namespace * return nil } -func (g NetworkPolicyGenerrator) GenerateCommunicationRule( +func (g NetworkPolicyGenerator) GenerateCommunicationRule( writer io.Writer, app *Application, ingress *Ingress, diff --git a/cmd/policygen/templates/linkerd/application/network-authentication.yaml b/cmd/policygen/templates/linkerd/application/network-authentication.yaml new file mode 100644 index 0000000..52682ca --- /dev/null +++ b/cmd/policygen/templates/linkerd/application/network-authentication.yaml @@ -0,0 +1,17 @@ +{{- if .CIDR }} +--- +apiVersion: policy.linkerd.io/v1alpha1 +kind: NetworkAuthentication +metadata: + name: {{ .Name }} + namespace: default +spec: + networks: + - cidr: {{ .CIDR }} + {{- if .Except }} + except: + {{- range $cidr := .Except }} + - {{ $cidr }} + {{- end }} + {{- end }} + {{- end }} \ No newline at end of file diff --git a/cmd/policygen/validator.go b/cmd/policygen/validator.go index 4f38dcf..39cea1b 100644 --- a/cmd/policygen/validator.go +++ b/cmd/policygen/validator.go @@ -32,7 +32,7 @@ var translations = map[string]Translation{ }, }, "applicationName": { - "{0} must not end with -p[0-9]+$ to prevent conflicts with generated resource names", + "{0} must not end with -[0-9]+$ to prevent conflicts with generated resource names", func(fe validator.FieldError) []any { return []any{fe.Namespace()} },