nixos modules for convenient deployment of cloud resources

refactor: split code, add test for hetzner firewall app

ptr.pet 4ef813c9 fde701d9

verified
Changed files
+77 -38
firewall
provider
+12
firewall/provider/hetzner/app.nix
···
···
+
{pkgs, lib ? pkgs.lib, taggedPorts, id}: let
+
l = lib // (import ./rules.nix {inherit lib;});
+
+
firewallRules =
+
builtins.toFile
+
"hetzner-firewall-${toString id}-rules.json"
+
(builtins.toJSON (l.mkFirewallRuleset taggedPorts));
+
in pkgs.writers.writeNu "apply-hetzner" ''
+
let firewallId = ${toString id}
+
let rulesFile = "${firewallRules}"
+
${l.fileContents ./app.nu}
+
''
+9 -35
firewall/provider/hetzner/default.nix
···
-
{pkgs, lib, config, options, ...}: let
l = lib;
t = l.types;
taggedPorts = config.networking.firewall.public;
···
type = t.ints.unsigned;
description = "The ID of the firewall to update.";
};
-
app = l.mkOption {
-
type = t.package;
readOnly = true;
description = ''
-
The generated app for this provider, run it to apply the configuration.
-
For this to work, you need to set the `HETZNER_API_TOKEN` environment variable to a valid API token from Hetzner.
'';
};
};
};
-
config = let
-
mkRule = proto: tag: port: {
-
description = tag;
-
direction = "in";
-
protocol = proto;
-
port =
-
if l.isAttrs port
-
then l.concatMapStringsSep "-" toString [port.from port.to]
-
else toString port;
-
source_ips = ["0.0.0.0/0" "::/0"];
-
};
-
mkTcpRule = mkRule "tcp";
-
mkUdpRule = mkRule "udp";
-
firewallRules = pkgs.writers.writeJSON "hetzner-firewall-${toString cfg.id}-rules.json" {
-
rules = l.flatten (
-
l.mapAttrsToList
-
(tag: ports: [
-
(l.map (mkTcpRule tag) ports.allowedTCPPorts)
-
(l.map (mkTcpRule tag) ports.allowedTCPPortRanges)
-
(l.map (mkUdpRule tag) ports.allowedUDPPorts)
-
(l.map (mkUdpRule tag) ports.allowedUDPPortRanges)
-
])
-
taggedPorts
-
);
};
-
in {
-
providers.hetzner.firewall.app = pkgs.writers.writeNu "apply-hetzner" ''
-
let firewallId = ${toString cfg.id}
-
let rulesFile = "${firewallRules}"
-
${l.fileContents ./app.nu}
-
'';
};
}
···
+
{lib, config, ...}: let
l = lib;
t = l.types;
taggedPorts = config.networking.firewall.public;
···
type = t.ints.unsigned;
description = "The ID of the firewall to update.";
};
+
mkApp = l.mkOption {
+
type = t.functionTo t.package;
readOnly = true;
description = ''
+
Function that generates a script for this provider, pass it an instance of nixpkgs and run to apply the configuration.
+
For this app to work, you need to set the `HETZNER_API_TOKEN` environment variable to a valid API token from Hetzner.
'';
};
};
};
+
config = {
+
providers.hetzner.firewall.mkApp = pkgs: import ./app.nix {
+
inherit pkgs lib taggedPorts;
+
inherit (cfg) id;
};
};
}
+29
firewall/provider/hetzner/rules.nix
···
···
+
{lib}: let
+
l = lib;
+
mkRule = proto: tag: port: {
+
description = tag;
+
direction = "in";
+
protocol = proto;
+
port =
+
if l.isAttrs port
+
then l.concatMapStringsSep "-" toString [port.from port.to]
+
else toString port;
+
source_ips = ["0.0.0.0/0" "::/0"];
+
};
+
in rec {
+
mkTcpRule = mkRule "tcp";
+
mkUdpRule = mkRule "udp";
+
# taggedPorts: attrset of {allowedTCPPorts, allowedTCPPortRanges, ...}
+
mkFirewallRuleset = taggedPorts: {
+
rules = l.flatten (
+
l.mapAttrsToList
+
(tag: ports: [
+
(l.map (mkTcpRule tag) (ports.allowedTCPPorts or []))
+
(l.map (mkTcpRule tag) (ports.allowedTCPPortRanges or []))
+
(l.map (mkUdpRule tag) (ports.allowedUDPPorts or []))
+
(l.map (mkUdpRule tag) (ports.allowedUDPPortRanges or []))
+
])
+
taggedPorts
+
);
+
};
+
}
+27 -3
flake.nix
···
inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
-
outputs = inp: {
nixosModules = {
-
firewall = ./firewall/default.nix;
-
firewall-hetzner = ./firewall/provider/hetzner/default.nix;
};
};
}
···
inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
+
outputs = inp: let
+
l = inp.nixpkgs.lib;
+
pkgsInstances =
+
l.genAttrs
+
["x86_64-linux"]
+
(s: inp.nixpkgs.legacyPackages.${s});
+
in {
nixosModules = {
+
firewall = ./firewall;
+
firewall-hetzner = ./firewall/provider/hetzner;
};
+
checks =
+
l.mapAttrs
+
(_: pkgs: {
+
firewall-hetzner-app = import ./firewall/provider/hetzner/app.nix {
+
inherit pkgs;
+
taggedPorts = {
+
http.allowedTCPPorts = [80 443];
+
ssh.allowedTCPPorts = [22];
+
"bla bla" = {
+
allowedUDPPortRanges = [{from = 1332; to = 8891;}];
+
allowedTCPPorts = [101];
+
allowedUDPPorts = [102];
+
};
+
};
+
id = 1;
+
};
+
})
+
pkgsInstances;
};
}