Unverified Commit e2a43fbf authored by pennae's avatar pennae Committed by GitHub
Browse files

Merge pull request #244356 from datafoo/mosquitto-systemd-credentials

nixos/mosquitto: leverage systemd credentials
parents f8e5fdc6 533ff854
Loading
Loading
Loading
Loading
+56 −9
Original line number Diff line number Diff line
@@ -42,12 +42,15 @@ let
      };

      passwordFile = mkOption {
        type = uniq (nullOr types.path);
        type = uniq (nullOr path);
        example = "/path/to/file";
        default = null;
        description = lib.mdDoc ''
          Specifies the path to a file containing the
          clear text password for the MQTT user.
          The file is securely passed to mosquitto by
          leveraging systemd credentials. No special
          permissions need to be set on this file.
        '';
      };

@@ -64,7 +67,7 @@ let
      };

      hashedPasswordFile = mkOption {
        type = uniq (nullOr types.path);
        type = uniq (nullOr path);
        example = "/path/to/file";
        default = null;
        description = mdDoc ''
@@ -73,6 +76,9 @@ let
          To generate hashed password install the `mosquitto`
          package and use `mosquitto_passwd`, then remove the
          `username:` prefix from the generated file.
          The file is securely passed to mosquitto by
          leveraging systemd credentials. No special
          permissions need to be set on this file.
        '';
      };

@@ -102,15 +108,43 @@ let
        message = "Cannot set more than one password option for user ${n} in ${prefix}";
      }) users;

  makePasswordFile = users: path:
  listenerScope = index: "listener-${toString index}";
  userScope = prefix: index: "${prefix}-user-${toString index}";
  credentialID = prefix: credential: "${prefix}-${credential}";

  toScopedUsers = listenerScope: users: pipe users [
    attrNames
    (imap0 (index: user: nameValuePair user
      (users.${user} // { scope = userScope listenerScope index; })
    ))
    listToAttrs
  ];

  userCredentials = user: credentials: pipe credentials [
    (filter (credential: user.${credential} != null))
    (map (credential: "${credentialID user.scope credential}:${user.${credential}}"))
  ];
  usersCredentials = listenerScope: users: credentials: pipe users [
    (toScopedUsers listenerScope)
    (mapAttrsToList (_: user: userCredentials user credentials))
    concatLists
  ];
  systemdCredentials = listeners: listenerCredentials: pipe listeners [
    (imap0 (index: listener: listenerCredentials (listenerScope index) listener))
    concatLists
  ];

  makePasswordFile = listenerScope: users: path:
    let
      makeLines = store: file:
      makeLines = store: file: let
        scopedUsers = toScopedUsers listenerScope users;
      in
        mapAttrsToList
          (n: u: "addLine ${escapeShellArg n} ${escapeShellArg u.${store}}")
          (filterAttrs (_: u: u.${store} != null) users)
          (name: user: ''addLine ${escapeShellArg name} "''$(systemd-creds cat ${credentialID user.scope store})"'')
          (filterAttrs (_: user: user.${store} != null) scopedUsers)
        ++ mapAttrsToList
          (n: u: "addFile ${escapeShellArg n} ${escapeShellArg "${u.${file}}"}")
          (filterAttrs (_: u: u.${file} != null) users);
          (name: user: ''addFile ${escapeShellArg name} "''${CREDENTIALS_DIRECTORY}/${credentialID user.scope file}"'')
          (filterAttrs (_: user: user.${file} != null) scopedUsers);
      plainLines = makeLines "password" "passwordFile";
      hashedLines = makeLines "hashedPassword" "hashedPasswordFile";
    in
@@ -581,6 +615,19 @@ in
        ExecStart = "${cfg.package}/bin/mosquitto -c ${configFile}";
        ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";

        # Credentials
        SetCredential = let
          listenerCredentials = listenerScope: listener:
            usersCredentials listenerScope listener.users [ "password" "hashedPassword" ];
        in
          systemdCredentials cfg.listeners listenerCredentials;

        LoadCredential = let
          listenerCredentials = listenerScope: listener:
            usersCredentials listenerScope listener.users [ "passwordFile" "hashedPasswordFile" ];
        in
          systemdCredentials cfg.listeners listenerCredentials;

        # Hardening
        CapabilityBoundingSet = "";
        DevicePolicy = "closed";
@@ -653,7 +700,7 @@ in
        concatStringsSep
          "\n"
          (imap0
            (idx: listener: makePasswordFile listener.users "${cfg.dataDir}/passwd-${toString idx}")
            (idx: listener: makePasswordFile (listenerScope idx) listener.users "${cfg.dataDir}/passwd-${toString idx}")
            cfg.listeners);
    };