From 61d74a71944513a99a095e08fa443211fb4bbf41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Janne=20He=C3=9F?= Date: Fri, 21 Jan 2022 21:20:02 +0100 Subject: [PATCH] Redo LDAP config in the main configuration and add role mappings --- doc/manual/src/configuration.md | 101 +++++++++++++++++++------------ flake.nix | 1 - src/lib/Hydra.pm | 6 +- src/lib/Hydra/Controller/User.pm | 10 ++- 4 files changed, 71 insertions(+), 47 deletions(-) diff --git a/doc/manual/src/configuration.md b/doc/manual/src/configuration.md index e0a20d3c..fe1a8402 100644 --- a/doc/manual/src/configuration.md +++ b/doc/manual/src/configuration.md @@ -108,47 +108,70 @@ Using LDAP as authentication backend (optional) Instead of using Hydra\'s built-in user management you can optionally use LDAP to manage roles and users. -The `hydra-server` accepts the environment variable -*HYDRA\_LDAP\_CONFIG*. The value of the variable should point to a valid -YAML file containing the Catalyst LDAP configuration. The format of the -configuration file is describe in the -[*Catalyst::Authentication::Store::LDAP* -documentation](https://metacpan.org/pod/Catalyst::Authentication::Store::LDAP#CONFIGURATION-OPTIONS). -An example is given below. +This is configured by defining the `` block in the configuration file. +In this block it\'s possible to configure the authentication plugin in the +`` block, all options are directly passed to `Catalyst::Authentication +::Store::LDAP`. The documentation for the available settings can be found [here] +(https://metacpan.org/pod/Catalyst::Authentication::Store::LDAP#CONFIGURATION-OPTIONS). -Roles can be assigned to users based on their LDAP group membership -(*use\_roles: 1* in the below example). For a user to have the role -*admin* assigned to them they should be in the group *hydra\_admin*. In -general any LDAP group of the form *hydra\_some\_role* (notice the -*hydra\_* prefix) will work. +Note that the bind password (if needed) should be supplied as an included file to +prevent it from leaking to the Nix store. - credential: - class: Password - password_field: password - password_type: self_check - store: - class: LDAP - ldap_server: localhost - ldap_server_options.timeout: 30 - binddn: "cn=root,dc=example" - bindpw: notapassword - start_tls: 0 - start_tls_options: - verify: none - user_basedn: "ou=users,dc=example" - user_filter: "(&(objectClass=inetOrgPerson)(cn=%s))" - user_scope: one - user_field: cn - user_search_options: - deref: always - use_roles: 1 - role_basedn: "ou=groups,dc=example" - role_filter: "(&(objectClass=groupOfNames)(member=%s))" - role_scope: one - role_field: cn - role_value: dn - role_search_options: - deref: always +Roles can be assigned to users based on their LDAP group membership. For this +to work *use\_roles = 1* needs to be defined for the authentication plugin. +LDAP groups can then be mapped to Hydra roles using the `` block. + +Example configuration: +``` + + + + class = Password + password_field = password + password_type= self_check + + + class = LDAP + ldap_server = localhost + + timeout = 30 + debug = 2 + + binddn = "cn=root,dc=example" + bindpw = notapassword + start_tls = 0 + + verify = none + + user_basedn = "ou=users,dc=example" + user_filter = "(&(objectClass=inetOrgPerson)(cn=%s))" + user_scope = one + user_field = cn + + deref = always + + # Important for role mappings to work: + use_roles = 1 + role_basedn = "ou=groups,dc=example" + role_filter = "(&(objectClass=groupOfNames)(member=%s))" + role_scope = one + role_field = cn + role_value = dn + + deref = always + + + + # Make all users in the hydra_admin group Hydra admins + hydra_admin = admin + # Allow all users in the dev group to restart jobs + dev = restart-jobs + + +``` + +This example configuration also enables the (very verbose) LDAP debug logging +by setting `config.ldap_server_options.debug`. Embedding Extra HTML -------------------- diff --git a/flake.nix b/flake.nix index b61d7d0d..736cbd53 100644 --- a/flake.nix +++ b/flake.nix @@ -522,7 +522,6 @@ TextTable UUID4Tiny XMLSimple - YAML ]; }; diff --git a/src/lib/Hydra.pm b/src/lib/Hydra.pm index 07aec922..47ada081 100644 --- a/src/lib/Hydra.pm +++ b/src/lib/Hydra.pm @@ -6,6 +6,7 @@ use parent 'Catalyst'; use Moose; use Hydra::Plugin; use Hydra::Model::DB; +use Hydra::Helper::Nix qw(getHydraConfig); use Catalyst::Runtime '5.70'; use Catalyst qw/ConfigLoader Static::Simple @@ -19,7 +20,6 @@ use Catalyst qw/ConfigLoader PrometheusTiny/, '-Log=warn,fatal,error'; use CatalystX::RoleApplicator; -use YAML qw(LoadFile); use Path::Class 'file'; our $VERSION = '0.01'; @@ -43,9 +43,7 @@ __PACKAGE__->config( role_field => "role", }, }, - ldap => $ENV{'HYDRA_LDAP_CONFIG'} ? LoadFile( - file($ENV{'HYDRA_LDAP_CONFIG'}) - ) : undef + ldap => Hydra::Helper::Nix::getHydraConfig->{'ldap'}->{'config'} }, 'Plugin::ConfigLoader' => { driver => { diff --git a/src/lib/Hydra/Controller/User.pm b/src/lib/Hydra/Controller/User.pm index 01f59dee..08b2c91b 100644 --- a/src/lib/Hydra/Controller/User.pm +++ b/src/lib/Hydra/Controller/User.pm @@ -59,7 +59,9 @@ sub doLDAPLogin { my $user = $c->find_user({ username => $username }); my $LDAPUser = $c->find_user({ username => $username }, 'ldap'); - my @LDAPRoles = grep { (substr $_, 0, 6) eq "hydra_" } $LDAPUser->roles; + my @LDAPRoles = $LDAPUser->roles; + my %ldap_config = %{Hydra::Helper::Nix::getHydraConfig->{'ldap'}}; + my %role_mapping = $ldap_config{'role_mapping'} ? %{$ldap_config{'role_mapping'}} : (); if (!$user) { $c->model('DB::Users')->create( @@ -79,8 +81,10 @@ sub doLDAPLogin { }); } $user->userroles->delete; - if (@LDAPRoles) { - $user->userroles->create({ role => (substr $_, 6) }) for @LDAPRoles; + foreach my $ldap_role (@LDAPRoles) { + if (%role_mapping{$ldap_role}) { + $user->userroles->create({ role => $role_mapping{$ldap_role} }); + } } $c->set_authenticated($user); }