nixos/cryptpad: harden service

cryptpad is not directly exposed to the network, but has plenty that can
be hardened more properly, so fix that.
This commit is contained in:
Dominique Martinet 2024-07-20 20:32:31 +09:00
parent b846e8762f
commit 7c448e8d44
2 changed files with 89 additions and 8 deletions

View File

@ -141,23 +141,69 @@ in
# apparently needs proc for workers management # apparently needs proc for workers management
"/proc" "/proc"
"/dev/urandom" "/dev/urandom"
] ++ (if ! cfg.settings.blockDailyCheck then [ ];
# allow DNS & TLS if telemetry is explicitly enabled
"-/etc/resolv.conf"
"-/run/systemd"
"/etc/hosts"
"/etc/ssl/certs/ca-certificates.crt"
] else []);
DynamicUser = true; DynamicUser = true;
Environment = [ Environment = [
"CRYPTPAD_CONFIG=${cryptpadConfigFile}" "CRYPTPAD_CONFIG=${cryptpadConfigFile}"
"HOME=%S/cryptpad" "HOME=%S/cryptpad"
]; ];
ExecStart = lib.getExe cfg.package; ExecStart = lib.getExe cfg.package;
PrivateTmp = true;
Restart = "always"; Restart = "always";
StateDirectory = "cryptpad"; StateDirectory = "cryptpad";
WorkingDirectory = "%S/cryptpad"; WorkingDirectory = "%S/cryptpad";
# security way too many numerous options, from the systemd-analyze security output
# at end of test: block everything except
# - SystemCallFiters=@resources is required for node
# - MemoryDenyWriteExecute for node JIT
# - RestrictAddressFamilies=~AF_(INET|INET6) / PrivateNetwork to bind to sockets
# - IPAddressDeny likewise allow localhost if binding to localhost or any otherwise
# - PrivateUsers somehow service doesn't start with that
# - DeviceAllow (char-rtc r added by ProtectClock)
AmbientCapabilities = "";
CapabilityBoundingSet = "";
DeviceAllow = "";
LockPersonality = true;
NoNewPrivileges = true;
PrivateDevices = true;
PrivateTmp = true;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
ProtectSystem = "strict";
RemoveIPC = true;
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
RuntimeDirectoryMode = "700";
SocketBindAllow = [
"tcp:${builtins.toString cfg.settings.httpPort}"
"tcp:${builtins.toString cfg.settings.websocketPort}"
];
SocketBindDeny = [ "any" ];
StateDirectoryMode = "0700";
SystemCallArchitectures = "native";
SystemCallFilter = [
"@pkey"
"@system-service"
"~@chown"
"~@keyring"
"~@memlock"
"~@privileged"
"~@resources"
"~@setuid"
"~@timer"
];
UMask = "0077";
}; };
confinement = { confinement = {
enable = true; enable = true;
@ -166,6 +212,38 @@ in
}; };
}; };
} }
# block external network access if not phoning home and
# binding to localhost (default)
(mkIf
(
cfg.settings.blockDailyCheck
&& (builtins.elem cfg.settings.httpAddress [
"127.0.0.1"
"::1"
])
)
{
systemd.services.cryptpad = {
serviceConfig = {
IPAddressAllow = [ "localhost" ];
IPAddressDeny = [ "any" ];
};
};
}
)
# .. conversely allow DNS & TLS if telemetry is explicitly enabled
(mkIf (!cfg.settings.blockDailyCheck) {
systemd.services.cryptpad = {
serviceConfig = {
BindReadOnlyPaths = [
"-/etc/resolv.conf"
"-/run/systemd"
"/etc/hosts"
"/etc/ssl/certs/ca-certificates.crt"
];
};
};
})
(mkIf cfg.configureNginx { (mkIf cfg.configureNginx {
assertions = [ assertions = [

View File

@ -64,5 +64,8 @@ in
# test telemetry has been disabled # test telemetry has been disabled
machine.fail("journalctl -u cryptpad | grep TELEMETRY"); machine.fail("journalctl -u cryptpad | grep TELEMETRY");
# for future improvements
machine.log(machine.execute("systemd-analyze security cryptpad.service")[1])
''; '';
} }