Unverified Commit 3ab6ee74 authored by sweenu's avatar sweenu
Browse files

nixos/lldap: allow automatic creation of a local database

parent ee97808b
Loading
Loading
Loading
Loading
+82 −4
Original line number Diff line number Diff line
@@ -8,6 +8,10 @@
let
  cfg = config.services.lldap;
  format = pkgs.formats.toml { };
  dbName = "lldap";
  dbUser = "lldap";
  localPostgresql = cfg.database.createLocally && cfg.database.type == "postgresql";
  localMysql = cfg.database.createLocally && cfg.database.type == "mariadb";
in
{
  options.services.lldap = with lib; {
@@ -36,6 +40,25 @@ in
      '';
    };

    database = {
      createLocally = mkOption {
        type = types.bool;
        default = true;
        description = "Create the database and database user locally.";
      };

      type = mkOption {
        type = types.enum [
          "mariadb"
          "postgresql"
          "sqlite"
        ];
        example = "postgresql";
        default = "sqlite";
        description = "Database engine to use.";
      };
    };

    settings = mkOption {
      description = ''
        Free-form settings written directly to the `lldap_config.toml` file.
@@ -96,9 +119,20 @@ in
          };

          database_url = mkOption {
            type = types.str;
            type = types.nullOr types.str;
            default = null;
            defaultText = lib.literalExpression ''
              if config.services.lldap.database.createLocally
              then
                if cfg.database.type == "sqlite"
                then "sqlite://./users.db?mode=rwc"
                else if cfg.database.type == "postgresql"
                then "postgresql:///lldap?host=/run/postgresql"
                else if cfg.database.type == "mariadb"
                then "mysql://lldap@localhost/lldap?socket=/run/mysqld/mysqld.sock"
              else null
            '';
            description = "Database URL.";
            default = "sqlite://./users.db?mode=rwc";
            example = "postgres://postgres-user:password@postgres-server/my-database";
          };

@@ -188,7 +222,7 @@ in
    ];

    warnings =
      lib.optionals (cfg.settings.ldap_user_pass or null != null) [
      lib.optionals ((cfg.settings.ldap_user_pass or null) != null) [
        ''
          lldap: Unsecure `ldap_user_pass` setting is used. Prefer `ldap_user_pass_file` instead.
        ''
@@ -205,10 +239,29 @@ in
            ''
          ];

    services.lldap.settings.database_url = lib.mkIf cfg.database.createLocally (
      lib.mkDefault (
        if cfg.database.type == "sqlite" then
          "sqlite://./users.db?mode=rwc"
        else if cfg.database.type == "postgresql" then
          "postgresql:///${dbName}?host=/run/postgresql"
        else if cfg.database.type == "mariadb" then
          "mysql://${dbUser}@localhost/${dbName}?socket=/run/mysqld/mysqld.sock"
        else
          null
      )
    );

    systemd.services.lldap = {
      description = "Lightweight LDAP server (lldap)";
      wants = [ "network-online.target" ];
      after = [ "network-online.target" ];
      after = [
        "network-online.target"
      ]
      ++ lib.optional localPostgresql "postgresql.target"
      ++ lib.optional localMysql "mysql.service";
      requires =
        lib.optional localPostgresql "postgresql.target" ++ lib.optional localMysql "mysql.service";
      wantedBy = [ "multi-user.target" ];
      # lldap defaults to a hardcoded `jwt_secret` value if none is provided, which is bad, because
      # an attacker could create a valid admin jwt access token fairly trivially.
@@ -238,5 +291,30 @@ in
      };
      inherit (cfg) environment;
    };

    services.postgresql = lib.mkIf localPostgresql {
      enable = true;
      ensureDatabases = [ dbName ];
      ensureUsers = [
        {
          name = dbUser;
          ensureDBOwnership = true;
        }
      ];
    };

    services.mysql = lib.mkIf localMysql {
      enable = true;
      package = lib.mkDefault pkgs.mariadb;
      ensureDatabases = [ dbName ];
      ensureUsers = [
        {
          name = dbUser;
          ensurePermissions = {
            "${dbName}.*" = "ALL PRIVILEGES";
          };
        }
      ];
    };
  };
}