cluster/simulacrum: implement nowhere, fix networking

This commit is contained in:
Max Headroom 2024-08-10 13:37:14 +02:00
parent 3ca573f79a
commit a19f0871f4
3 changed files with 131 additions and 3 deletions

View file

@ -17,7 +17,8 @@ let
};
nodes = lib.attrNames config.gods.fromLight;
digits = lib.attrsets.listToAttrs (lib.zipListsWith lib.nameValuePair nodes (lib.range 1 255));
nodes' = lib.attrNames (config.gods.fromLight // { nowhere = null; });
digits = lib.attrsets.listToAttrs (lib.zipListsWith lib.nameValuePair nodes' (lib.range 1 255));
depot' = extendModules {
modules = [
({ config, ... }: {
@ -51,6 +52,12 @@ testers.runNixOSTest {
imports = [
serviceConfig.simulacrum.settings
./nowhere
{
nodes.nowhere.imports = [
config.flake.nixosModules.port-magic
];
}
] ++ allAugments;
_module.args = {
@ -73,12 +80,15 @@ testers.runNixOSTest {
${hour.interfaces.primary.link} = {
useDHCP = lib.mkForce false;
virtual = true;
ipv4.addresses = lib.mkForce [
ipv4.addresses = lib.mkForce ([
{
address = hour.interfaces.primary.addr;
prefixLength = 32;
}
];
] ++ lib.optional hour.interfaces.primary.isNat {
address = hour.interfaces.primary.addrPublic;
prefixLength = 32;
});
};
eth1.ipv4.routes = lib.pipe nodes [
(lib.filter (n: n != node))
@ -95,6 +105,7 @@ testers.runNixOSTest {
firewall.extraCommands = lib.mkAfter (lib.optionalString (hour.interfaces.primary.isNat) ''
# self-nat
iptables -t nat -A PREROUTING -d ${hour.interfaces.primary.addrPublic} -j DNAT --to-destination ${hour.interfaces.primary.addr}
iptables -t nat -A OUTPUT -d ${hour.interfaces.primary.addrPublic} -j DNAT --to-destination ${hour.interfaces.primary.addr}
iptables -t nat -A POSTROUTING -s ${hour.interfaces.primary.addr} -j SNAT --to-source ${hour.interfaces.primary.addrPublic}
'');
};

View file

@ -0,0 +1,101 @@
{ cluster, config, lib, pkgs, ... }:
let
lift = config;
cfsslConfigIntermediateCA = pkgs.writeText "simulacrum-cfssl-config.json" (builtins.toJSON {
signing = {
default.expiry = "8760h";
profiles.intermediate = {
expiry = "8760h";
usages = [
"cert sign"
"crl sign"
];
ca_constraint = {
is_ca = true;
max_path_len = 1;
};
};
};
});
caCsr = pkgs.writeText "simulacrum-ca-csr.json" (builtins.toJSON {
CN = "Simulacrum Root CA";
});
ca = pkgs.runCommand "simulacrum-snakeoil-ca" {
nativeBuildInputs = [
pkgs.cfssl
];
} ''
mkdir $out
cfssl gencert --initca ${caCsr} | cfssljson --bare $out/ca
'';
genCert = extraFlags: csrData: let
csr = pkgs.writeText "simulacrum-csr.json" (builtins.toJSON csrData);
in pkgs.runCommand "simulacrum-snakeoil-cert" {
nativeBuildInputs = [
pkgs.cfssl
];
} ''
mkdir $out
cfssl gencert ${lib.escapeShellArgs ([
"--ca=file:${ca}/ca.pem"
"--ca-key=file:${ca}/ca-key.pem"
] ++ extraFlags ++ [
csr
])} | cfssljson --bare $out/cert
'';
genHostCert = hostname: genCert [ "--hostname=${hostname}" ] { CN = hostname; };
getNodeAddr = node: (builtins.head config.nodes.${node}.networking.interfaces.eth1.ipv4.addresses).address;
in
{
imports = [
./options.nix
];
defaults = {
networking.hosts."${getNodeAddr "nowhere"}" = lib.attrNames config.nowhere.names;
security.pki.certificateFiles = [
"${ca}/ca.pem"
];
};
nowhere.certs = {
inherit ca;
intermediate = genCert [ "--config=${cfsslConfigIntermediateCA}" "--profile=intermediate" ] {
CN = "Simulacrum Intermediate CA";
};
};
nodes.nowhere = { config, depot, ... }: {
networking = {
firewall.allowedTCPPorts = [ 443 ];
interfaces.eth1.ipv4.routes = lib.mapAttrsToList (name: hour: {
address = hour.interfaces.primary.addrPublic;
prefixLength = 32;
via = getNodeAddr name;
}) depot.gods.fromLight;
nameservers = map (name: depot.hours.${name}.interfaces.primary.addrPublic) cluster.config.services.dns.nodes.authoritative;
};
services.nginx = {
enable = true;
recommendedProxySettings = true;
virtualHosts = lib.mapAttrs (name: link: let
cert = genHostCert name;
in {
forceSSL = true;
sslCertificate = "${cert}/cert.pem";
sslCertificateKey = "${cert}/cert-key.pem";
locations."/" = {
proxyPass = config.links.${link}.url;
extraConfig = "proxy_ssl_verify off;";
};
}) lift.nowhere.names;
};
};
}

View file

@ -0,0 +1,16 @@
{ lib, ... }:
{
options.nowhere = {
names = lib.mkOption {
description = "Hostnames that point Nowhere.";
type = with lib.types; attrsOf str;
default = {};
};
certs = lib.mkOption {
description = "Snakeoil certificate packages.";
type = with lib.types; attrsOf package;
default = {};
};
};
}