Skip to content

Commit

Permalink
nixos/web-servers: assert ACME cert access via service user and groups
Browse files Browse the repository at this point in the history
Allows giving access using SupplementaryGroups.
  • Loading branch information
ThinkChaos committed Nov 3, 2024
1 parent a4abee1 commit ecb28d1
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 11 deletions.
23 changes: 20 additions & 3 deletions nixos/modules/security/acme/mk-cert-ownership-assertion.nix
Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
{ cert, group, groups, user }: {
assertion = cert.group == group || builtins.any (u: u == user) groups.${cert.group}.members;
message = "Group for certificate ${cert.domain} must be ${group}, or user ${user} must be a member of group ${cert.group}";
lib:

{ cert, groups, services }:
let
catSep = builtins.concatStringsSep;

svcGroups = svc:
(lib.optional (svc.serviceConfig ? Group) svc.serviceConfig.Group)
++ (svc.serviceConfig.SupplementaryGroups or [ ]);
in
{
assertion = builtins.all (svc:
svc.serviceConfig.User or "root" == "root"
|| builtins.elem svc.serviceConfig.User groups.${cert.group}.members
|| builtins.elem cert.group (svcGroups svc)
) services;

message = "Certificate ${cert.domain} (group=${cert.group}) must be readable by service(s) ${
catSep ", " (map (svc: "${svc.name} (user=${svc.serviceConfig.User} groups=${catSep " " (svcGroups svc)})") services)
}";
}
6 changes: 3 additions & 3 deletions nixos/modules/services/web-servers/apache-httpd/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ let
echo "$options" >> $out
'';

mkCertOwnershipAssertion = import ../../../security/acme/mk-cert-ownership-assertion.nix;
mkCertOwnershipAssertion = import ../../../security/acme/mk-cert-ownership-assertion.nix lib;
in


Expand Down Expand Up @@ -642,9 +642,9 @@ in
'';
}
] ++ map (name: mkCertOwnershipAssertion {
inherit (cfg) group user;
cert = config.security.acme.certs.${name};
groups = config.users.groups;
services = [ config.systemd.services.httpd ] ++ lib.optional (vhostCertNames != []) config.systemd.services.httpd-config-reload;
}) vhostCertNames;

warnings =
Expand Down Expand Up @@ -792,7 +792,7 @@ in
systemd.services.httpd-config-reload = let
sslServices = map (certName: "acme-${certName}.service") vhostCertNames;
sslTargets = map (certName: "acme-finished-${certName}.target") vhostCertNames;
in mkIf (sslServices != []) {
in mkIf (vhostCertNames != []) {
wantedBy = sslServices ++ [ "multi-user.target" ];
# Before the finished targets, after the renew services.
# This service might be needed for HTTP-01 challenges, but we only want to confirm
Expand Down
4 changes: 2 additions & 2 deletions nixos/modules/services/web-servers/caddy/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ let

configPath = "/etc/${etcConfigFile}";

mkCertOwnershipAssertion = import ../../../security/acme/mk-cert-ownership-assertion.nix;
mkCertOwnershipAssertion = import ../../../security/acme/mk-cert-ownership-assertion.nix lib;
in
{
imports = [
Expand Down Expand Up @@ -330,9 +330,9 @@ in
message = "To specify an adapter other than 'caddyfile' please provide your own configuration via `services.caddy.configFile`";
}
] ++ map (name: mkCertOwnershipAssertion {
inherit (cfg) group user;
cert = config.security.acme.certs.${name};
groups = config.users.groups;
services = [ config.systemd.services.caddy ];
}) vhostCertNames;

services.caddy.globalConfig = ''
Expand Down
6 changes: 3 additions & 3 deletions nixos/modules/services/web-servers/nginx/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ let
'') authDef)
);

mkCertOwnershipAssertion = import ../../../security/acme/mk-cert-ownership-assertion.nix;
mkCertOwnershipAssertion = import ../../../security/acme/mk-cert-ownership-assertion.nix lib;

oldHTTP2 = (versionOlder cfg.package.version "1.25.1" && !(cfg.package.pname == "angie" || cfg.package.pname == "angieQuic"));
in
Expand Down Expand Up @@ -1210,9 +1210,9 @@ in
'';
}
] ++ map (name: mkCertOwnershipAssertion {
inherit (cfg) group user;
cert = config.security.acme.certs.${name};
groups = config.users.groups;
services = [ config.systemd.services.nginx ] ++ lib.optional (cfg.enableReload || vhostCertNames != []) config.systemd.services.nginx-config-reload;
}) vhostCertNames;

services.nginx.additionalModules = optional cfg.recommendedBrotliSettings pkgs.nginxModules.brotli
Expand Down Expand Up @@ -1319,7 +1319,7 @@ in
systemd.services.nginx-config-reload = let
sslServices = map (certName: "acme-${certName}.service") vhostCertNames;
sslTargets = map (certName: "acme-finished-${certName}.target") vhostCertNames;
in mkIf (cfg.enableReload || sslServices != []) {
in mkIf (cfg.enableReload || vhostCertNames != []) {
wants = optionals cfg.enableReload [ "nginx.service" ];
wantedBy = sslServices ++ [ "multi-user.target" ];
# Before the finished targets, after the renew services.
Expand Down

0 comments on commit ecb28d1

Please sign in to comment.