add ldapgroup contract
This commit is contained in:
parent
b34a1e57a7
commit
3213f119d2
10 changed files with 469 additions and 56 deletions
|
|
@ -1,6 +1,9 @@
|
|||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) mkOption;
|
||||
inherit (lib.types) attrsOf str submodule;
|
||||
|
||||
cfg = config.shb.ldap;
|
||||
|
||||
contracts = pkgs.callPackage ../contracts {};
|
||||
|
|
@ -149,16 +152,42 @@ in
|
|||
};
|
||||
|
||||
groups = lib.mkOption {
|
||||
description = "LDAP Groups to manage declaratively.";
|
||||
description = "LDAP Groups to manage declaratively following the [ldap group contract](./contracts-ldap-group.html).";
|
||||
default = {};
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
family = {};
|
||||
}
|
||||
'';
|
||||
type = lib.types.attrsOf (lib.types.submodule {
|
||||
options = {};
|
||||
});
|
||||
type = attrsOf (submodule ({ name, config, ... }: {
|
||||
options = contracts.ldapgroup.mkProvider {
|
||||
settings = mkOption {
|
||||
description = ''
|
||||
Settings specific to the LLDAP provider.
|
||||
|
||||
By default it is the same as the field name.
|
||||
'';
|
||||
default = {
|
||||
inherit name;
|
||||
};
|
||||
|
||||
type = submodule {
|
||||
options = {
|
||||
name = mkOption {
|
||||
description = "Name of the LDAP group";
|
||||
type = str;
|
||||
default = name;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
resultCfg = {
|
||||
name = config.settings.name;
|
||||
nameText = name;
|
||||
};
|
||||
};
|
||||
}));
|
||||
};
|
||||
|
||||
deleteUnmanagedUsers = lib.mkOption {
|
||||
|
|
@ -372,8 +401,6 @@ in
|
|||
|
||||
systemd.services.lldap.postStart =
|
||||
let
|
||||
configFile = (pkgs.formats.toml {}).generate "lldap_config.toml" config.services.lldap.settings;
|
||||
|
||||
login = [''
|
||||
set -euo pipefail
|
||||
|
||||
|
|
@ -388,7 +415,7 @@ in
|
|||
|
||||
deleteGroups = [''
|
||||
allUids=(${lib.concatStringsSep " " (
|
||||
(lib.mapAttrsToList (id: g: id) cfg.groups)
|
||||
(lib.mapAttrsToList (id: g: g.settings.name) cfg.groups)
|
||||
++ [ "lldap_admin" "lldap_password_manager" "lldap_strict_readonly" ])
|
||||
})
|
||||
echo All managed groups are: ''${allUids[*]}
|
||||
|
|
@ -405,7 +432,7 @@ in
|
|||
createGroups = [''
|
||||
existingUids=$(${lldap-cli}/bin/lldap-cli group list | ${pkgs.jq}/bin/jq -r 'map(.displayName)[]')
|
||||
managedUids=(${lib.concatStringsSep " " (
|
||||
(lib.mapAttrsToList (id: g: id) cfg.groups)
|
||||
(lib.mapAttrsToList (id: g: g.settings.name) cfg.groups)
|
||||
++ [ "lldap_admin" "lldap_password_manager" "lldap_strict_readonly" ])
|
||||
})
|
||||
echo All managed groups are: ''${managedUids[*]}
|
||||
|
|
|
|||
133
modules/blocks/ldap/docs/default.md
Normal file
133
modules/blocks/ldap/docs/default.md
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
# LLDAP Block {#blocks-lldap}
|
||||
|
||||
Defined in [`/modules/blocks/lldap.nix`](@REPO@/modules/blocks/lldap.nix).
|
||||
|
||||
This block sets up a LDAP server using [LLDAP][].
|
||||
|
||||
[LLDAP]: https://github.com/lldap/lldap
|
||||
|
||||
## Tests {#blocks-lldap-tests}
|
||||
|
||||
Specific integration tests are defined in [`/test/blocks/lldap.nix`](@REPO@/test/blocks/lldap.nix).
|
||||
The tests use a neat trick using specialization and switching configuration
|
||||
to make sure changing the declarative configuration has the expected result.
|
||||
|
||||
## Provider Contracts {#blocks-lldap-contract-provider}
|
||||
|
||||
This block provides the following contract:
|
||||
|
||||
- [groups ldap contract](contracts-groups-ldap.html) under the [`shb.ldap.groups`][groups] option.
|
||||
It is tested with [contract tests][groups ldap contract tests].
|
||||
|
||||
[groups]: #blocks-lldap-options-shb.ldap.groups
|
||||
[groups ldap contract tests]: @REPO@/test/contracts/groups-ldap.nix
|
||||
|
||||
## Usage {#blocks-lldap-usage}
|
||||
|
||||
### Manage groups {#blocks-lldap-usage-groups}
|
||||
|
||||
The following snippet will create group named "family" if it does not exist yet.
|
||||
Also, all other groups will be deleted and only the "family" group will remain.
|
||||
|
||||
Note that the "admin" group, which is internal to LLDAP, will never be deleted.
|
||||
|
||||
```nix
|
||||
{
|
||||
shb.ldap.groups = {
|
||||
family = {};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Changing the configuration to the following will add a new group "friends":
|
||||
|
||||
```nix
|
||||
{
|
||||
shb.ldap.groups = {
|
||||
family = {};
|
||||
friends = {};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Switching back the configuration to the previous one will delete the group "friends":
|
||||
|
||||
```nix
|
||||
{
|
||||
shb.ldap.groups = {
|
||||
family = {};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Currently, only the empty attrset is supported as the value for a group.
|
||||
This will change in the future when LLDAP supports custom group attributes.
|
||||
|
||||
### Manage users {#blocks-lldap-usage-users}
|
||||
|
||||
The following snippet creates a user and makes it a member of the "family" group.
|
||||
|
||||
```nix
|
||||
{
|
||||
shb.ldap.users = {
|
||||
dad = {
|
||||
email = "dad@example.com";
|
||||
displayName = "Dad";
|
||||
firstName = "First Name";
|
||||
lastName = "Last Name";
|
||||
groups = [ "family" ];
|
||||
password.result = config.shb.sops.secret."dad".result;
|
||||
};
|
||||
};
|
||||
|
||||
shb.sops.secret."dad".request =
|
||||
shb.ldap.users.dad.password.request;
|
||||
}
|
||||
```
|
||||
|
||||
The password field assumes usage of the [sops block][] to provide secrets
|
||||
although any blocks providing the [secrets contract][] works too.
|
||||
|
||||
[sops block]: ./blocks-sops.html
|
||||
[secrets contract]: ./contracts-secrets.html
|
||||
|
||||
The user is still editable through the UI.
|
||||
That being said, any change will be overwritten next time the configuration is applied.
|
||||
If instead you just want to set initial values,
|
||||
there are fields for that:
|
||||
|
||||
```nix
|
||||
{
|
||||
shb.ldap.users = {
|
||||
dad = {
|
||||
initialEmail = "dad@example.com";
|
||||
initialDisplayName = "Dad";
|
||||
initialFirstName = "First Name";
|
||||
initialLastName = "Last Name";
|
||||
initialGroups = [ "family" ];
|
||||
initialPassword.result = config.shb.sops.secret."dad".result;
|
||||
};
|
||||
};
|
||||
|
||||
shb.sops.secret."dad".request =
|
||||
shb.ldap.users.dad.password.request;
|
||||
}
|
||||
```
|
||||
|
||||
Also, all fields apart from the email are optional, even the password.
|
||||
|
||||
Adding or removing groups to the `shb.ldap.users.<name>.groups` will make the user member of the groups listed in the option.
|
||||
|
||||
## Troubleshooting {#blocks-lldap-troubleshooting}
|
||||
|
||||
To see the logs, run `journalctl -u lldap.service`.
|
||||
|
||||
To see the trace of the GraphQL queries, set `shb.ldap.debug = true;`.
|
||||
|
||||
## Options Reference {#blocks-lldap-options}
|
||||
|
||||
```{=include=} options
|
||||
id-prefix: blocks-lldap-options-
|
||||
list-id: selfhostblocks-block-lldap-options
|
||||
source: @OPTIONS_JSON@
|
||||
```
|
||||
|
|
@ -19,29 +19,39 @@ source: @OPTIONS_JSON@
|
|||
|
||||
## Usage {#contract-databasebackup-usage}
|
||||
|
||||
A database that can be backed up will provide a `databasebackup` option.
|
||||
Such a service is a `requester` providing a `request` for a module `provider` of this contract.
|
||||
|
||||
What this option defines is, from the user perspective - that is _you_ - an implementation detail
|
||||
What this contract defines is, from the user perspective - that is _you_ - an implementation detail
|
||||
but it will at least define how to create a database dump,
|
||||
the user to backup with
|
||||
and how to restore from a database dump.
|
||||
|
||||
A NixOS module that can be backed up using this contract will provide a `databasebackup` option.
|
||||
Such a service is a `requester` which has a `request`.
|
||||
|
||||
Here is an example module defining such a `databasebackup` option:
|
||||
|
||||
```nix
|
||||
{
|
||||
options = {
|
||||
myservice.databasebackup = mkOption {
|
||||
type = contracts.databasebackup.request;
|
||||
default = {
|
||||
user = "myservice";
|
||||
backupCmd = ''
|
||||
${pkgs.postgresql}/bin/pg_dumpall | ${pkgs.gzip}/bin/gzip --rsyncable
|
||||
'';
|
||||
restoreCmd = ''
|
||||
${pkgs.gzip}/bin/gunzip | ${pkgs.postgresql}/bin/psql postgres
|
||||
'';
|
||||
databasebackupservices.instances = mkOption {
|
||||
description = ''
|
||||
Backup configuration.
|
||||
'';
|
||||
|
||||
default = {};
|
||||
type = submodule {
|
||||
options = contracts.databasebackup.mkRequester {
|
||||
user = "postgres";
|
||||
|
||||
backupName = "postgres.sql";
|
||||
|
||||
backupCmd = ''
|
||||
${pkgs.postgresql}/bin/pg_dumpall | ${pkgs.gzip}/bin/gzip --rsyncable
|
||||
'';
|
||||
|
||||
restoreCmd = ''
|
||||
${pkgs.gzip}/bin/gunzip | ${pkgs.postgresql}/bin/psql postgres
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -51,28 +61,60 @@ Here is an example module defining such a `databasebackup` option:
|
|||
Now, on the other side we have a service that uses this `backup` option and actually backs up files.
|
||||
This service is a `provider` of this contract and will provide a `result` option.
|
||||
|
||||
Let's assume such a module is available under the `databasebackupservice` option
|
||||
and that one can create multiple backup instances under `databasebackupservice.instances`.
|
||||
Then, to actually backup the `myservice` service, one would write:
|
||||
```nix
|
||||
{
|
||||
options = {
|
||||
instances = mkOption {
|
||||
description = "Files to backup.";
|
||||
default = {};
|
||||
type = attrsOf (submodule ({ name, config, ... }: {
|
||||
options = contracts.backup.mkProvider {
|
||||
settings = mkOption {
|
||||
description = ''
|
||||
Settings specific to the this provider.
|
||||
'';
|
||||
|
||||
type = submodule {
|
||||
options = {
|
||||
enable = mkEnableOption "this backup intance.";
|
||||
# ... Other options specific to this provider.
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
resultCfg = let
|
||||
fullName = name: repository: "backups-${name}_${repository.path}";
|
||||
in {
|
||||
restoreScript = fullName name config.settings.repository;
|
||||
restoreScriptText = "${fullName "<name>" { path = "path/to/repository"; }}";
|
||||
|
||||
backupService = "${fullName name config.settings.repository}.service";
|
||||
backupServiceText = "${fullName "<name>" { path = "path/to/repository"; }}.service";
|
||||
};
|
||||
};
|
||||
}));
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Then, to actually backup the `myservice` service,
|
||||
one would need to link the requester to the provider with:
|
||||
|
||||
```nix
|
||||
databasebackupservice.instances.myservice = {
|
||||
request = myservice.databasebackup;
|
||||
request = config.myservice.databasebackup.request;
|
||||
|
||||
settings = {
|
||||
enable = true;
|
||||
|
||||
repository = {
|
||||
path = "/srv/backup/myservice";
|
||||
};
|
||||
|
||||
# ... Other options specific to backupservice like scheduling.
|
||||
# ... Other options specific to this provider.
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
It is advised to backup files to different location, to improve redundancy.
|
||||
Thanks to using contracts, this can be made easily either with the same `databasebackupservice`:
|
||||
Thanks to using contracts, this can be done easily either with the same `databasebackupservice`:
|
||||
|
||||
```nix
|
||||
databasebackupservice.instances.myservice_2 = {
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ in
|
|||
{
|
||||
databasebackup = importContract ./databasebackup.nix;
|
||||
backup = importContract ./backup.nix;
|
||||
ldapgroup = importContract ./ldapgroup.nix;
|
||||
mount = import ./mount.nix { inherit lib; };
|
||||
secret = importContract ./secret.nix;
|
||||
ssl = import ./ssl.nix { inherit lib; };
|
||||
|
|
|
|||
83
modules/contracts/ldapgroup.nix
Normal file
83
modules/contracts/ldapgroup.nix
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
{ pkgs, lib, ... }:
|
||||
let
|
||||
inherit (lib) literalMD mkOption optionalAttrs optionalString;
|
||||
inherit (lib.types) str submodule;
|
||||
|
||||
shblib = pkgs.callPackage ../../lib {};
|
||||
inherit (shblib) anyNotNull;
|
||||
in
|
||||
{
|
||||
mkRequest = {
|
||||
name ? "",
|
||||
nameText ? null,
|
||||
}: mkOption {
|
||||
description = ''
|
||||
Request part of the ldap group contract.
|
||||
|
||||
Options set by the requester module
|
||||
enforcing what properties the group should have.
|
||||
|
||||
This is intentionally empty as the only required property
|
||||
is the existence of this option.
|
||||
'';
|
||||
default = {
|
||||
inherit name;
|
||||
};
|
||||
defaultText = optionalString (anyNotNull [
|
||||
nameText
|
||||
]) (literalMD ''
|
||||
{
|
||||
name = ${if nameText != null then nameText else name};
|
||||
}
|
||||
'');
|
||||
|
||||
type = submodule {
|
||||
options = {
|
||||
name = mkOption {
|
||||
description = ''
|
||||
Name of the LDAP group.
|
||||
'';
|
||||
type = str;
|
||||
default = name;
|
||||
} // optionalAttrs (nameText != null) {
|
||||
defaultText = literalMD nameText;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mkResult = {
|
||||
name ? "",
|
||||
nameText ? null,
|
||||
}: mkOption {
|
||||
description = ''
|
||||
Result part of the ldap group contract.
|
||||
|
||||
Options set by the provider module that indicates the name of the group and other properties.
|
||||
'';
|
||||
default = {
|
||||
inherit name;
|
||||
};
|
||||
defaultText = optionalString (anyNotNull [
|
||||
nameText
|
||||
]) (literalMD ''
|
||||
{
|
||||
name = ${if nameText != null then nameText else name};
|
||||
}
|
||||
'');
|
||||
|
||||
type = submodule {
|
||||
options = {
|
||||
name = mkOption {
|
||||
description = ''
|
||||
Name of the LDAP group.
|
||||
'';
|
||||
type = str;
|
||||
default = name;
|
||||
} // optionalAttrs (nameText != null) {
|
||||
defaultText = literalMD nameText;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
124
modules/contracts/ldapgroup/docs/default.md
Normal file
124
modules/contracts/ldapgroup/docs/default.md
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
# LDAP Group Contract {#contract-ldapgroup}
|
||||
|
||||
This NixOS contract represents an LDAP group
|
||||
that must be created.
|
||||
|
||||
It is a contract between a service that needs an LDAP group
|
||||
and a service that can provide such a group.
|
||||
|
||||
## Contract Reference {#contract-ldapgroup-options}
|
||||
|
||||
These are all the options that are expected to exist for this contract to be respected.
|
||||
|
||||
```{=include=} options
|
||||
id-prefix: contracts-ldapgroup-options-
|
||||
list-id: selfhostblocks-options
|
||||
source: @OPTIONS_JSON@
|
||||
```
|
||||
|
||||
## Usage {#contract-ldapgroup-usage}
|
||||
|
||||
What this contract defines is, from the user perspective - that is _you_ - an implementation detail
|
||||
but you can know it simply defines the LDAP group name.
|
||||
|
||||
A NixOS module that needs a LDAP group using this contract will provide a `ldapgroup` option or similarly named.
|
||||
Such a service is a `requester` providing a `request` for a module `provider` of this contract.
|
||||
|
||||
Here is an example module defining such a `ldapgroup` option:
|
||||
|
||||
```nix
|
||||
{
|
||||
options = {
|
||||
myservice.ldapgroup = mkOption {
|
||||
type = contracts.ldapgroup.request;
|
||||
};
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
Now, on the other side we have a service that uses this `ldapgroup` option and actually creates the LDAP group.
|
||||
This service is a `provider` of this contract and will provide a `result` option containing the name of the group.
|
||||
|
||||
```nix
|
||||
{
|
||||
options = {
|
||||
ldap.groups = lib.mkOption {
|
||||
description = "LDAP Groups to manage declaratively.";
|
||||
default = {};
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
family = {};
|
||||
}
|
||||
'';
|
||||
type = attrsOf (submodule ({ name, config, ... }: {
|
||||
options = contracts.ldapgroup.mkProvider {
|
||||
settings = mkOption {
|
||||
description = ''
|
||||
Settings specific to the LLDAP provider.
|
||||
|
||||
By default it is the same as the field name.
|
||||
'';
|
||||
default = {
|
||||
inherit name;
|
||||
};
|
||||
|
||||
type = submodule {
|
||||
options = {
|
||||
name = mkOption {
|
||||
description = "Name of the LDAP group";
|
||||
type = str;
|
||||
default = name;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
resultCfg = {
|
||||
name = config.settings.name;
|
||||
nameText = name;
|
||||
};
|
||||
};
|
||||
}));
|
||||
};
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
Then, to actually backup the `myservice` service,
|
||||
one would need to link the requester to the provider with:
|
||||
|
||||
```nix
|
||||
# requester -> provider
|
||||
ldapgroupservice.groups.myservice = {
|
||||
request = config.myservice.ldapgroup.request;
|
||||
};
|
||||
# provider -> requester
|
||||
myservice.ldapgroup.result = config.ldapgroupservice.groups.myservice.result;
|
||||
```
|
||||
|
||||
By default, the name of the LDAP group will be the same as the field name under the `groups` option. Here, `"myservice"`.
|
||||
|
||||
Usually, a service will require two LDAP groups to work properly,
|
||||
one for users and another one for admin users.
|
||||
In this case, the linking them together will look like so:
|
||||
|
||||
```nix
|
||||
# requester -> provider
|
||||
ldapgroupservice.groups = {
|
||||
myservice_user.request = config.myservice.ldap.userGroup.request;
|
||||
myservice_admin.request = config.myservice.ldap.adminGroup.request;
|
||||
};
|
||||
# provider -> requester
|
||||
myservice.ldap = {
|
||||
userGroup.result = config.ldapgroupservice.groups.myservice_user.result;
|
||||
adminGroup.result = config.ldapgroupservice.groups.myservice_admin.result;
|
||||
};
|
||||
```
|
||||
|
||||
## Providers of the Database Backup Contract {#contract-ldapgroup-providers}
|
||||
|
||||
- [LDAP block](blocks-ldap.html).
|
||||
|
||||
## Requester Blocks and Services {#contract-ldapgroup-requesters}
|
||||
|
||||
- [Nextcloud service](services-nextcloud.html#services-nextcloud-contract-ldapgroup).
|
||||
|
|
@ -98,15 +98,13 @@ in
|
|||
};
|
||||
|
||||
userGroup = mkOption {
|
||||
type = str;
|
||||
type = contracts.ldapgroup.request;
|
||||
description = "Group users must belong to be able to login.";
|
||||
default = "forgejo_user";
|
||||
};
|
||||
|
||||
adminGroup = mkOption {
|
||||
type = str;
|
||||
type = contracts.ldapgroup.request;
|
||||
description = "Group users must belong to be admins.";
|
||||
default = "forgejo_admin";
|
||||
};
|
||||
};
|
||||
});
|
||||
|
|
@ -394,8 +392,8 @@ in
|
|||
--bind-password $(tr -d '\n' < ${cfg.ldap.adminPassword.result.path}) \
|
||||
--security-protocol Unencrypted \
|
||||
--user-search-base ou=people,${cfg.ldap.dcdomain} \
|
||||
--user-filter '(&(memberof=cn=${cfg.ldap.userGroup},ou=groups,${cfg.ldap.dcdomain})(|(uid=%[1]s)(mail=%[1]s)))' \
|
||||
--admin-filter '(memberof=cn=${cfg.ldap.adminGroup},ou=groups,${cfg.ldap.dcdomain})' \
|
||||
--user-filter '(&(memberof=cn=${cfg.ldap.userGroup.result.name},ou=groups,${cfg.ldap.dcdomain})(|(uid=%[1]s)(mail=%[1]s)))' \
|
||||
--admin-filter '(memberof=cn=${cfg.ldap.adminGroup.result.name},ou=groups,${cfg.ldap.dcdomain})' \
|
||||
--username-attribute uid \
|
||||
--firstname-attribute givenName \
|
||||
--surname-attribute sn \
|
||||
|
|
@ -413,8 +411,8 @@ in
|
|||
--bind-password $(tr -d '\n' < ${cfg.ldap.adminPassword.result.path}) \
|
||||
--security-protocol Unencrypted \
|
||||
--user-search-base ou=people,${cfg.ldap.dcdomain} \
|
||||
--user-filter '(&(memberof=cn=${cfg.ldap.userGroup},ou=groups,${cfg.ldap.dcdomain})(|(uid=%[1]s)(mail=%[1]s)))' \
|
||||
--admin-filter '(memberof=cn=${cfg.ldap.adminGroup},ou=groups,${cfg.ldap.dcdomain})' \
|
||||
--user-filter '(&(memberof=cn=${cfg.ldap.userGroup.result.name},ou=groups,${cfg.ldap.dcdomain})(|(uid=%[1]s)(mail=%[1]s)))' \
|
||||
--admin-filter '(memberof=cn=${cfg.ldap.adminGroup.result.name},ou=groups,${cfg.ldap.dcdomain})' \
|
||||
--username-attribute uid \
|
||||
--firstname-attribute givenName \
|
||||
--surname-attribute sn \
|
||||
|
|
|
|||
|
|
@ -122,9 +122,8 @@ in
|
|||
};
|
||||
|
||||
userGroup = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
type = contracts.ldapgroup.request;
|
||||
description = "Group users must belong to to be able to login to Nextcloud.";
|
||||
default = "homeassistant_user";
|
||||
};
|
||||
|
||||
keepDefaultAuth = lib.mkOption {
|
||||
|
|
@ -241,7 +240,7 @@ in
|
|||
{
|
||||
type = "command_line";
|
||||
command = ldap_auth_script + "/bin/ldap_auth.sh";
|
||||
args = [ "http://${cfg.ldap.host}:${toString cfg.ldap.port}" cfg.ldap.userGroup ];
|
||||
args = [ "http://${cfg.ldap.host}:${toString cfg.ldap.port}" cfg.ldap.userGroup.result.name ];
|
||||
meta = true;
|
||||
}
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -56,15 +56,23 @@ in
|
|||
};
|
||||
|
||||
userGroup = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "LDAP user group";
|
||||
default = "jellyfin_user";
|
||||
default = {};
|
||||
type = lib.types.submodule {
|
||||
options = contracts.ldapgroup.mkRequester {
|
||||
name = "jellyfin_user";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
adminGroup = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = "LDAP admin group";
|
||||
default = "jellyfin_admin";
|
||||
default = {};
|
||||
type = lib.types.submodule {
|
||||
options = contracts.ldapgroup.mkRequester {
|
||||
name = "jellyfin_admin";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
adminPassword = lib.mkOption {
|
||||
|
|
@ -313,9 +321,9 @@ in
|
|||
<LdapBindUser>uid=admin,ou=people,${cfg.ldap.dcdomain}</LdapBindUser>
|
||||
<LdapBindPassword>%LDAP_PASSWORD%</LdapBindPassword>
|
||||
<LdapBaseDn>ou=people,${cfg.ldap.dcdomain}</LdapBaseDn>
|
||||
<LdapSearchFilter>(memberof=cn=${cfg.ldap.userGroup},ou=groups,${cfg.ldap.dcdomain})</LdapSearchFilter>
|
||||
<LdapSearchFilter>(memberof=cn=${cfg.ldap.userGroup.result.name},ou=groups,${cfg.ldap.dcdomain})</LdapSearchFilter>
|
||||
<LdapAdminBaseDn>ou=people,${cfg.ldap.dcdomain}</LdapAdminBaseDn>
|
||||
<LdapAdminFilter>(memberof=cn=${cfg.ldap.adminGroup},ou=groups,${cfg.ldap.dcdomain})</LdapAdminFilter>
|
||||
<LdapAdminFilter>(memberof=cn=${cfg.ldap.adminGroup.result.name},ou=groups,${cfg.ldap.dcdomain})</LdapAdminFilter>
|
||||
<EnableLdapAdminFilterMemberUid>false</EnableLdapAdminFilterMemberUid>
|
||||
<LdapSearchAttributes>uid, cn, mail, displayName</LdapSearchAttributes>
|
||||
<LdapClientCertPath />
|
||||
|
|
|
|||
|
|
@ -414,11 +414,9 @@ in
|
|||
};
|
||||
};
|
||||
|
||||
|
||||
userGroup = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
type = contracts.ldapgroup.request;
|
||||
description = "Group users must belong to to be able to login to Nextcloud.";
|
||||
default = "nextcloud_user";
|
||||
};
|
||||
|
||||
configID = lib.mkOption {
|
||||
|
|
@ -1010,21 +1008,21 @@ in
|
|||
${occ} ldap:set-config "${cID}" 'ldapEmailAttribute' \
|
||||
'mail'
|
||||
${occ} ldap:set-config "${cID}" 'ldapGroupFilter' \
|
||||
'(&(|(objectclass=groupOfUniqueNames))(|(cn=${cfg'.userGroup})))'
|
||||
'(&(|(objectclass=groupOfUniqueNames))(|(cn=${cfg'.userGroup.result.name})))'
|
||||
${occ} ldap:set-config "${cID}" 'ldapGroupFilterGroups' \
|
||||
'${cfg'.userGroup}'
|
||||
'${cfg'.userGroup.result.name}'
|
||||
${occ} ldap:set-config "${cID}" 'ldapGroupFilterObjectclass' \
|
||||
'groupOfUniqueNames'
|
||||
${occ} ldap:set-config "${cID}" 'ldapGroupMemberAssocAttr' \
|
||||
'uniqueMember'
|
||||
${occ} ldap:set-config "${cID}" 'ldapLoginFilter' \
|
||||
'(&(&(objectclass=person)(memberOf=cn=${cfg'.userGroup},ou=groups,${cfg'.dcdomain}))(|(uid=%uid)(|(mail=%uid)(objectclass=%uid))))'
|
||||
'(&(&(objectclass=person)(memberOf=cn=${cfg'.userGroup.result.name},ou=groups,${cfg'.dcdomain}))(|(uid=%uid)(|(mail=%uid)(objectclass=%uid))))'
|
||||
${occ} ldap:set-config "${cID}" 'ldapLoginFilterAttributes' \
|
||||
'mail;objectclass'
|
||||
${occ} ldap:set-config "${cID}" 'ldapUserDisplayName' \
|
||||
'displayname'
|
||||
${occ} ldap:set-config "${cID}" 'ldapUserFilter' \
|
||||
'(&(objectclass=person)(memberOf=cn=${cfg'.userGroup},ou=groups,${cfg'.dcdomain}))'
|
||||
'(&(objectclass=person)(memberOf=cn=${cfg'.userGroup.result.name},ou=groups,${cfg'.dcdomain}))'
|
||||
${occ} ldap:set-config "${cID}" 'ldapUserFilterMode' \
|
||||
'1'
|
||||
${occ} ldap:set-config "${cID}" 'ldapUserFilterObjectclass' \
|
||||
|
|
|
|||
Loading…
Reference in a new issue