summaryrefslogtreecommitdiff
path: root/modules/ri-wireguard/src/main/resources/io/trygvis/rules/wireguard/wireguard.drl
diff options
context:
space:
mode:
Diffstat (limited to 'modules/ri-wireguard/src/main/resources/io/trygvis/rules/wireguard/wireguard.drl')
-rw-r--r--modules/ri-wireguard/src/main/resources/io/trygvis/rules/wireguard/wireguard.drl185
1 files changed, 185 insertions, 0 deletions
diff --git a/modules/ri-wireguard/src/main/resources/io/trygvis/rules/wireguard/wireguard.drl b/modules/ri-wireguard/src/main/resources/io/trygvis/rules/wireguard/wireguard.drl
new file mode 100644
index 0000000..5630ab6
--- /dev/null
+++ b/modules/ri-wireguard/src/main/resources/io/trygvis/rules/wireguard/wireguard.drl
@@ -0,0 +1,185 @@
+package io.trygvis.rules.wireguard;
+
+import io.trygvis.rules.dns.DnsEntry;
+import io.trygvis.rules.machine.Machine;
+import io.trygvis.rules.network.IpCalc
+import io.trygvis.rules.network.Ipv4Address
+import io.trygvis.rules.network.Ipv4Cidr
+import java.util.ArrayList
+import java.util.List
+import java.util.Map
+
+global io.trygvis.rules.engine.TemplateEngine te;
+
+dialect "mvel"
+
+declare WgNet
+ name : String
+ domain : String
+ port : int
+ linkCidr : String
+ networkCidr : String
+ networkBits : int
+end
+
+declare WgIpPool
+ net : WgNet
+ role : String
+ cidr : Ipv4Cidr
+end
+
+declare WgHost
+ machine : Machine
+ net : WgNet
+ publicName : String
+ publicPort : int
+ ip : String // This host's IP
+ networkCidr : String
+end
+
+declare WgConnection
+ name : String
+ host : WgHost
+ to : WgHost
+end
+
+declare WgIpAllocation
+ host : WgHost
+ role : String
+ ip : Ipv4Address
+end
+
+rule "Create IP pools" when
+ $net : WgNet()
+// not(Ipv4Cidr(network == Ipv4Cidr.parseCidr($net.linkCidr).network))
+then
+ System.out.println("Creating main IP pools");
+ insert(new WgIpPool($net, "link", Ipv4Cidr.parseCidr($net.getLinkCidr())))
+ insert(new WgIpPool($net, "networks", Ipv4Cidr.parseCidr($net.getNetworkCidr())))
+end
+
+rule "WgHost VPN machines"
+when
+ $machine : Machine()
+ $wgNet : WgNet(name == "vpn0")
+ not(WgHost(machine == $machine))
+then
+ WgHost wgHost = new WgHost();
+ wgHost.machine = $machine;
+ wgHost.net = $wgNet;
+ wgHost.publicName = $machine.fqdn;
+ wgHost.publicPort = $wgNet.port;
+ insert(wgHost)
+end
+
+rule "Set public name of WgHost"
+when
+ $host : WgHost(publicName == null)
+ $m : Machine(this == $host.machine, fqdn != null)
+then
+ modify($host) {
+ publicName = $m.fqdn
+ }
+end
+
+rule "Make DNS entries for all VPN hosts"
+when
+ $h : WgHost()
+ not(DnsEntry(fqdn == "%s.%s".formatted($h.machine.name, $h.net.domain), type == "A"))
+then
+ String fqdn = "%s.%s".formatted($h.machine.name, $h.net.domain);
+ insert(DnsEntry.a(fqdn))
+end
+
+rule "Connect VPN nodes"
+ salience -1
+when
+ $h : WgHost()
+ $other : WgHost(publicName != null, this != $h)
+then
+ System.out.printf("VPN connection from %s to %s%n", $h.machine.name, $other.machine.name);
+ WgConnection c = new WgConnection();
+ c.host = $h;
+ c.to = $other;
+ insert(c)
+end
+
+rule "Name connections"
+when
+ $c : WgConnection(name == null, host != null, to != null)
+then
+ String n = $c.host.machine.name + "_x_" + $c.to.machine.name;
+ modify($c) {
+ name = n
+ }
+end
+
+// This and the next rule needs to use .toString(), the specific objects might be generated multiple times,
+// but Drools use identityHashCode() to find equal objects, not equals().
+rule "Assign IP"
+when
+ $pool : WgIpPool(role == "link")
+ $ip : Ipv4Address() from $pool.cidr.addresses()
+ not(WgHost(net == $pool.net, ip == $ip.toString()))
+ $host : WgHost(net == $pool.net, ip == null)
+then
+ System.out.printf("IP: net=%s, pool.role=%s, host=%s, ip=%s%n", $pool.net.name, $pool.role, $host.machine.name, $ip);
+ modify($host) {
+ ip = $ip.toString()
+ }
+end
+
+rule "Assign network CIDR"
+when
+ $net : WgNet()
+ $network : Ipv4Cidr() from Ipv4Cidr.parseCidr($net.networkCidr).partition($net.networkBits)
+ $host : WgHost(net == $net, networkCidr == null)
+ not(WgHost(net == $net, networkCidr == $network.toString()))
+then
+ System.out.printf("Network CIDR: net=%s, host=%s, network=%s%n", $net.name, $host.machine.name, $network);
+ modify($host) {
+ networkCidr = $network.toString()
+ }
+end
+
+rule "Generate per-net files"
+ agenda-group "generate"
+ salience 10
+when
+ $net : WgNet()
+ $hosts : ArrayList() from collect(WgHost(net == $net))
+then
+ te.template("wireguard/ansible", "wireguard-" + $net.name + ".yml", Map.of(
+ "net", $net
+ ));
+
+ List machines = new ArrayList();
+ for (Object o : $hosts) {
+ WgHost m = (WgHost) o;
+ machines.add(m.getMachine());
+ }
+
+ te.template("wireguard/inventory", "inventory.yml", Map.of(
+ "net", $net,
+ "hosts", machines
+ ));
+end
+
+rule "Generate per-net, per-host files"
+ agenda-group "generate"
+ salience 10
+when
+ $net : WgNet()
+ $host : WgHost(net == $net)
+ $peers : ArrayList() from accumulate(WgConnection(host == $host, $to: to), collectList($to))
+then
+ System.out.printf("Generating per-host files: net=%s, host=%s%n", $net.name, $host.machine.name);
+
+ String output = "host_vars/%s/wireguard.yml".formatted($host.machine.name);
+
+ te.template("wireguard/ansible-host", output, Map.of(
+ "net", $net,
+ "host", $host,
+ "peers", $peers
+ ));
+end