[pve-devel] [PATCH access-control] auth ldap/ad: make password a parameter for the api
Dominik Csapak
d.csapak at proxmox.com
Tue Apr 7 12:59:01 CEST 2020
Instead of simply requiring it to exist in /etc/pve.
Takes after the password handling of CIFS in pve-storage.
Signed-off-by: Dominik Csapak <d.csapak at proxmox.com>
---
i guess if we have to add this pattern again somewhere, it would be
useful to refactor it to the SectionConfig, but for now we simply duplicate
PVE/API2/Domains.pm | 24 +++++++++++++++
PVE/Auth/AD.pm | 1 +
PVE/Auth/LDAP.pm | 73 ++++++++++++++++++++++++++++++++++++++++++++-
PVE/Auth/Plugin.pm | 15 ++++++++++
4 files changed, 112 insertions(+), 1 deletion(-)
diff --git a/PVE/API2/Domains.pm b/PVE/API2/Domains.pm
index 8ae1db0..c6c4d9d 100644
--- a/PVE/API2/Domains.pm
+++ b/PVE/API2/Domains.pm
@@ -88,6 +88,9 @@ __PACKAGE__->register_method ({
code => sub {
my ($param) = @_;
+ # always extract, add it with hook
+ my $password = extract_param($param, 'password');
+
PVE::Auth::Plugin::lock_domain_config(
sub {
@@ -117,6 +120,13 @@ __PACKAGE__->register_method ({
$ids->{$realm} = $config;
+ my $opts = $plugin->options();
+ if (defined($password) && !defined($opts->{password})) {
+ $password = undef;
+ warn "ignoring password parameter";
+ }
+ $plugin->on_add_hook($realm, $config, password => $password);
+
cfs_write_file($domainconfigfile, $cfg);
}, "add auth server failed");
@@ -137,6 +147,9 @@ __PACKAGE__->register_method ({
code => sub {
my ($param) = @_;
+ # always extract, update in hook
+ my $password = extract_param($param, 'password');
+
PVE::Auth::Plugin::lock_domain_config(
sub {
@@ -171,6 +184,14 @@ __PACKAGE__->register_method ({
$ids->{$realm}->{$p} = $config->{$p};
}
+ my $opts = $plugin->options();
+ if (defined($opts->{password})) {
+ $plugin->on_update_hook($realm, $config, password => $password);
+ } else {
+ warn "ignoring password parameter" if defined($password);
+ $plugin->on_update_hook($realm, $config);
+ }
+
cfs_write_file($domainconfigfile, $cfg);
}, "update auth server failed");
@@ -238,6 +259,9 @@ __PACKAGE__->register_method ({
die "domain '$realm' does not exist\n" if !$ids->{$realm};
+ my $plugin = PVE::Auth::Plugin->lookup($ids->{$realm}->{type});
+ $plugin->on_delete_hook($realm, $ids->{$realm});
+
delete $ids->{$realm};
cfs_write_file($domainconfigfile, $cfg);
diff --git a/PVE/Auth/AD.pm b/PVE/Auth/AD.pm
index 4f40be3..24b0e9f 100755
--- a/PVE/Auth/AD.pm
+++ b/PVE/Auth/AD.pm
@@ -83,6 +83,7 @@ sub options {
certkey => { optional => 1 },
base_dn => { optional => 1 },
bind_dn => { optional => 1 },
+ password => { optional => 1 },
user_attr => { optional => 1 },
filter => { optional => 1 },
sync_attributes => { optional => 1 },
diff --git a/PVE/Auth/LDAP.pm b/PVE/Auth/LDAP.pm
index 905cc47..1b2c606 100755
--- a/PVE/Auth/LDAP.pm
+++ b/PVE/Auth/LDAP.pm
@@ -37,6 +37,11 @@ sub properties {
optional => 1,
maxLength => 256,
},
+ password => {
+ description => "LDAP bind password. Will be stored in '/etc/pve/priv/ldap/<REALM>.pw'.",
+ type => 'string',
+ optional => 1,
+ },
verify => {
description => "Verify the server's SSL certificate",
type => 'boolean',
@@ -126,6 +131,7 @@ sub options {
server2 => { optional => 1 },
base_dn => {},
bind_dn => { optional => 1 },
+ password => { optional => 1 },
user_attr => {},
port => { optional => 1 },
secure => { optional => 1 },
@@ -185,7 +191,7 @@ sub connect_and_bind {
if ($config->{bind_dn}) {
$bind_dn = $config->{bind_dn};
- $bind_pass = PVE::Tools::file_read_firstline("/etc/pve/priv/ldap/${realm}.pw");
+ $bind_pass = ldap_get_credentials($realm);
die "missing password for realm $realm\n" if !defined($bind_pass);
}
@@ -343,4 +349,69 @@ sub authenticate_user {
return 1;
}
+my $ldap_pw_dir = "/etc/pve/priv/ldap";
+
+sub ldap_cred_filename {
+ my ($realm) = @_;
+ return "${ldap_pw_dir}/${realm}.pw";
+}
+
+sub ldap_set_credentials {
+ my ($password, $realm) = @_;
+
+ my $file = ldap_cred_filename($realm);
+ mkdir $ldap_pw_dir;
+
+ PVE::Tools::file_set_contents($file, $password);
+
+ return $file;
+}
+
+sub ldap_get_credentials {
+ my ($realm) = @_;
+
+ my $file = ldap_cred_filename($realm);
+
+ if (-e $file) {
+ return PVE::Tools::file_read_firstline($file);
+ }
+ return undef;
+}
+
+sub ldap_delete_credentials {
+ my ($realm) = @_;
+
+ my $file = ldap_cred_filename($realm);
+
+ unlink($file) or warn "removing ldap credentials '$file' failed: $!\n";
+}
+
+sub on_add_hook {
+ my ($class, $realm, $config, %param) = @_;
+
+ if (defined($param{password})) {
+ ldap_set_credentials($param{password}, $realm);
+ } else {
+ ldap_delete_credentials($realm);
+ }
+}
+
+sub on_update_hook {
+ my ($class, $realm, $config, %param) = @_;
+
+ return if !exists($param{password});
+
+ if (defined($param{password})) {
+ ldap_set_credentials($param{password}, $realm);
+ } else {
+ ldap_delete_credentials($realm);
+ }
+}
+
+sub on_delete_hook {
+ my ($class, $realm, $config) = @_;
+
+ ldap_delete_credentials($realm);
+}
+
1;
diff --git a/PVE/Auth/Plugin.pm b/PVE/Auth/Plugin.pm
index 7a08d27..7843599 100755
--- a/PVE/Auth/Plugin.pm
+++ b/PVE/Auth/Plugin.pm
@@ -268,4 +268,19 @@ sub delete_user {
# do nothing by default
}
+sub on_add_hook {
+ my ($class, $realm, $config, %param) = @_;
+ # do nothing by default
+}
+
+sub on_update_hook {
+ my ($class, $realm, $config, %param) = @_;
+ # do nothing by default
+}
+
+sub on_delete_hook {
+ my ($class, $realm, $config) = @_;
+ # do nothing by default
+}
+
1;
--
2.20.1
More information about the pve-devel
mailing list