about summary refs log tree commit diff
path: root/nixos/modules/security
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/security')
-rw-r--r--nixos/modules/security/acme/default.nix2
-rw-r--r--nixos/modules/security/ca.nix6
-rw-r--r--nixos/modules/security/ipa.nix16
-rw-r--r--nixos/modules/security/krb5/default.nix18
-rw-r--r--nixos/modules/security/krb5/krb5-conf-format.nix73
-rw-r--r--nixos/modules/security/pam.nix2
-rw-r--r--nixos/modules/security/sudo-rs.nix2
-rw-r--r--nixos/modules/security/systemd-confinement.nix36
8 files changed, 122 insertions, 33 deletions
diff --git a/nixos/modules/security/acme/default.nix b/nixos/modules/security/acme/default.nix
index 5ffafdc37fefb..83581d02840ed 100644
--- a/nixos/modules/security/acme/default.nix
+++ b/nixos/modules/security/acme/default.nix
@@ -545,7 +545,7 @@ let
       };
 
       server = mkOption {
-        type = types.str;
+        type = types.nullOr types.str;
         inherit (defaultAndText "server" "https://acme-v02.api.letsencrypt.org/directory") default defaultText;
         example = "https://acme-staging-v02.api.letsencrypt.org/directory";
         description = ''
diff --git a/nixos/modules/security/ca.nix b/nixos/modules/security/ca.nix
index af5d91b35f2eb..8aae6eb3f29b0 100644
--- a/nixos/modules/security/ca.nix
+++ b/nixos/modules/security/ca.nix
@@ -26,13 +26,13 @@ in
 
     security.pki.useCompatibleBundle = mkEnableOption ''usage of a compatibility bundle.
 
-      Such a bundle consist exclusively of `BEGIN CERTIFICATE` and no `BEGIN TRUSTED CERTIFICATE`,
-      which is a OpenSSL specific PEM format.
+      Such a bundle consists exclusively of `BEGIN CERTIFICATE` and no `BEGIN TRUSTED CERTIFICATE`,
+      which is an OpenSSL specific PEM format.
 
       It is known to be incompatible with certain software stacks.
 
       Nevertheless, enabling this will strip all additional trust rules provided by the
-      certificates themselves, this can have security consequences depending on your usecases.
+      certificates themselves. This can have security consequences depending on your usecases
     '';
 
     security.pki.certificateFiles = mkOption {
diff --git a/nixos/modules/security/ipa.nix b/nixos/modules/security/ipa.nix
index 543b1abfa672c..e746ca75724a1 100644
--- a/nixos/modules/security/ipa.nix
+++ b/nixos/modules/security/ipa.nix
@@ -85,6 +85,18 @@ in {
         description = "Whether to cache credentials.";
       };
 
+      ipaHostname = mkOption {
+        type = types.str;
+        example = "myworkstation.example.com";
+        default = if config.networking.domain != null then config.networking.fqdn
+                  else "${config.networking.hostName}.${cfg.domain}";
+        defaultText = literalExpression ''
+          if config.networking.domain != null then config.networking.fqdn
+          else "''${networking.hostName}.''${security.ipa.domain}"
+        '';
+        description = "Fully-qualified hostname used to identify this host in the IPA domain.";
+      };
+
       ifpAllowedUids = mkOption {
         type = types.listOf types.str;
         default = ["root"];
@@ -218,7 +230,7 @@ in {
 
       ipa_domain = ${cfg.domain}
       ipa_server = _srv_, ${cfg.server}
-      ipa_hostname = ${config.networking.hostName}.${cfg.domain}
+      ipa_hostname = ${cfg.ipaHostname}
 
       cache_credentials = ${pyBool cfg.cacheCredentials}
       krb5_store_password_if_offline = ${pyBool cfg.offlinePasswords}
@@ -232,7 +244,6 @@ in {
       ldap_user_extra_attrs = mail:mail, sn:sn, givenname:givenname, telephoneNumber:telephoneNumber, lock:nsaccountlock
 
       [sssd]
-      debug_level = 65510
       services = nss, sudo, pam, ssh, ifp
       domains = ${cfg.domain}
 
@@ -244,7 +255,6 @@ in {
       pam_verbosity = 3
 
       [sudo]
-      debug_level = 65510
 
       [autofs]
 
diff --git a/nixos/modules/security/krb5/default.nix b/nixos/modules/security/krb5/default.nix
index 78426c07cbc98..6714c41d8a07c 100644
--- a/nixos/modules/security/krb5/default.nix
+++ b/nixos/modules/security/krb5/default.nix
@@ -77,8 +77,22 @@ in {
     };
   };
 
-  config = mkIf cfg.enable {
-    environment = {
+  config = {
+    assertions = mkIf (cfg.enable || config.services.kerberos_server.enable) [(let
+      implementation = cfg.package.passthru.implementation or "<NOT SET>";
+    in {
+      assertion = lib.elem implementation [ "krb5" "heimdal" ];
+      message = ''
+        `security.krb5.package` must be one of:
+
+          - krb5
+          - heimdal
+
+        Currently chosen implementation: ${implementation}
+      '';
+    })];
+
+    environment = mkIf cfg.enable {
       systemPackages = [ cfg.package ];
       etc."krb5.conf".source = format.generate "krb5.conf" cfg.settings;
     };
diff --git a/nixos/modules/security/krb5/krb5-conf-format.nix b/nixos/modules/security/krb5/krb5-conf-format.nix
index 5a6bbed9fd188..3e5e64ae0cb04 100644
--- a/nixos/modules/security/krb5/krb5-conf-format.nix
+++ b/nixos/modules/security/krb5/krb5-conf-format.nix
@@ -7,17 +7,61 @@
 let
   inherit (lib) boolToString concatMapStringsSep concatStringsSep filter
     isAttrs isBool isList mapAttrsToList mkOption singleton splitString;
-  inherit (lib.types) attrsOf bool coercedTo either int listOf oneOf path
-    str submodule;
+  inherit (lib.types) attrsOf bool coercedTo either enum int listOf oneOf
+    path str submodule;
 in
-{ }: {
-  type = let
-    section = attrsOf relation;
-    relation = either (attrsOf value) value;
+{
+  enableKdcACLEntries ? false
+}: rec {
+  sectionType = let
+    relation = oneOf [
+      (listOf (attrsOf value))
+      (attrsOf value)
+      value
+    ];
     value = either (listOf atom) atom;
     atom = oneOf [int str bool];
+  in attrsOf relation;
+
+  type = let
+    aclEntry = submodule {
+      options = {
+        principal = mkOption {
+          type = str;
+          description = "Which principal the rule applies to";
+        };
+        access = mkOption {
+          type = either
+            (listOf (enum ["add" "cpw" "delete" "get" "list" "modify"]))
+            (enum ["all"]);
+          default = "all";
+          description = "The changes the principal is allowed to make.";
+        };
+        target = mkOption {
+          type = str;
+          default = "*";
+          description = "The principals that 'access' applies to.";
+        };
+      };
+    };
+
+    realm = submodule ({ name, ... }: {
+      freeformType = sectionType;
+      options = {
+        acl = mkOption {
+          type = listOf aclEntry;
+          default = [
+            { principal = "*/admin"; access = "all"; }
+            { principal = "admin"; access = "all"; }
+          ];
+          description = ''
+            The privileges granted to a user.
+          '';
+        };
+      };
+    });
   in submodule {
-    freeformType = attrsOf section;
+    freeformType = attrsOf sectionType;
     options = {
       include = mkOption {
         default = [ ];
@@ -40,7 +84,17 @@ in
         '';
         type = coercedTo path singleton (listOf path);
       };
-    };
+
+    }
+    //
+    (lib.optionalAttrs enableKdcACLEntries {
+      realms = mkOption {
+        type = attrsOf realm;
+        description = ''
+          The realm(s) to serve keys for.
+        '';
+      };
+    });
   };
 
   generate = let
@@ -71,6 +125,9 @@ in
         ${name} = {
         ${indent (concatStringsSep "\n" (mapAttrsToList formatValue relation))}
         }''
+      else if isList relation
+      then
+        concatMapStringsSep "\n" (formatRelation name) relation
       else formatValue name relation;
 
     formatValue = name: value:
diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix
index 5d3bed2fb02c8..f77e819d0c83a 100644
--- a/nixos/modules/security/pam.nix
+++ b/nixos/modules/security/pam.nix
@@ -1055,7 +1055,7 @@ in
           the dp9ik pam module provided by tlsclient.
 
           If set, users can be authenticated against the 9front
-          authentication server given in {option}`security.pam.dp9ik.authserver`.
+          authentication server given in {option}`security.pam.dp9ik.authserver`
         '';
       control = mkOption {
         default = "sufficient";
diff --git a/nixos/modules/security/sudo-rs.nix b/nixos/modules/security/sudo-rs.nix
index 6ccf42ed7f087..e63a64d4691c0 100644
--- a/nixos/modules/security/sudo-rs.nix
+++ b/nixos/modules/security/sudo-rs.nix
@@ -41,7 +41,7 @@ in
 
     enable = mkEnableOption ''
       a memory-safe implementation of the {command}`sudo` command,
-      which allows non-root users to execute commands as root.
+      which allows non-root users to execute commands as root
     '';
 
     package = mkPackageOption pkgs "sudo-rs" { };
diff --git a/nixos/modules/security/systemd-confinement.nix b/nixos/modules/security/systemd-confinement.nix
index 0304749b8d109..041c900338864 100644
--- a/nixos/modules/security/systemd-confinement.nix
+++ b/nixos/modules/security/systemd-confinement.nix
@@ -79,13 +79,20 @@ in {
         description = ''
           The value `full-apivfs` (the default) sets up
           private {file}`/dev`, {file}`/proc`,
-          {file}`/sys` and {file}`/tmp` file systems in a separate user
-          name space.
+          {file}`/sys`, {file}`/tmp` and {file}`/var/tmp` file systems
+          in a separate user name space.
 
           If this is set to `chroot-only`, only the file
           system name space is set up along with the call to
           {manpage}`chroot(2)`.
 
+          In all cases, unless `serviceConfig.PrivateTmp=true` is set,
+          both {file}`/tmp` and {file}`/var/tmp` paths are added to `InaccessiblePaths=`.
+          This is to overcome options like `DynamicUser=true`
+          implying `PrivateTmp=true` without letting it being turned off.
+          Beware however that giving processes the `CAP_SYS_ADMIN` and `@mount` privileges
+          can let them undo the effects of `InaccessiblePaths=`.
+
           ::: {.note}
           This doesn't cover network namespaces and is solely for
           file system level isolation.
@@ -98,8 +105,12 @@ in {
         wantsAPIVFS = lib.mkDefault (config.confinement.mode == "full-apivfs");
       in lib.mkIf config.confinement.enable {
         serviceConfig = {
-          RootDirectory = "/var/empty";
-          TemporaryFileSystem = "/";
+          ReadOnlyPaths = [ "+/" ];
+          RuntimeDirectory = [ "confinement/${mkPathSafeName name}" ];
+          RootDirectory = "/run/confinement/${mkPathSafeName name}";
+          InaccessiblePaths = [
+            "-+/run/confinement/${mkPathSafeName name}"
+          ];
           PrivateMounts = lib.mkDefault true;
 
           # https://github.com/NixOS/nixpkgs/issues/14645 is a future attempt
@@ -148,16 +159,6 @@ in {
               + " Please either define a separate service or find a way to run"
               + " commands other than ExecStart within the chroot.";
     }
-    { assertion = !cfg.serviceConfig.DynamicUser or false;
-      message = "${whatOpt "DynamicUser"}. Please create a dedicated user via"
-              + " the 'users.users' option instead as this combination is"
-              + " currently not supported.";
-    }
-    { assertion = cfg.serviceConfig ? ProtectSystem -> cfg.serviceConfig.ProtectSystem == false;
-      message = "${whatOpt "ProtectSystem"}. ProtectSystem is not compatible"
-              + " with service confinement as it fails to remount /usr within"
-              + " our chroot. Please disable the option.";
-    }
   ]) config.systemd.services);
 
   config.systemd.packages = lib.concatLists (lib.mapAttrsToList (name: cfg: let
@@ -183,6 +184,13 @@ in {
         echo "BindReadOnlyPaths=$realprog:/bin/sh" >> "$serviceFile"
       ''}
 
+      # If DynamicUser= is enabled, PrivateTmp=true is implied (and cannot be turned off).
+      # so disable them unless PrivateTmp=true is explicitely set.
+      ${lib.optionalString (!cfg.serviceConfig.PrivateTmp) ''
+        echo "InaccessiblePaths=-+/tmp" >> "$serviceFile"
+        echo "InaccessiblePaths=-+/var/tmp" >> "$serviceFile"
+      ''}
+
       while read storePath; do
         if [ -L "$storePath" ]; then
           # Currently, systemd can't cope with symlinks in Bind(ReadOnly)Paths,