policy-generator/cmd/policygen/generator.go

165 lines
3.7 KiB
Go

package main
import (
"io"
"os"
)
type Generator interface {
GenerateNamespace(writer io.Writer, namespace *Namespace) error
GenerateCommunicationRule(writer io.Writer, app *Application, ingress *Ingress, egress *Egress) error
}
type ApplicationPeer struct {
Application *Application
Ports []Port
}
type NetworkPeer struct {
Network *Network
Ports []Port
}
type Peer struct {
Applications []*ApplicationPeer
Networks []*NetworkPeer
Predefined []string
}
func (p *Peer) append(app *ApplicationPeer, network *NetworkPeer, predefined string) {
if app != nil {
p.Applications = append(p.Applications, app)
}
if network != nil {
p.Networks = append(p.Networks, network)
}
if predefined != "" {
p.Predefined = append(p.Predefined, predefined)
}
}
func (p *Peer) Empty() bool {
return len(p.Applications)+len(p.Networks)+len(p.Predefined) == 0
}
func (p Peer) String() string {
res := ""
for _, app := range p.Applications {
res += "app:" + app.Application.Name + " "
}
for _, net := range p.Networks {
res += "net:" + net.Network.Name + " "
}
for _, pre := range p.Predefined {
res += "pre:" + pre + " "
}
return res
}
type Ingress struct {
Peer
}
type Egress struct {
Peer
}
func Generate(writer io.Writer, generator Generator, config *Config) error {
for _, ns := range config.Namespaces {
err := generator.GenerateNamespace(os.Stdout, ns)
if err != nil {
return err
}
}
// Loop over all applications and gather the ingress and egress for each application
var ingresses = make(map[string]*Ingress)
var egresses = make(map[string]*Egress)
for _, ns := range config.Namespaces {
for _, app := range ns.Applications {
if ingresses[app.Name] == nil {
ingresses[app.Name] = &Ingress{}
}
if egresses[app.Name] == nil {
egresses[app.Name] = &Egress{}
}
}
}
for _, communication := range config.Communications {
for _, from := range communication.From {
appFrom, networkFrom, predefinedFrom := config.GetApplication(from)
for _, to := range communication.To {
appTo, networkTo, predefinedTo := config.GetApplication(to)
if appFrom != nil {
// we have an egress from appFrom
egress := egresses[from]
ports := communication.Ports
var appPeer *ApplicationPeer = nil
var networkPeer *NetworkPeer = nil
if appTo != nil {
if len(ports) == 0 {
ports = appTo.Ports
}
appPeer = &ApplicationPeer{
Application: appTo,
Ports: ports,
}
} else if networkTo != nil {
if len(ports) == 0 {
ports = networkTo.Ports
}
networkPeer = &NetworkPeer{
Network: networkTo,
Ports: ports,
}
}
egress.append(appPeer, networkPeer, predefinedTo)
}
if appTo != nil {
// we have an ingress on appTo
ingress := ingresses[to]
ports := communication.Ports
var appPeer *ApplicationPeer = nil
var networkPeer *NetworkPeer = nil
if appFrom != nil {
if len(ports) == 0 {
ports = appTo.Ports
}
appPeer = &ApplicationPeer{
Application: appFrom,
Ports: ports,
}
} else if networkFrom != nil {
if len(ports) == 0 {
ports = appTo.Ports
}
networkPeer = &NetworkPeer{
Network: networkFrom,
Ports: ports,
}
}
ingress.append(appPeer, networkPeer, predefinedFrom)
}
}
}
}
// loop over all apps and configure them
for _, ns := range config.Namespaces {
for _, app := range ns.Applications {
ingress := ingresses[app.Name]
egress := egresses[app.Name]
if !ingress.Empty() || !egress.Empty() {
err := generator.GenerateCommunicationRule(writer, app, ingress, egress)
if err != nil {
return err
}
}
}
}
return nil
}