Skip to content

Commit

Permalink
Merge pull request #1344 from Mic92/fix_pam_module
Browse files Browse the repository at this point in the history
fix: move `pam` configuration to `sudo_local`
  • Loading branch information
Enzime authored Feb 25, 2025
2 parents 59efa72 + 11ea44f commit 42be12b
Showing 1 changed file with 76 additions and 51 deletions.
127 changes: 76 additions & 51 deletions modules/security/pam.nix
Original file line number Diff line number Diff line change
@@ -1,69 +1,94 @@
{ config, lib, pkgs, ... }:

with lib;

let
cfg = config.security.pam;

# Implementation Notes
#
# We don't use `environment.etc` because this would require that the user manually delete
# `/etc/pam.d/sudo` which seems unwise given that applying the nix-darwin configuration requires
# sudo. We also can't use `system.patchs` since it only runs once, and so won't patch in the
# changes again after OS updates (which remove modifications to this file).
#
# As such, we resort to line addition/deletion in place using `sed`. We add a comment to the
# added line that includes the name of the option, to make it easier to identify the line that
# should be deleted when the option is disabled.
mkSudoTouchIdAuthScript = isEnabled:
let
file = "/etc/pam.d/sudo";
option = "security.pam.enableSudoTouchIdAuth";
sed = "${pkgs.gnused}/bin/sed";
in ''
${if isEnabled then ''
# Enable sudo Touch ID authentication, if not already enabled
if ! grep 'pam_tid.so' ${file} > /dev/null; then
${sed} -i '2i\
auth sufficient pam_tid.so # nix-darwin: ${option}
' ${file}
fi
'' else ''
# Disable sudo Touch ID authentication, if added by nix-darwin
if grep '${option}' ${file} > /dev/null; then
${sed} -i '/${option}/d' ${file}
fi
''}
'';
cfg = config.security.pam.services.sudo_local;
in

{
imports = [
(lib.mkRemovedOptionModule [ "security" "pam" "enableSudoTouchIdAuth" ] ''
This option has been renamed to `security.pam.services.sudo_local.touchIdAuth` for consistency with NixOS.
'')
];

options = {
security.pam.enableSudoTouchIdAuth = mkEnableOption "" // {
description = ''
Enable sudo authentication with Touch ID.
security.pam.services.sudo_local = {
enable = lib.mkEnableOption "managing {file}`/etc/pam.d/sudo_local` with nix-darwin" // {
default = true;
example = false;
};

text = lib.mkOption {
type = lib.types.lines;
default = "";
description = ''
Contents of {file}`/etc/pam.d/sudo_local`
'';
};

touchIdAuth = lib.mkEnableOption "" // {
description = ''
Whether to enable Touch ID with sudo.
When enabled, this option adds the following line to
{file}`/etc/pam.d/sudo`:
This will also allow your Apple Watch to be used for sudo. If this doesn't work,
you can go into `System Settings > Touch ID & Password` and toggle the switch for
your Apple Watch.
'';
};

```
auth sufficient pam_tid.so
```
reattach = lib.mkEnableOption "" // {
description = ''
Whether to enable reattaching a program to the user's bootstrap session.
::: {.note}
macOS resets this file when doing a system update. As such, sudo
authentication with Touch ID won't work after a system update
until the nix-darwin configuration is reapplied.
:::
'';
This fixes Touch ID for sudo not working inside tmux and screen.
This allows programs like tmux and screen that run in the background to
survive across user sessions to work with PAM services that are tied to the
bootstrap session.
'';
};
};
};

config = {
system.activationScripts.pam.text = ''
security.pam.services.sudo_local.text = lib.concatLines (
(lib.optional cfg.reattach "auth optional ${pkgs.pam-reattach}/lib/pam/pam_reattach.so")
++ (lib.optional cfg.touchIdAuth "auth sufficient pam_tid.so")
);

environment.etc."pam.d/sudo_local" = {
inherit (cfg) enable text;
};

system.activationScripts.pam.text =
let
file = "/etc/pam.d/sudo";
marker = "security.pam.services.sudo_local";
deprecatedOption = "security.pam.enableSudoTouchIdAuth";
sed = lib.getExe pkgs.gnused;
in
''
# PAM settings
echo >&2 "setting up pam..."
${mkSudoTouchIdAuthScript cfg.enableSudoTouchIdAuth}
# REMOVEME when macOS 13 no longer supported as macOS automatically
# nukes this file on system upgrade
# Always clear out older implementation if it is present
if grep '${deprecatedOption}' ${file} > /dev/null; then
${sed} -i '/${deprecatedOption}/d' ${file}
fi
${if cfg.enable then ''
# REMOVEME when macOS 13 no longer supported
# `sudo_local` is automatically included after macOS 14
if ! grep 'sudo_local' ${file} > /dev/null; then
${sed} -i '2iauth include sudo_local # nix-darwin: ${marker}' ${file}
fi
'' else ''
# Remove include line if we added it
if grep '${marker}' ${file} > /dev/null; then
${sed} -i '/${marker}/d' ${file}
fi
''}
'';
};
}

0 comments on commit 42be12b

Please sign in to comment.