indico: wip: add LDAP support
Signed-off-by: Jeltz <jeltz@federez.net>
This commit is contained in:
parent
0a8ae58334
commit
dd2afc2cfb
2 changed files with 143 additions and 29 deletions
|
@ -14,7 +14,9 @@ let
|
||||||
pythonEnv = pkgs.python3.withPackages (ps: [
|
pythonEnv = pkgs.python3.withPackages (ps: [
|
||||||
(ps.toPythonModule indico)
|
(ps.toPythonModule indico)
|
||||||
ps.gunicorn
|
ps.gunicorn
|
||||||
]);
|
]
|
||||||
|
++ lib.optionals (cfg.ldap != null)
|
||||||
|
indico.optional-dependencies.ldap);
|
||||||
redisSocket = config.services.redis.servers.${cfg.redis.name}.unixSocket;
|
redisSocket = config.services.redis.servers.${cfg.redis.name}.unixSocket;
|
||||||
indicoSocket = "/run/indico/indico.sock";
|
indicoSocket = "/run/indico/indico.sock";
|
||||||
baseDir = "${pythonEnv}/${pythonEnv.sitePackages}/indico";
|
baseDir = "${pythonEnv}/${pythonEnv.sitePackages}/indico";
|
||||||
|
@ -36,7 +38,23 @@ let
|
||||||
format = "%(levelname)s %(request_id)s %(user_id)s %(name)s %(message)s";
|
format = "%(levelname)s %(request_id)s %(user_id)s %(name)s %(message)s";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
configFile = pythonFmt.generate "indico.conf" {
|
ldapConfig = {
|
||||||
|
uri = cfg.ldap.uri;
|
||||||
|
bind_dn = cfg.ldap.bindDN;
|
||||||
|
bind_password = cfg.ldap.bindPassword;
|
||||||
|
timeout = 30;
|
||||||
|
verify_cert = true;
|
||||||
|
page_size = 1500;
|
||||||
|
uid = cfg.ldap.uid;
|
||||||
|
user_base = cfg.ldap.userBaseDN;
|
||||||
|
user_filter = cfg.ldap.userFilter;
|
||||||
|
gid = cfg.ldap.gid;
|
||||||
|
group_base = cfg.ldap.groupBaseDN;
|
||||||
|
group_filter = cfg.ldap.groupFilter;
|
||||||
|
member_of_attr = cfg.ldap.memberOf;
|
||||||
|
ad_group_style = false;
|
||||||
|
};
|
||||||
|
configFile = pythonFmt.generate "indico.conf" ({
|
||||||
SQLALCHEMY_DATABASE_URI = cfg.database;
|
SQLALCHEMY_DATABASE_URI = cfg.database;
|
||||||
CACHE_DIR = "${cfg.stateDir}/cache";
|
CACHE_DIR = "${cfg.stateDir}/cache";
|
||||||
TEMP_DIR = "${cfg.stateDir}/tmp";
|
TEMP_DIR = "${cfg.stateDir}/tmp";
|
||||||
|
@ -64,9 +82,27 @@ let
|
||||||
SMTP_LOGIN = cfg.email.smtp.login;
|
SMTP_LOGIN = cfg.email.smtp.login;
|
||||||
SMTP_PASSWORD = cfg.email.smtp.password;
|
SMTP_PASSWORD = cfg.email.smtp.password;
|
||||||
SMTP_USE_TLS = cfg.email.smtp.useTLS;
|
SMTP_USE_TLS = cfg.email.smtp.useTLS;
|
||||||
|
} // lib.optionalAttrs (cfg.ldap != null) {
|
||||||
|
AUTH_PROVIDERS = {
|
||||||
|
ldap = {
|
||||||
|
type = "ldap";
|
||||||
|
title = "LDAP";
|
||||||
|
ldap = ldapConfig;
|
||||||
|
default = true;
|
||||||
};
|
};
|
||||||
in
|
};
|
||||||
{
|
IDENTITY_PROVIDERS = {
|
||||||
|
ldap = {
|
||||||
|
type = "ldap";
|
||||||
|
title = "LDAP";
|
||||||
|
ldap = ldapConfig;
|
||||||
|
mapping = cfg.ldap.mapping;
|
||||||
|
trusted_email = cfg.ldap.trustedEmail;
|
||||||
|
synced_fields = cfg.ldap.syncedFields;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
in {
|
||||||
# TODO cProfile; indico standalone command is *very* slow
|
# TODO cProfile; indico standalone command is *very* slow
|
||||||
# (~30s just to print the help)
|
# (~30s just to print the help)
|
||||||
|
|
||||||
|
@ -235,6 +271,91 @@ in
|
||||||
"postgresql://@/${cfg.user}?host=/run/postgresql";
|
"postgresql://@/${cfg.user}?host=/run/postgresql";
|
||||||
description = "Database URL.";
|
description = "Database URL.";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ldap = lib.mkOption {
|
||||||
|
type = lib.types.nullOr (lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
uri = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "LDAP server URI.";
|
||||||
|
};
|
||||||
|
|
||||||
|
bindDN = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "LDAP server bind DN.";
|
||||||
|
};
|
||||||
|
|
||||||
|
bindPassword = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "LDAP server bind password.";
|
||||||
|
};
|
||||||
|
|
||||||
|
uid = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "uid";
|
||||||
|
description = "LDAP UID attribute.";
|
||||||
|
};
|
||||||
|
|
||||||
|
userBaseDN = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "LDAP users base DN.";
|
||||||
|
};
|
||||||
|
|
||||||
|
userFilter = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "LDAP users filter.";
|
||||||
|
};
|
||||||
|
|
||||||
|
gid = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "gid";
|
||||||
|
description = "LDAP GID attribute.";
|
||||||
|
};
|
||||||
|
|
||||||
|
groupBaseDN = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "LDAP groups base DN.";
|
||||||
|
};
|
||||||
|
|
||||||
|
groupFilter = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
description = "LDAP groups filter.";
|
||||||
|
};
|
||||||
|
|
||||||
|
memberOf = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "memberOf";
|
||||||
|
description = "LDAP memberOf attribute.";
|
||||||
|
};
|
||||||
|
|
||||||
|
mapping = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf lib.types.str;
|
||||||
|
default = {
|
||||||
|
first_name = "givenName";
|
||||||
|
last_name = "sn";
|
||||||
|
email = "mail";
|
||||||
|
affiliation = "company";
|
||||||
|
phone = "telephoneNumber";
|
||||||
|
};
|
||||||
|
description = "Mapping between local and LDAP fields.";
|
||||||
|
};
|
||||||
|
|
||||||
|
trustedEmail = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Whether LDAP emails are to be trusted.";
|
||||||
|
};
|
||||||
|
|
||||||
|
syncedFields = lib.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
default = [ "first_name" "last_name" ];
|
||||||
|
description = "Fields to sync with LDAP server.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
default = null;
|
||||||
|
description = "LDAP authentication and identity provider configuration.";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
|
@ -254,12 +375,10 @@ in
|
||||||
package = pkgs.postgresql_16; # TODO add setting
|
package = pkgs.postgresql_16; # TODO add setting
|
||||||
# TODO db name != cfg.user
|
# TODO db name != cfg.user
|
||||||
ensureDatabases = [ cfg.user ];
|
ensureDatabases = [ cfg.user ];
|
||||||
ensureUsers = [
|
ensureUsers = [{
|
||||||
{
|
|
||||||
name = cfg.user;
|
name = cfg.user;
|
||||||
ensureDBOwnership = true;
|
ensureDBOwnership = true;
|
||||||
}
|
}];
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
environment.systemPackages =
|
environment.systemPackages =
|
||||||
|
@ -268,7 +387,7 @@ in
|
||||||
#!${pkgs.runtimeShell}
|
#!${pkgs.runtimeShell}
|
||||||
sudo=exec
|
sudo=exec
|
||||||
if [[ "$USER" != "indico" ]]; then
|
if [[ "$USER" != "indico" ]]; then
|
||||||
sudo='exec /run/wrappers/bin/sudo -u indico -E INDICO_CONFIG'
|
sudo='exec /run/wrappers/bin/sudo -u indico --preserve-env=INDICO_CONFIG'
|
||||||
fi
|
fi
|
||||||
export INDICO_CONFIG=${configFile}
|
export INDICO_CONFIG=${configFile}
|
||||||
$sudo ${lib.getExe' pythonEnv "indico"} "$@"
|
$sudo ${lib.getExe' pythonEnv "indico"} "$@"
|
||||||
|
@ -311,9 +430,7 @@ in
|
||||||
{
|
{
|
||||||
indico-db = lib.recursiveUpdate common {
|
indico-db = lib.recursiveUpdate common {
|
||||||
description = "Indico database preparation and upgrade";
|
description = "Indico database preparation and upgrade";
|
||||||
after = [
|
after = [ "postgresql.service" ];
|
||||||
"postgresql.service"
|
|
||||||
];
|
|
||||||
serviceConfig.Type = "oneshot";
|
serviceConfig.Type = "oneshot";
|
||||||
# Source: pretalx module ; passer par un service oneshot
|
# Source: pretalx module ; passer par un service oneshot
|
||||||
script = ''
|
script = ''
|
||||||
|
|
|
@ -69,7 +69,6 @@ python.pkgs.buildPythonApplication rec {
|
||||||
INDICO_NO_GIT = "true";
|
INDICO_NO_GIT = "true";
|
||||||
INDICO_MAP_VERSION = src.outputHash;
|
INDICO_MAP_VERSION = src.outputHash;
|
||||||
|
|
||||||
# TODO bin/maintenance/build-{wheel,assets}.py
|
|
||||||
build-system = [
|
build-system = [
|
||||||
python.pkgs.hatchling
|
python.pkgs.hatchling
|
||||||
python.pkgs.hatch-requirements-txt
|
python.pkgs.hatch-requirements-txt
|
||||||
|
@ -97,7 +96,7 @@ python.pkgs.buildPythonApplication rec {
|
||||||
# FIXME *why* is it required?
|
# FIXME *why* is it required?
|
||||||
makeCacheWritable = true;
|
makeCacheWritable = true;
|
||||||
|
|
||||||
npmFlags = [ "--verbose" ];
|
# npmFlags = [ "--verbose" ];
|
||||||
|
|
||||||
patches = [
|
patches = [
|
||||||
./remove_marshmallow_enum.patch
|
./remove_marshmallow_enum.patch
|
||||||
|
@ -137,11 +136,9 @@ python.pkgs.buildPythonApplication rec {
|
||||||
# TODO TODO ./bin/maintenance/build-assets.py
|
# TODO TODO ./bin/maintenance/build-assets.py
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# TODO build-assets.py
|
|
||||||
# build_urls_map.py tries to import indico.web.flask.app
|
# build_urls_map.py tries to import indico.web.flask.app
|
||||||
# which has not been installed yet at this stage
|
# which has not been installed yet at this stage
|
||||||
preBuild = ''
|
preBuild = ''
|
||||||
ls -lah
|
|
||||||
PYTHONPATH="$(pwd):$PYTHONPATH" ${lib.getExe python} bin/maintenance/build-assets.py indico --clean
|
PYTHONPATH="$(pwd):$PYTHONPATH" ${lib.getExe python} bin/maintenance/build-assets.py indico --clean
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
@ -233,9 +230,9 @@ python.pkgs.buildPythonApplication rec {
|
||||||
++ sentry-sdk_1.optional-dependencies.pure_eval
|
++ sentry-sdk_1.optional-dependencies.pure_eval
|
||||||
++ wtforms.optional-dependencies.email;
|
++ wtforms.optional-dependencies.email;
|
||||||
|
|
||||||
# passthru = {
|
optional-dependencies = {
|
||||||
# inherit python;
|
ldap = [ python.pkgs.python-ldap ];
|
||||||
# };
|
};
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
description = "Full-featured conferency lifecycle management and meeting/lecture scheduling tool";
|
description = "Full-featured conferency lifecycle management and meeting/lecture scheduling tool";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue