Redo LDAP config in the main configuration and add role mappings

This commit is contained in:
Janne Heß 2022-01-21 21:20:02 +01:00 committed by Graham Christensen
parent 76b4b43ac5
commit 61d74a7194
4 changed files with 71 additions and 47 deletions

View file

@ -108,47 +108,70 @@ Using LDAP as authentication backend (optional)
Instead of using Hydra\'s built-in user management you can optionally Instead of using Hydra\'s built-in user management you can optionally
use LDAP to manage roles and users. use LDAP to manage roles and users.
The `hydra-server` accepts the environment variable This is configured by defining the `<ldap>` block in the configuration file.
*HYDRA\_LDAP\_CONFIG*. The value of the variable should point to a valid In this block it\'s possible to configure the authentication plugin in the
YAML file containing the Catalyst LDAP configuration. The format of the `<config>` block, all options are directly passed to `Catalyst::Authentication
configuration file is describe in the ::Store::LDAP`. The documentation for the available settings can be found [here]
[*Catalyst::Authentication::Store::LDAP* (https://metacpan.org/pod/Catalyst::Authentication::Store::LDAP#CONFIGURATION-OPTIONS).
documentation](https://metacpan.org/pod/Catalyst::Authentication::Store::LDAP#CONFIGURATION-OPTIONS).
An example is given below.
Roles can be assigned to users based on their LDAP group membership Note that the bind password (if needed) should be supplied as an included file to
(*use\_roles: 1* in the below example). For a user to have the role prevent it from leaking to the Nix store.
*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.
credential: Roles can be assigned to users based on their LDAP group membership. For this
class: Password to work *use\_roles = 1* needs to be defined for the authentication plugin.
password_field: password LDAP groups can then be mapped to Hydra roles using the `<role_mapping>` block.
password_type: self_check
store: Example configuration:
class: LDAP ```
ldap_server: localhost <ldap>
ldap_server_options.timeout: 30 <config>
binddn: "cn=root,dc=example" <credential>
bindpw: notapassword class = Password
start_tls: 0 password_field = password
start_tls_options: password_type= self_check
verify: none </credential>
user_basedn: "ou=users,dc=example" <store>
user_filter: "(&(objectClass=inetOrgPerson)(cn=%s))" class = LDAP
user_scope: one ldap_server = localhost
user_field: cn <ldap_server_options>
user_search_options: timeout = 30
deref: always debug = 2
use_roles: 1 </ldap_server_options>
role_basedn: "ou=groups,dc=example" binddn = "cn=root,dc=example"
role_filter: "(&(objectClass=groupOfNames)(member=%s))" bindpw = notapassword
role_scope: one start_tls = 0
role_field: cn <start_tls_options>
role_value: dn verify = none
role_search_options: </start_tls_options>
deref: always user_basedn = "ou=users,dc=example"
user_filter = "(&(objectClass=inetOrgPerson)(cn=%s))"
user_scope = one
user_field = cn
<user_search_options>
deref = always
</user_search_options>
# 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
<role_search_options>
deref = always
</role_search_options>
</config>
<role_mapping>
# 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
</role_mapping>
</ldap>
```
This example configuration also enables the (very verbose) LDAP debug logging
by setting `config.ldap_server_options.debug`.
Embedding Extra HTML Embedding Extra HTML
-------------------- --------------------

View file

@ -522,7 +522,6 @@
TextTable TextTable
UUID4Tiny UUID4Tiny
XMLSimple XMLSimple
YAML
]; ];
}; };

View file

@ -6,6 +6,7 @@ use parent 'Catalyst';
use Moose; use Moose;
use Hydra::Plugin; use Hydra::Plugin;
use Hydra::Model::DB; use Hydra::Model::DB;
use Hydra::Helper::Nix qw(getHydraConfig);
use Catalyst::Runtime '5.70'; use Catalyst::Runtime '5.70';
use Catalyst qw/ConfigLoader use Catalyst qw/ConfigLoader
Static::Simple Static::Simple
@ -19,7 +20,6 @@ use Catalyst qw/ConfigLoader
PrometheusTiny/, PrometheusTiny/,
'-Log=warn,fatal,error'; '-Log=warn,fatal,error';
use CatalystX::RoleApplicator; use CatalystX::RoleApplicator;
use YAML qw(LoadFile);
use Path::Class 'file'; use Path::Class 'file';
our $VERSION = '0.01'; our $VERSION = '0.01';
@ -43,9 +43,7 @@ __PACKAGE__->config(
role_field => "role", role_field => "role",
}, },
}, },
ldap => $ENV{'HYDRA_LDAP_CONFIG'} ? LoadFile( ldap => Hydra::Helper::Nix::getHydraConfig->{'ldap'}->{'config'}
file($ENV{'HYDRA_LDAP_CONFIG'})
) : undef
}, },
'Plugin::ConfigLoader' => { 'Plugin::ConfigLoader' => {
driver => { driver => {

View file

@ -59,7 +59,9 @@ sub doLDAPLogin {
my $user = $c->find_user({ username => $username }); my $user = $c->find_user({ username => $username });
my $LDAPUser = $c->find_user({ username => $username }, 'ldap'); 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) { if (!$user) {
$c->model('DB::Users')->create( $c->model('DB::Users')->create(
@ -79,8 +81,10 @@ sub doLDAPLogin {
}); });
} }
$user->userroles->delete; $user->userroles->delete;
if (@LDAPRoles) { foreach my $ldap_role (@LDAPRoles) {
$user->userroles->create({ role => (substr $_, 6) }) for @LDAPRoles; if (%role_mapping{$ldap_role}) {
$user->userroles->create({ role => $role_mapping{$ldap_role} });
}
} }
$c->set_authenticated($user); $c->set_authenticated($user);
} }