nixos/stargazer: add allowCgiUser to make cgi-user option work

Previously the cgi-user option in stargazer was broken in this module
because stargazer didn't have CAP_SETUID and CAP_SETGID. cgi-user tells
stargazer to run cgi processes as a different user. I added an option
allowCgiUser that give stargazer these capabilities when enabled. I made
this an option because access to those syscalls greatly increases the
damage a RCE bug in stargazer could do. So they should only be enabled
if needed.
This commit is contained in:
gaykitty 2024-03-10 15:08:11 -04:00
parent c3aa7b8938
commit 77430d388d
2 changed files with 47 additions and 1 deletions

View File

@ -83,6 +83,21 @@ in
''; '';
}; };
allowCgiUser = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
When enabled, the stargazer process will be given `CAP_SETGID`
and `CAP_SETUID` so that it can run cgi processes as a different
user. This is required if the `cgi-user` option is used for a route.
Note that these capabilities could allow privilege escalation so be
careful. For that reason, this is disabled by default.
You will need to create the user mentioned `cgi-user` if it does not
already exist.
'';
};
store = lib.mkOption { store = lib.mkOption {
type = lib.types.path; type = lib.types.path;
default = /var/lib/gemini/certs; default = /var/lib/gemini/certs;
@ -206,6 +221,10 @@ in
# User and group # User and group
User = cfg.user; User = cfg.user;
Group = cfg.group; Group = cfg.group;
AmbientCapabilities = lib.mkIf cfg.allowCgiUser [
"CAP_SETGID"
"CAP_SETUID"
];
}; };
}; };

View File

@ -117,16 +117,43 @@ in
}; };
}; };
}; };
cgiTestServer = { ... }: {
users.users.cgi = {
isSystemUser = true;
group = "cgi";
};
users.groups.cgi = { };
services.stargazer = {
enable = true;
connectionLogging = false;
requestTimeout = 1;
allowCgiUser = true;
routes = [
{
route = "localhost:/cgi-bin";
root = "${test_env}/test_data";
cgi = true;
cgi-timeout = 5;
cgi-user = "cgi";
}
];
};
};
}; };
testScript = { nodes, ... }: '' testScript = { nodes, ... }: ''
geminiserver.wait_for_unit("scgi_server") geminiserver.wait_for_unit("scgi_server")
geminiserver.wait_for_open_port(1099) geminiserver.wait_for_open_port(1099)
geminiserver.wait_for_unit("stargazer") geminiserver.wait_for_unit("stargazer")
geminiserver.wait_for_open_port(1965) geminiserver.wait_for_unit("stargazer")
cgiTestServer.wait_for_open_port(1965)
cgiTestServer.wait_for_open_port(1965)
with subtest("stargazer test suite"): with subtest("stargazer test suite"):
response = geminiserver.succeed("sh -c 'cd ${test_env}; ${test_script}/bin/test'") response = geminiserver.succeed("sh -c 'cd ${test_env}; ${test_script}/bin/test'")
print(response) print(response)
with subtest("stargazer cgi-user test"):
response = cgiTestServer.succeed("sh -c 'cd ${test_env}; ${test_script}/bin/test --checks CGIVars'")
print(response)
''; '';
} }