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,15 +35,25 @@ 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 { | ||||||
| 	return len(p.Applications)+len(p.Networks)+len(p.Predefined) == 0 | 	return len(p.Applications)+len(p.Networks)+len(p.Predefined) == 0 | ||||||
|  | |||||||
| @ -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 }} | ||||||
|  |   {{- else }} | ||||||
|  |     fail (printf "no service accounts defined for app %s" .Name ) | ||||||
|   {{- end}} |   {{- end}} | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user