Compare commits

..

2 commits

13 changed files with 293 additions and 14 deletions

View file

@ -1,7 +1,8 @@
{ pkgs, ... }:
{
services.crowdsec = {
security.crowdsec = {
enable = true;
remediationComponents.firewallBouncer.enable = true;
parserWhitelist = [
"1.64.239.213"
@ -17,7 +18,7 @@
---
source: journalctl
journalctl_filter:
- "SYSLOG_IDENTIFIER=sshd-service"
- "SYSLOG_IDENTIFIER=sshd-session"
labels:
type: syslog
---

View file

@ -100,10 +100,16 @@
# Garbage collection root #
###########################
packages.${system} = {
default = vm.config.system.build.vm;
crowdsec = pkgs.callPackage "${inputs.nixpkgs-crowdsec}/pkgs/by-name/cr/crowdsec/package.nix" { };
};
packages.${system} =
let
localPkgs = import ./pkgs { inherit pkgs; };
in
{
default = vm.config.system.build.vm;
crowdsec = pkgs.callPackage "${inputs.nixpkgs-crowdsec}/pkgs/by-name/cr/crowdsec/package.nix" { };
crowdsec-hub = localPkgs.crowdsec.hub;
crowdsec-firewall-bouncer = localPkgs.crowdsec.firewall-bouncer;
};
###################
# Utility scripts #
@ -120,6 +126,22 @@
${vm.config.system.build.vm.outPath}/bin/run-testvm-vm
'').outPath;
};
update-crowdsec-packages =
let
git = pkgs.lib.getExe pkgs.git;
nvfetcher = pkgs.lib.getExe pkgs.nvfetcher;
in
{
type = "app";
program =
(pkgs.writeShellScript "update-crowdsec-packages" ''
cd "$(${git} rev-parse --show-toplevel)"
cd ./pkgs/crowdsec
${nvfetcher}
echo 'Remember to update the vendorHash of any go packages!'
'').outPath;
};
};
###########################

View file

@ -6,7 +6,7 @@
...
}:
let
cfg = config.services.crowdsec;
cfg = config.security.crowdsec;
settingsFormat = pkgs.formats.yaml { };
crowdsec = flake-inputs.self.packages.${pkgs.system}.crowdsec;
@ -31,7 +31,9 @@ let
'';
in
{
options.services.crowdsec =
imports = [ ./remediations ];
options.security.crowdsec =
let
inherit (lib.types)
nullOr
@ -81,6 +83,50 @@ in
'';
};
hubConfigurations = {
collections = lib.mkOption {
type = listOf str;
description = ''
List of pre-made crowdsec collections to install.
'';
};
scenarios = lib.mkOption {
type = listOf str;
description = ''
List of pre-made crowdsec scenarios to install.
'';
};
parsers = lib.mkOption {
type = listOf str;
description = ''
List of pre-made crowdsec parsers to install.
'';
};
postoverflows = lib.mkOption {
type = listOf str;
description = ''
List of pre-made crowdsec postoverflows to install.
'';
};
appsecConfigs = lib.mkOption {
type = listOf str;
description = ''
List of pre-made crowdsec appsec configurations to install.
'';
};
appsecRules = lib.mkOption {
type = listOf str;
description = ''
List of pre-made crowdsec appsec rules to install.
'';
};
};
centralApiCredentials = lib.mkOption {
type = nullOr path;
default = null;
@ -115,7 +161,7 @@ in
# Set up default settings; anything that *shouldn't* be changed is
# set to the default priority so that users need to use
# `lib.mkForce`.
services.crowdsec = {
security.crowdsec = {
stateDirectory = "/var/lib/crowdsec";
settings = {
@ -278,6 +324,8 @@ in
# Note that the service basics are already defined upstream
crowdsec = {
enable = true;
after = [ "crowdsec-setup.service" ];
bindsTo = [ "crowdsec-setup.service" ];

View file

@ -0,0 +1,90 @@
{
flake-inputs,
pkgs,
lib,
config,
...
}:
let
crowdsecCfg = config.security.crowdsec;
cfg = crowdsecCfg.remediationComponents.firewallBouncer;
settingsFormat = pkgs.formats.yaml { };
crowdsec-firewall-bouncer = flake-inputs.self.packages.${pkgs.system}.crowdsec-firewall-bouncer;
in
{
options.security.crowdsec.remediationComponents.firewallBouncer = {
enable = lib.mkEnableOption "cs-firewall-bouncer";
settings = lib.mkOption {
inherit (settingsFormat) type;
default = { };
description = ''
The bouncer configuration. Refer to
<https://docs.crowdsec.net/u/bouncers/firewall/> for details
on supported values.
'';
};
};
config = lib.mkIf cfg.enable {
security.crowdsec.remediationComponents.firewallBouncer.settings = {
mode = lib.mkDefault "${if config.networking.nftables.enable then "nftables" else "iptables"}";
log_mode = "stdout";
iptables_chains = [
"nixos-fw"
];
# Don't let users easily override this; unfortunately we need to
# set up this key through substitution at runtime.
api_key = lib.mkForce "\${API_KEY}";
api_url = lib.mkDefault "http://${crowdsecCfg.settings.api.server.listen_uri}";
};
systemd = {
packages = [ crowdsec-firewall-bouncer ];
services = {
crowdsec-firewall-bouncer-setup = {
description = "Crowdsec firewall bouncer config preparation";
script = ''
if [ ! -e '${crowdsecCfg.stateDirectory}/firewall_bouncer_credentials.yaml' ]; then
${crowdsecCfg.package}/bin/cscli -oraw bouncers add "cs-firewall-bouncer-$(${pkgs.coreutils}/bin/date +%s)" > \
${crowdsecCfg.stateDirectory}/firewall_bouncer_credentials.yaml
fi
# Stdout redirection is deliberately used to forcibly
# overwrite the file if it exists
API_KEY="$(<${crowdsecCfg.stateDirectory}/firewall_bouncer_credentials.yaml)" \
${lib.getExe pkgs.envsubst} \
-i ${settingsFormat.generate "crowdsec-firewall-bouncer.yaml" cfg.settings} \
> /var/lib/crowdsec/config/crowdsec-firewall-bouncer.yaml
'';
serviceConfig = {
User = "crowdsec";
Group = "crowdsec";
Type = "oneshot";
RemainAfterExit = true;
};
};
crowdsec-firewall-bouncer = {
enable = true;
after = [ "crowdsec-firewall-bouncer-setup.service" ];
bindsTo = [ "crowdsec-firewall-bouncer-setup.service" ];
partOf = [ "crowdsec.service" ];
path =
lib.optionals (cfg.settings.mode == "ipset" || cfg.settings.mode == "iptables") [
pkgs.ipset
]
++ lib.optional (cfg.settings.mode == "iptables") pkgs.iptables
++ lib.optional (cfg.settings.mode == "nftables") pkgs.nftables;
};
};
};
};
}

View file

@ -0,0 +1,5 @@
{
imports = [
./cs-firewall-bouncer.nix
];
}

View file

@ -1,6 +1,6 @@
{
imports = [
./crowdsec.nix
./crowdsec
./nginxExtensions.nix
];
}

View file

@ -0,0 +1,42 @@
{
"crowdsec-firewall-bouncer": {
"cargoLocks": null,
"date": null,
"extract": null,
"name": "crowdsec-firewall-bouncer",
"passthru": null,
"pinned": false,
"src": {
"deepClone": false,
"fetchSubmodules": false,
"leaveDotGit": false,
"name": null,
"owner": "crowdsecurity",
"repo": "cs-firewall-bouncer",
"rev": "v0.0.31",
"sha256": "sha256-59MWll8v00CF4WA53gjHZSTFc8hpYaHENg9O7LgTCrA=",
"type": "github"
},
"version": "v0.0.31"
},
"crowdsec-hub": {
"cargoLocks": null,
"date": "2025-01-30",
"extract": null,
"name": "crowdsec-hub",
"passthru": null,
"pinned": false,
"src": {
"deepClone": false,
"fetchSubmodules": false,
"leaveDotGit": false,
"name": null,
"owner": "crowdsecurity",
"repo": "hub",
"rev": "8f102f5ac79af59d3024ca2771b65ec87411ac02",
"sha256": "sha256-8K1HkBg0++Au1dr2KMrl9b2ruqXdo+vqWngOCwL11Mo=",
"type": "github"
},
"version": "8f102f5ac79af59d3024ca2771b65ec87411ac02"
}
}

View file

@ -0,0 +1,27 @@
# This file was generated by nvfetcher, please do not modify it manually.
{ fetchgit, fetchurl, fetchFromGitHub, dockerTools }:
{
crowdsec-firewall-bouncer = {
pname = "crowdsec-firewall-bouncer";
version = "v0.0.31";
src = fetchFromGitHub {
owner = "crowdsecurity";
repo = "cs-firewall-bouncer";
rev = "v0.0.31";
fetchSubmodules = false;
sha256 = "sha256-59MWll8v00CF4WA53gjHZSTFc8hpYaHENg9O7LgTCrA=";
};
};
crowdsec-hub = {
pname = "crowdsec-hub";
version = "8f102f5ac79af59d3024ca2771b65ec87411ac02";
src = fetchFromGitHub {
owner = "crowdsecurity";
repo = "hub";
rev = "8f102f5ac79af59d3024ca2771b65ec87411ac02";
fetchSubmodules = false;
sha256 = "sha256-8K1HkBg0++Au1dr2KMrl9b2ruqXdo+vqWngOCwL11Mo=";
};
date = "2025-01-30";
};
}

View file

@ -0,0 +1,9 @@
{ pkgs }:
let
sources = pkgs.callPackage ./_sources/generated.nix { };
callPackage = pkgs.lib.callPackageWith (pkgs // { inherit sources; });
in
{
hub = callPackage ./hub.nix { };
firewall-bouncer = callPackage ./firewall-bouncer.nix { };
}

View file

@ -0,0 +1,26 @@
{
lib,
sources,
buildGoModule,
envsubst,
coreutils,
}:
let
envsubstBin = lib.getExe envsubst;
in
buildGoModule {
inherit (sources.crowdsec-firewall-bouncer) pname version src;
vendorHash = "sha256-7Jxvg8UEjUxnIz1llvXyI2AefJ31OVdNzhWD/C8wU/Y=";
postInstall = ''
mkdir -p $out/lib/systemd/system
CFG=/var/lib/crowdsec/config BIN=$out/bin/cs-firewall-bouncer ${envsubstBin} \
-i ./config/crowdsec-firewall-bouncer.service \
-o $out/lib/systemd/system/crowdsec-firewall-bouncer.service
substituteInPlace $out/lib/systemd/system/crowdsec-firewall-bouncer.service \
--replace-fail /bin/sleep ${coreutils}/bin/sleep
'';
}

4
pkgs/crowdsec/hub.nix Normal file
View file

@ -0,0 +1,4 @@
{
sources,
}:
sources.crowdsec-hub.src

View file

@ -0,0 +1,7 @@
[crowdsec-hub]
src.git = "https://github.com/crowdsecurity/hub.git"
fetch.github = "crowdsecurity/hub"
[crowdsec-firewall-bouncer]
src.github = "crowdsecurity/cs-firewall-bouncer"
fetch.github = "crowdsecurity/cs-firewall-bouncer"

View file

@ -1,7 +1,5 @@
{ pkgs }:
let
inherit (pkgs) callPackage;
in
{
starbound = callPackage ./starbound { };
crowdsec = import ./crowdsec { inherit pkgs; };
starbound = pkgs.callPackage ./starbound { };
}