summary refs log tree commit diff
path: root/nixos/modules/services/misc/sssd.nix
blob: edd5750a4a478eb1f3904fb83805c4e325560cfc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
{ config, lib, pkgs, ... }:
with lib;
let
  cfg = config.services.sssd;
  nscd = config.services.nscd;

  dataDir = "/var/lib/sssd";
  settingsFile = "${dataDir}/sssd.conf";
  settingsFileUnsubstituted = pkgs.writeText "${dataDir}/sssd-unsubstituted.conf" cfg.config;
in {
  options = {
    services.sssd = {
      enable = mkEnableOption (lib.mdDoc "the System Security Services Daemon");

      config = mkOption {
        type = types.lines;
        description = lib.mdDoc "Contents of {file}`sssd.conf`.";
        default = ''
          [sssd]
          config_file_version = 2
          services = nss, pam
          domains = shadowutils

          [nss]

          [pam]

          [domain/shadowutils]
          id_provider = proxy
          proxy_lib_name = files
          auth_provider = proxy
          proxy_pam_target = sssd-shadowutils
          proxy_fast_alias = True
        '';
      };

      sshAuthorizedKeysIntegration = mkOption {
        type = types.bool;
        default = false;
        description = lib.mdDoc ''
          Whether to make sshd look up authorized keys from SSS.
          For this to work, the `ssh` SSS service must be enabled in the sssd configuration.
        '';
      };

      kcm = mkOption {
        type = types.bool;
        default = false;
        description = lib.mdDoc ''
          Whether to use SSS as a Kerberos Cache Manager (KCM).
          Kerberos will be configured to cache credentials in SSS.
        '';
      };
      environmentFile = mkOption {
        type = types.nullOr types.path;
        default = null;
        description = lib.mdDoc ''
          Environment file as defined in {manpage}`systemd.exec(5)`.

          Secrets may be passed to the service without adding them to the world-readable
          Nix store, by specifying placeholder variables as the option value in Nix and
          setting these variables accordingly in the environment file.

          ```
            # snippet of sssd-related config
            [domain/LDAP]
            ldap_default_authtok = $SSSD_LDAP_DEFAULT_AUTHTOK
          ```

          ```
            # contents of the environment file
            SSSD_LDAP_DEFAULT_AUTHTOK=verysecretpassword
          ```
        '';
      };
    };
  };
  config = mkMerge [
    (mkIf cfg.enable {
      systemd.services.sssd = {
        description = "System Security Services Daemon";
        wantedBy    = [ "multi-user.target" ];
        before = [ "systemd-user-sessions.service" "nss-user-lookup.target" ];
        after = [ "network-online.target" "nscd.service" ];
        requires = [ "network-online.target" "nscd.service" ];
        wants = [ "nss-user-lookup.target" ];
        restartTriggers = [
          config.environment.etc."nscd.conf".source
          settingsFileUnsubstituted
        ];
        script = ''
          export LDB_MODULES_PATH+="''${LDB_MODULES_PATH+:}${pkgs.ldb}/modules/ldb:${pkgs.sssd}/modules/ldb"
          mkdir -p /var/lib/sss/{pubconf,db,mc,pipes,gpo_cache,secrets} /var/lib/sss/pipes/private /var/lib/sss/pubconf/krb5.include.d
          ${pkgs.sssd}/bin/sssd -D -c ${settingsFile}
        '';
        serviceConfig = {
          Type = "forking";
          PIDFile = "/run/sssd.pid";
          StateDirectory = baseNameOf dataDir;
          # We cannot use LoadCredential here because it's not available in ExecStartPre
          EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile;
        };
        preStart = ''
          [ -f ${settingsFile} ] && rm -f ${settingsFile}
          old_umask=$(umask)
          umask 0177
          ${pkgs.envsubst}/bin/envsubst \
            -o ${settingsFile} \
            -i ${settingsFileUnsubstituted}
          umask $old_umask
        '';
      };

      system.nssModules = [ pkgs.sssd ];
      system.nssDatabases = {
        group = [ "sss" ];
        passwd = [ "sss" ];
        services = [ "sss" ];
        shadow = [ "sss" ];
      };
      services.dbus.packages = [ pkgs.sssd ];
    })

    (mkIf cfg.kcm {
      systemd.services.sssd-kcm = {
        description = "SSSD Kerberos Cache Manager";
        requires = [ "sssd-kcm.socket" ];
        serviceConfig = {
          ExecStartPre = "-${pkgs.sssd}/bin/sssd --genconf-section=kcm";
          ExecStart = "${pkgs.sssd}/libexec/sssd/sssd_kcm --uid 0 --gid 0";
        };
        restartTriggers = [
          config.environment.etc."sssd/sssd.conf".source
        ];
      };
      systemd.sockets.sssd-kcm = {
        description = "SSSD Kerberos Cache Manager responder socket";
        wantedBy = [ "sockets.target" ];
        # Matches the default in MIT krb5 and Heimdal:
        # https://github.com/krb5/krb5/blob/krb5-1.19.3-final/src/include/kcm.h#L43
        listenStreams = [ "/var/run/.heim_org.h5l.kcm-socket" ];
      };
      krb5.libdefaults.default_ccache_name = "KCM:";
    })

    (mkIf cfg.sshAuthorizedKeysIntegration {
    # Ugly: sshd refuses to start if a store path is given because /nix/store is group-writable.
    # So indirect by a symlink.
    environment.etc."ssh/authorized_keys_command" = {
      mode = "0755";
      text = ''
        #!/bin/sh
        exec ${pkgs.sssd}/bin/sss_ssh_authorizedkeys "$@"
      '';
    };
    services.openssh.authorizedKeysCommand = "/etc/ssh/authorized_keys_command";
    services.openssh.authorizedKeysCommandUser = "nobody";
  })];

  meta.maintainers = with maintainers; [ bbigras ];
}