go-csp-collector: init at 0.0.16-unstable-2025-10-10 (#455610)

This commit is contained in:
Sandro
2025-11-02 22:10:10 +00:00
committed by GitHub
5 changed files with 227 additions and 0 deletions
+1
View File
@@ -992,6 +992,7 @@
./services/monitoring/gitwatch.nix
./services/monitoring/glances.nix
./services/monitoring/glpi-agent.nix
./services/monitoring/go-csp-collector.nix
./services/monitoring/goss.nix
./services/monitoring/grafana-image-renderer.nix
./services/monitoring/grafana-reporter.nix
@@ -0,0 +1,106 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.go-csp-collector;
inherit (lib)
boolToString
concatStringsSep
getExe
isBool
literalExpression
maintainers
mapAttrsToList
mkEnableOption
mkIf
mkOption
mkPackageOption
types
;
settingsToArgs =
settings:
concatStringsSep " " (
mapAttrsToList (
name: value:
let
flag = "-${name}";
in
if isBool value then "${flag}=${boolToString value}" else "${flag} ${toString value}"
) settings
);
in
{
meta.maintainers = with maintainers; [ stepbrobd ];
options.services.go-csp-collector = {
enable = mkEnableOption "go-csp-collector, a content security policy violation collector";
package = mkPackageOption pkgs "go-csp-collector" { };
settings = mkOption {
type = types.submodule {
freeformType =
with types;
attrsOf (oneOf [
bool
path
str
]);
options = {
port = mkOption {
type = types.port;
description = "The port to listen on.";
default = 8080;
example = 8080;
};
output-format = mkOption {
type = types.enum [
"text"
"json"
];
description = "Define how the violation reports are formatted for output.";
default = "text";
example = "text";
};
};
};
description = ''
Settings for go-csp-collector. See
<https://github.com/jacobbednarz/go-csp-collector> for supported options.
'';
default = { };
example = literalExpression ''
{
debug = true;
health-check-path = "/health";
}
'';
};
};
config = mkIf cfg.enable {
systemd.packages = [ cfg.package ];
systemd.services.go-csp-collector = {
description = "CSP violation collector";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
ReadOnlyPaths = cfg.settings.filter-file or "";
ExecStart = [
""
"${getExe cfg.package} ${settingsToArgs cfg.settings}"
];
};
};
};
}
+1
View File
@@ -646,6 +646,7 @@ in
gns3-server = runTest ./gns3-server.nix;
gnupg = runTest ./gnupg.nix;
go-camo = runTest ./go-camo.nix;
go-csp-collector = runTest ./go-csp-collector.nix;
go-httpbin = runTest ./go-httpbin.nix;
go-neb = runTest ./go-neb.nix;
goatcounter = runTest ./goatcounter.nix;
+66
View File
@@ -0,0 +1,66 @@
{ lib, ... }:
{
name = "go-csp-collector";
meta.maintainers = with lib.maintainers; [ stepbrobd ];
nodes.machine =
{ pkgs, ... }:
{
services.go-csp-collector = {
enable = true;
settings = {
debug = true;
port = 9999;
health-check-path = "/health";
filter-file = pkgs.writeText "filter" "chrome-extension://";
};
};
};
testScript = ''
import json
# health check
machine.wait_for_unit("go-csp-collector.service")
machine.wait_for_open_port(9999)
machine.succeed("curl -f http://localhost:9999/health")
# send valid csp report
machine.succeed(
"curl -f -X POST http://127.0.0.1:9999/ "
"-H 'Content-Type: application/csp-report' "
"-d '" + json.dumps({
"csp-report": {
"document-uri": "https://example.com/",
"referrer": "https://example.com/",
"violated-directive": "script-src",
"effective-directive": "script-src",
"original-policy": "script-src 'self'",
"blocked-uri": "https://example.org/malicious.js",
"status-code": 200
}
}) + "'"
)
logs = machine.succeed("journalctl -u go-csp-collector.service")
assert "level=debug" in logs, "debug mode not enabled"
assert "blocked_uri" in logs, "csp report not logged"
assert "https://example.org/malicious.js" in logs, "blocked uri not in logs"
# check rejection
machine.fail(
"curl -f -X POST http://[::1]:9999/ "
"-H 'Content-Type: application/csp-report' "
"-d '" + json.dumps({
"csp-report": {
"document-uri": "https://example.com/",
"blocked-uri": "chrome-extension://something",
"violated-directive": "script-src"
}
}) + "'"
)
logs = machine.succeed("journalctl -u go-csp-collector.service")
assert "invalid resource" in logs, "filter rejection not logged"
assert "chrome-extension://" in logs, "filtered uri pattern not in logs"
'';
}
@@ -0,0 +1,53 @@
{
lib,
buildGoModule,
fetchFromGitHub,
versionCheckHook,
nix-update-script,
nixosTests,
}:
buildGoModule (finalAttrs: {
pname = "go-csp-collector";
version = "0.0.16-unstable-2025-10-10";
src = fetchFromGitHub {
owner = "jacobbednarz";
repo = "go-csp-collector";
rev = "a0cf22ac6d1f5c8972bf53671ba174767d2adcd5";
hash = "sha256-xFvO8ZuJQ5luCDOTPHtVeb1+3VvIKSwjt2TqkxBIY58=";
};
vendorHash = "sha256-SrQahSHO5ZIkcLR3BR5CR5BTStW1pH1Ij1Eql0b3tuU=";
ldflags = [
"-s"
"-w"
"-X main.Rev=${finalAttrs.version}"
];
postInstall = ''
install -Dm644 init/go-csp-collector.service $out/lib/systemd/system/go-csp-collector.service
substituteInPlace $out/lib/systemd/system/go-csp-collector.service \
--replace-fail "/usr/local/bin/go-csp-collector" "$out/bin/go-csp-collector"
'';
doInstallCheck = true;
nativeInstallCheckInputs = [ versionCheckHook ];
versionCheckProgramArg = "-version";
passthru = {
updateScript = nix-update-script { };
tests.service = nixosTests.go-csp-collector;
};
meta = {
description = "A content security policy violation collector written in Golang";
homepage = "https://github.com/jacobbednarz/go-csp-collector";
changelog = "https://github.com/jacobbednarz/go-csp-collector/blob/${finalAttrs.src.rev}/CHANGELOG.md";
license = lib.licenses.mit;
mainProgram = "go-csp-collector";
maintainers = with lib.maintainers; [ stepbrobd ];
};
})