mirror of
https://github.com/rubenhensen/k8scd.git
synced 2026-09-18 18:42:56 +02:00
Add nix-infra-machine
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
# CrowdSec HAProxy SPOA Bouncer Module
|
||||
# Provides application-layer protection via HAProxy Stream Processing Offload API
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
appName = "crowdsec";
|
||||
cfg = config.infrastructure.${appName};
|
||||
stateDir = "/var/lib/crowdsec";
|
||||
yamlFormat = pkgs.formats.yaml {};
|
||||
in
|
||||
{
|
||||
# ==========================================================================
|
||||
# Options
|
||||
# ==========================================================================
|
||||
options.infrastructure.${appName} = {
|
||||
features.haproxyProtection = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
description = ''
|
||||
Enable HAProxy security integration via SPOA (Stream Processing Offload API).
|
||||
|
||||
The cs-haproxy-spoa-bouncer acts as a stream processing agent that checks
|
||||
each connection in real-time against CrowdSec's decision database before
|
||||
allowing traffic to reach your application servers.
|
||||
|
||||
This provides layer 7 application-level protection, complementing the
|
||||
layer 3/4 protection from the firewall bouncer.
|
||||
|
||||
[NIS2 COMPLIANCE]
|
||||
Article 21(2)(d) - Network Security: Provides application-layer protection
|
||||
for HTTP/HTTPS traffic through HAProxy integration.
|
||||
|
||||
Article 21(2)(e) - Supply Chain Security: Protects web applications that
|
||||
may be part of the digital supply chain.
|
||||
'';
|
||||
default = false;
|
||||
};
|
||||
|
||||
haproxy = {
|
||||
package = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.package;
|
||||
description = ''
|
||||
CrowdSec HAProxy SPOA bouncer package to use.
|
||||
|
||||
The package should be available as pkgs.cs-haproxy-spoa-bouncer.
|
||||
Set to null to disable the bouncer even when features.haproxyProtection
|
||||
is enabled.
|
||||
'';
|
||||
default = pkgs.cs-haproxy-spoa-bouncer or null;
|
||||
defaultText = lib.literalExpression "pkgs.cs-haproxy-spoa-bouncer";
|
||||
example = lib.literalExpression "pkgs.cs-haproxy-spoa-bouncer";
|
||||
};
|
||||
|
||||
listenAddr = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
Address for the SPOA bouncer to listen on.
|
||||
HAProxy will connect to this address to check decisions.
|
||||
'';
|
||||
default = "127.0.0.1";
|
||||
example = "0.0.0.0";
|
||||
};
|
||||
|
||||
listenPort = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
description = "Port for the SPOA bouncer to listen on.";
|
||||
default = 3000;
|
||||
example = 3000;
|
||||
};
|
||||
|
||||
action = lib.mkOption {
|
||||
type = lib.types.enum [ "deny" "tarpit" ];
|
||||
description = ''
|
||||
Action to take for blocked requests in HAProxy.
|
||||
|
||||
- "deny": Immediately reject the connection
|
||||
- "tarpit": Slow down the connection (tar pit)
|
||||
'';
|
||||
default = "deny";
|
||||
};
|
||||
|
||||
logLevel = lib.mkOption {
|
||||
type = lib.types.enum [ "error" "warning" "info" "debug" ];
|
||||
description = "Log level for the SPOA bouncer.";
|
||||
default = "info";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# ==========================================================================
|
||||
# Configuration
|
||||
# ==========================================================================
|
||||
config = lib.mkIf (cfg.enable && cfg.features.haproxyProtection && cfg.haproxy.package != null) (
|
||||
let
|
||||
# HAProxy SPOA bouncer config file
|
||||
haproxyBouncerConfigFile = yamlFormat.generate "crowdsec-haproxy-spoa-bouncer.yaml" {
|
||||
lapi_url = "http://${cfg.api.listenAddr}:${toString cfg.api.listenPort}";
|
||||
lapi_key = "\${HAPROXY_SPOA_API_KEY}";
|
||||
action = cfg.haproxy.action;
|
||||
log_level = cfg.haproxy.logLevel;
|
||||
listen_addr = cfg.haproxy.listenAddr;
|
||||
listen_port = cfg.haproxy.listenPort;
|
||||
update_frequency = "10s";
|
||||
};
|
||||
|
||||
haproxyBouncerRegisterScript = pkgs.writeShellScript "crowdsec-haproxy-bouncer-register" ''
|
||||
set -e
|
||||
export PATH="${lib.makeBinPath [ cfg.package pkgs.coreutils pkgs.gnugrep pkgs.gnused ]}:$PATH"
|
||||
|
||||
CONFIG_DIR="${stateDir}/config"
|
||||
KEY_FILE="/var/lib/crowdsec-haproxy-bouncer/api_key"
|
||||
|
||||
# Wait for CrowdSec API to be ready
|
||||
for i in $(seq 1 60); do
|
||||
if cscli -c "$CONFIG_DIR/config.yaml" bouncers list >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Check if bouncer already registered
|
||||
if ! cscli -c "$CONFIG_DIR/config.yaml" bouncers list 2>/dev/null | grep -q "haproxy-spoa-bouncer"; then
|
||||
# Register new bouncer and save key
|
||||
KEY=$(cscli -c "$CONFIG_DIR/config.yaml" bouncers add haproxy-spoa-bouncer -o raw 2>/dev/null || echo "")
|
||||
if [ -n "$KEY" ]; then
|
||||
echo "$KEY" > "$KEY_FILE"
|
||||
chmod 600 "$KEY_FILE"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Read existing key
|
||||
if [ -f "$KEY_FILE" ]; then
|
||||
export HAPROXY_SPOA_API_KEY=$(cat "$KEY_FILE")
|
||||
fi
|
||||
|
||||
# Generate config with key substituted
|
||||
# Use | as sed delimiter since API keys may contain /
|
||||
if [ -n "$HAPROXY_SPOA_API_KEY" ]; then
|
||||
sed "s|\''${HAPROXY_SPOA_API_KEY}|$HAPROXY_SPOA_API_KEY|g" ${haproxyBouncerConfigFile} > /var/lib/crowdsec-haproxy-bouncer/config.yaml
|
||||
fi
|
||||
'';
|
||||
|
||||
in {
|
||||
# Assertions
|
||||
assertions = [
|
||||
{
|
||||
assertion = cfg.haproxy.package != null;
|
||||
message = ''
|
||||
CrowdSec HAProxy SPOA bouncer is enabled but no package is configured.
|
||||
|
||||
The bouncer package should be available as pkgs.cs-haproxy-spoa-bouncer.
|
||||
If the package is not available, you may need to:
|
||||
|
||||
1. Set infrastructure.crowdsec.features.haproxyProtection = false
|
||||
2. Provide the package from an external source
|
||||
'';
|
||||
}
|
||||
];
|
||||
|
||||
# Tmpfiles
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /var/lib/crowdsec-haproxy-bouncer 0750 root root - -"
|
||||
];
|
||||
|
||||
# HAProxy SPOA bouncer service
|
||||
systemd.services.crowdsec-haproxy-bouncer = {
|
||||
description = "CrowdSec HAProxy SPOA Bouncer";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" "crowdsec.service" ];
|
||||
requires = [ "crowdsec.service" ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
ExecStartPre = "${haproxyBouncerRegisterScript}";
|
||||
ExecStart = "${cfg.haproxy.package}/bin/cs-haproxy-spoa-bouncer -c /var/lib/crowdsec-haproxy-bouncer/config.yaml";
|
||||
Restart = "always";
|
||||
RestartSec = "10s";
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user