eliminating duplicate communications. this caused problems with linkerd
and helm
This commit is contained in:
parent
cd4023f5ce
commit
2bea96cc57
@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Generator interface {
|
type Generator interface {
|
||||||
@ -15,12 +16,14 @@ type Generator interface {
|
|||||||
type ApplicationPeer struct {
|
type ApplicationPeer struct {
|
||||||
Application *Application
|
Application *Application
|
||||||
Ports []Port
|
Ports []Port
|
||||||
|
// used as convenience for template rendering.
|
||||||
Rule string
|
Rule string
|
||||||
}
|
}
|
||||||
|
|
||||||
type NetworkPeer struct {
|
type NetworkPeer struct {
|
||||||
Network *Network
|
Network *Network
|
||||||
Ports []Port
|
Ports []Port
|
||||||
|
// Used as convenience for template rendering.
|
||||||
Rule string
|
Rule string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,14 +35,24 @@ type Peer struct {
|
|||||||
|
|
||||||
func (p *Peer) append(app *ApplicationPeer, network *NetworkPeer, predefined string) {
|
func (p *Peer) append(app *ApplicationPeer, network *NetworkPeer, predefined string) {
|
||||||
if app != nil {
|
if app != nil {
|
||||||
|
if !slices.ContainsFunc(p.Applications, func(a *ApplicationPeer) bool {
|
||||||
|
return a.Application.Name == app.Application.Name && slices.Equal(a.Ports, app.Ports)
|
||||||
|
}) {
|
||||||
p.Applications = append(p.Applications, app)
|
p.Applications = append(p.Applications, app)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if network != nil {
|
if network != nil {
|
||||||
|
if !slices.ContainsFunc(p.Networks, func(n *NetworkPeer) bool {
|
||||||
|
return n.Network.Name == network.Network.Name && slices.Equal(n.Network.Ports, network.Network.Ports)
|
||||||
|
}) {
|
||||||
p.Networks = append(p.Networks, network)
|
p.Networks = append(p.Networks, network)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if predefined != "" {
|
if predefined != "" {
|
||||||
|
if !slices.Contains(p.Predefined, predefined) {
|
||||||
p.Predefined = append(p.Predefined, predefined)
|
p.Predefined = append(p.Predefined, predefined)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Peer) Empty() bool {
|
func (p *Peer) Empty() bool {
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"os"
|
"os"
|
||||||
"slices"
|
"slices"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -15,6 +14,7 @@ type LinkerdPolicyGenerator struct {
|
|||||||
config *Config
|
config *Config
|
||||||
policyTemplates *PolicyTemplates
|
policyTemplates *PolicyTemplates
|
||||||
|
|
||||||
|
apps map[string]*Application
|
||||||
networks map[string]*Network
|
networks map[string]*Network
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,6 +22,7 @@ func NewLinkerdPolicyGenerator(config *Config, templates *PolicyTemplates) *Link
|
|||||||
return &LinkerdPolicyGenerator{
|
return &LinkerdPolicyGenerator{
|
||||||
config: config,
|
config: config,
|
||||||
policyTemplates: templates,
|
policyTemplates: templates,
|
||||||
|
apps: make(map[string]*Application),
|
||||||
networks: make(map[string]*Network),
|
networks: make(map[string]*Network),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,83 +54,37 @@ func (g *LinkerdPolicyGenerator) GenerateCommunicationRule(
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(ingress.Applications)+
|
|
||||||
len(ingress.Networks) > 0 {
|
|
||||||
ports := make(map[int]bool)
|
|
||||||
//
|
|
||||||
clientApplications := make(map[int][]*ApplicationPeer)
|
|
||||||
for _, ingress := range ingress.Applications {
|
for _, ingress := range ingress.Applications {
|
||||||
for _, port := range ingress.Ports {
|
for _, port := range ingress.Ports {
|
||||||
if port.Protocol == "TCP" {
|
if port.Protocol != "TCP" {
|
||||||
portno, err := strconv.Atoi(port.Port)
|
continue
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error convert port '%s' of ingress '%s' of app '%s': %w",
|
|
||||||
port.Port, ingress.Application.Name, app.Name, err)
|
|
||||||
}
|
}
|
||||||
ports[portno] = true
|
g.apps[ingress.Application.Name] = ingress.Application
|
||||||
clientApplications[portno] = append(clientApplications[portno], ingress)
|
err = g.policyTemplates.Execute("linkerd", "authorizationpolicy-app",
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
clientNetworks := make(map[int][]*NetworkPeer)
|
|
||||||
for _, ingress := range ingress.Networks {
|
|
||||||
for _, port := range ingress.Ports {
|
|
||||||
if port.Protocol == "TCP" {
|
|
||||||
portno, err := strconv.Atoi(port.Port)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error convert port '%s' of ingress '%s' of app '%s': %w",
|
|
||||||
port.Port, ingress.Network.Name, app.Name, err)
|
|
||||||
}
|
|
||||||
ports[portno] = true
|
|
||||||
clientNetworks[portno] = append(clientNetworks[portno], ingress)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for port, _ := range ports {
|
|
||||||
fmt.Fprintf(os.Stderr, "Generating authorization policy: %v %v -> %v : %v\n",
|
|
||||||
Map(clientApplications[port], func(peer *ApplicationPeer) string {
|
|
||||||
return peer.Application.Name
|
|
||||||
}),
|
|
||||||
Map(clientNetworks[port], func(peer *NetworkPeer) string {
|
|
||||||
return peer.Network.Name
|
|
||||||
}),
|
|
||||||
app.Name,
|
|
||||||
port)
|
|
||||||
// Optimization: keep track of the references clientApps and
|
|
||||||
// client Networks and only generate authentications for those instead of for
|
|
||||||
// all apps and networks.
|
|
||||||
for _, clientNetwork := range clientNetworks[port] {
|
|
||||||
g.networks[clientNetwork.Network.Name] = clientNetwork.Network
|
|
||||||
}
|
|
||||||
|
|
||||||
// linkerd rules
|
|
||||||
// 1. an authpolicy may contain only one meshtlsauthentication rule
|
|
||||||
// 2. an authpolicy may contain only one service account .
|
|
||||||
// 3. an authpolicy may contain only one networkauthentication
|
|
||||||
//
|
|
||||||
// Should generate here a methtlsautheorization for every port
|
|
||||||
// and pass in a list of service accounts instead of a list of apps.
|
|
||||||
serviceAccounts := g.serviceAccounts(clientApplications[port])
|
|
||||||
if len(serviceAccounts) > 0 {
|
|
||||||
err = g.policyTemplates.Execute("linkerd", "meshtlsauthentication",
|
|
||||||
writer,
|
writer,
|
||||||
map[string]any{
|
map[string]any{
|
||||||
"app": app,
|
"app": app,
|
||||||
"port": port,
|
"port": port.Port,
|
||||||
"serviceAccounts": serviceAccounts,
|
"client": ingress.Application,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err = g.policyTemplates.Execute("linkerd", "authorizationpolicy",
|
}
|
||||||
|
|
||||||
|
for _, ingress := range ingress.Networks {
|
||||||
|
for _, port := range ingress.Ports {
|
||||||
|
if port.Protocol != "TCP" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
g.networks[ingress.Network.Name] = ingress.Network
|
||||||
|
err = g.policyTemplates.Execute("linkerd", "authorizationpolicy-net",
|
||||||
writer,
|
writer,
|
||||||
map[string]any{
|
map[string]any{
|
||||||
"app": app,
|
"app": app,
|
||||||
"port": port,
|
"port": port.Port,
|
||||||
"clientNetworks": clientNetworks[port],
|
"client": ingress.Network,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -160,6 +115,15 @@ func (g *LinkerdPolicyGenerator) serviceAccounts(peers []*ApplicationPeer) []v1.
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *LinkerdPolicyGenerator) Finalize(writer io.Writer) error {
|
func (g *LinkerdPolicyGenerator) Finalize(writer io.Writer) error {
|
||||||
|
for _, app := range g.apps {
|
||||||
|
fmt.Fprintf(os.Stderr, "MeshTLSAuthentication %s/%s %v\n",
|
||||||
|
app.Namespace.Name, app.Name, app.ServiceAccounts)
|
||||||
|
err := g.policyTemplates.Execute("linkerd", "meshtlsauthentication",
|
||||||
|
writer, app)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
for _, network := range g.networks {
|
for _, network := range g.networks {
|
||||||
fmt.Fprintf(os.Stderr, "NetworkAuthentication default/%s\n", network.Name)
|
fmt.Fprintf(os.Stderr, "NetworkAuthentication default/%s\n", network.Name)
|
||||||
err := g.policyTemplates.Execute("linkerd", "networkauthentication", writer, network)
|
err := g.policyTemplates.Execute("linkerd", "networkauthentication", writer, network)
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
apiVersion: policy.linkerd.io/v1alpha1
|
||||||
|
kind: AuthorizationPolicy
|
||||||
|
metadata:
|
||||||
|
name: app-{{ .client.Name }}-to-{{ .app.Name }}-p{{ .port }}
|
||||||
|
namespace: {{ .app.Namespace.Name}}
|
||||||
|
spec:
|
||||||
|
targetRef:
|
||||||
|
group: policy.linkerd.io
|
||||||
|
kind: Server
|
||||||
|
name: {{ .app.Name }}-p{{ .port }}
|
||||||
|
requiredAuthenticationRefs:
|
||||||
|
- name: {{ .client.Name }}
|
||||||
|
namespace: {{ .client.Namespace.Name }}
|
||||||
|
kind: MeshTLSAuthentication
|
||||||
|
group: policy.linkerd.io
|
@ -2,7 +2,7 @@
|
|||||||
apiVersion: policy.linkerd.io/v1alpha1
|
apiVersion: policy.linkerd.io/v1alpha1
|
||||||
kind: AuthorizationPolicy
|
kind: AuthorizationPolicy
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ .app.Name }}-p{{ .port }}
|
name: net-{{ .client.Name }}-to-{{ .app.Name }}-p{{ .port }}
|
||||||
namespace: {{ .app.Namespace.Name}}
|
namespace: {{ .app.Namespace.Name}}
|
||||||
spec:
|
spec:
|
||||||
targetRef:
|
targetRef:
|
||||||
@ -10,13 +10,7 @@ spec:
|
|||||||
kind: Server
|
kind: Server
|
||||||
name: {{ .app.Name }}-p{{ .port }}
|
name: {{ .app.Name }}-p{{ .port }}
|
||||||
requiredAuthenticationRefs:
|
requiredAuthenticationRefs:
|
||||||
- name: {{ .app.Name }}-p{{ .port }}
|
- name: {{ .client.Name }}
|
||||||
namespace: {{ .app.Namespace.Name }}
|
|
||||||
kind: MeshTLSAuthentication
|
|
||||||
group: policy.linkerd.io
|
|
||||||
{{- range $net := .clientNetworks }}
|
|
||||||
- name: {{ $net.Network.Name }}
|
|
||||||
namespace: default
|
namespace: default
|
||||||
kind: NetworkAuthentication
|
kind: NetworkAuthentication
|
||||||
group: policy.linkerd.io
|
group: policy.linkerd.io
|
||||||
{{- end }}
|
|
@ -2,13 +2,16 @@
|
|||||||
apiVersion: policy.linkerd.io/v1alpha1
|
apiVersion: policy.linkerd.io/v1alpha1
|
||||||
kind: MeshTLSAuthentication
|
kind: MeshTLSAuthentication
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ .app.Name }}-p{{.port}}
|
name: {{ .Name }}
|
||||||
namespace: {{ .app.Namespace.Name }}
|
namespace: {{ .Namespace.Name }}
|
||||||
spec:
|
spec:
|
||||||
|
{{- if .ServiceAccounts }}
|
||||||
identityRefs:
|
identityRefs:
|
||||||
{{- range $sa := .serviceAccounts }}
|
{{- range $sa := .ServiceAccounts }}
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: {{ $sa.Name }}
|
name: {{ $sa }}
|
||||||
namespace: {{ $sa.Namespace }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{- else }}
|
||||||
|
fail (printf "no service accounts defined for app %s" .Name )
|
||||||
|
{{- end}}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user