From: Christoph Heiss <c.heiss@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH access-control v2 5/5] ldap: check bind credentials with LDAP directory directly on change
Date: Mon, 24 Jul 2023 11:03:50 +0200 [thread overview]
Message-ID: <20230724090408.221672-6-c.heiss@proxmox.com> (raw)
In-Reply-To: <20230724090408.221672-1-c.heiss@proxmox.com>
Instead of letting a sync fail on the first try due to e.g. bad bind
credentials, give the user some direct feedback when trying to save a
LDAP realm in the UI.
This is part of the result of a previous discussion [0], and the same
approach is already implemented for PBS [1].
[0] https://lists.proxmox.com/pipermail/pve-devel/2023-May/056839.html
[1] https://lists.proxmox.com/pipermail/pbs-devel/2023-June/006237.html
Signed-off-by: Christoph Heiss <c.heiss@proxmox.com>
---
Changes v1 -> v2:
* Fixed updating a LDAP realm via pveum/pvesh/etc (thanks Friedrich!)
Summary: $plugin->on_update_hook() was passed only the updated
parameters, meaning if only e.g. the `comment` field was updated,
other options like `server1` were missing and thus the connect/bind
would fail - it worked via the GUI, as that always passes all set
options.
* Replaced ternary operator with simplier short-circuit ||
One thing to note might be that this "regresses" the UI in that you
cannot create or change realm settings, if the target LDAP server cannot
be reached.
After a short off-list discussion with Sterzy, a 'force' API
parameter (and accompanying checkbox in the UI) could be added to bypass
this "restriction", although open to discussion how useful that even
would be.
src/PVE/API2/Domains.pm | 7 +++++--
src/PVE/Auth/LDAP.pm | 19 +++++++++++++------
2 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/src/PVE/API2/Domains.pm b/src/PVE/API2/Domains.pm
index 9332aa7..68e3c7d 100644
--- a/src/PVE/API2/Domains.pm
+++ b/src/PVE/API2/Domains.pm
@@ -231,10 +231,13 @@ __PACKAGE__->register_method ({
}
my $opts = $plugin->options();
+
+ # Some update hooks, like e.g. LDAP, which tries to connect and bind to the target
+ # server, need the rest of config too => use the already-merged config
if ($delete_pw || defined($password)) {
- $plugin->on_update_hook($realm, $config, password => $password);
+ $plugin->on_update_hook($realm, $ids->{$realm}, password => $password);
} else {
- $plugin->on_update_hook($realm, $config);
+ $plugin->on_update_hook($realm, $ids->{$realm});
}
cfs_write_file($domainconfigfile, $cfg);
diff --git a/src/PVE/Auth/LDAP.pm b/src/PVE/Auth/LDAP.pm
index e0ead1b..ec4cd31 100755
--- a/src/PVE/Auth/LDAP.pm
+++ b/src/PVE/Auth/LDAP.pm
@@ -181,7 +181,7 @@ sub get_scheme_and_port {
}
sub connect_and_bind {
- my ($class, $config, $realm) = @_;
+ my ($class, $config, $realm, $param) = @_;
my $servers = [$config->{server1}];
push @$servers, $config->{server2} if $config->{server2};
@@ -212,7 +212,7 @@ sub connect_and_bind {
if ($config->{bind_dn}) {
my $bind_dn = $config->{bind_dn};
- my $bind_pass = ldap_get_credentials($realm);
+ my $bind_pass = $param->{password} || ldap_get_credentials($realm);
die "missing password for realm $realm\n" if !defined($bind_pass);
PVE::LDAP::ldap_bind($ldap, $bind_dn, $bind_pass);
} elsif ($config->{cert} && $config->{certkey}) {
@@ -427,20 +427,27 @@ sub on_add_hook {
my ($class, $realm, $config, %param) = @_;
if (defined($param{password})) {
+ $class->connect_and_bind($config, $realm, \%param);
ldap_set_credentials($param{password}, $realm);
} else {
- ldap_delete_credentials($realm);
+ # Still validate the bind credentials, even if no user/password is given
+ $class->connect_and_bind($config, $realm);
}
}
sub on_update_hook {
my ($class, $realm, $config, %param) = @_;
- return if !exists($param{password});
-
- if (defined($param{password})) {
+ if (!exists($param{password})) {
+ # Password wasn't changed, login still needs to be validated in case bind_dn changed
+ $class->connect_and_bind($config, $realm);
+ } elsif (defined($param{password})) {
+ # Password was updated, validate the login and only then store it
+ $class->connect_and_bind($config, $realm, \%param);
ldap_set_credentials($param{password}, $realm);
} else {
+ # Otherwise, the password was removed, so delete it
+ $class->connect_and_bind($config, $realm, \%param);
ldap_delete_credentials($realm);
}
}
--
2.41.0
next prev parent reply other threads:[~2023-07-24 9:04 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-24 9:03 [pve-devel] [PATCH common/access-control v2 0/5] improve LDAP DN and bind creds checking on creation/change Christoph Heiss
2023-07-24 9:03 ` [pve-devel] [PATCH common v2 1/5] schema: add `ldap-dn` format for validating LDAP distinguished names Christoph Heiss
2023-07-24 9:03 ` [pve-devel] [PATCH common v2 2/5] test: add test cases for new 'ldap-dn' schema format Christoph Heiss
2023-07-24 9:03 ` [pve-devel] [PATCH common v2 3/5] ldap: handle errors explicitly everywhere instead of simply `die`ing Christoph Heiss
2023-07-24 9:03 ` [pve-devel] [PATCH access-control v2 4/5] ldap: validate LDAP DNs using the `ldap-dn` schema format Christoph Heiss
2023-07-24 9:03 ` Christoph Heiss [this message]
2023-07-24 13:18 ` [pve-devel] [PATCH common/access-control v2 0/5] improve LDAP DN and bind creds checking on creation/change Friedrich Weber
2023-07-27 9:54 ` Lukas Wagner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230724090408.221672-6-c.heiss@proxmox.com \
--to=c.heiss@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.