From: Alexis | Dawnalex <alexis@danwalex.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH access-control] Add OpenID group sync in pve-access-control
Date: Thu, 15 Feb 2024 22:27:00 +0100 [thread overview]
Message-ID: <20240215212739.602-1-alexis@danwalex.com> (raw)
This commit adds the group synchronization feature to OpenID authentication, allowing automatic user group mapping and updates based on the OpenID provider information. Enhances integration and access control within Proxmox VE.
Signed-off-by: Alexis | Dawnalex <alexis@danwalex.com>
---
src/PVE/API2/OpenId.pm | 83 +++++++++++++++++++++++++++++++++++++++---
src/PVE/Auth/OpenId.pm | 18 ++++++++-
2 files changed, 95 insertions(+), 6 deletions(-)
diff --git a/src/PVE/API2/OpenId.pm b/src/PVE/API2/OpenId.pm
index 77410e6..52511ce 100644
--- a/src/PVE/API2/OpenId.pm
+++ b/src/PVE/API2/OpenId.pm
@@ -35,6 +35,7 @@ my $lookup_openid_auth = sub {
issuer_url => $config->{'issuer-url'},
client_id => $config->{'client-id'},
client_key => $config->{'client-key'},
+
};
$openid_config->{prompt} = $config->{'prompt'} if defined($config->{'prompt'});
@@ -150,6 +151,7 @@ __PACKAGE__->register_method ({
CSRFPreventionToken => { type => 'string' },
cap => { type => 'object' }, # computed api permissions
clustername => { type => 'string', optional => 1 },
+ groups => get_standard_option('group-list'),
},
},
permissions => { user => 'world' },
@@ -190,6 +192,8 @@ __PACKAGE__->register_method ({
}
my $username = "${unique_name}\@${realm}";
+
+
# first, check if $username respects our naming conventions
PVE::Auth::Plugin::verify_username($username);
@@ -210,16 +214,23 @@ __PACKAGE__->register_method ({
if (defined(my $family_name = $info->{'family_name'})) {
$entry->{lastname} = $family_name;
}
-
+ if (defined(my $groups = $info->{'groups'})) {
+ sync_group($username, $info, $config, $groups);
+ }
$usercfg->{users}->{$username} = $entry;
-
cfs_write_file("user.cfg", $usercfg);
}, "autocreate openid user failed");
} else {
+
+ if (defined(my $groups = $info->{'groups'})) {
+ my $usercfg = cfs_read_file("user.cfg");
+ sync_group($username, $info, $config, $groups);
+ }
# test if user exists and is enabled
$rpcenv->check_user_enabled($username);
}
-
+ #check
+
my $ticket = PVE::AccessControl::assemble_ticket($username);
my $csrftoken = PVE::AccessControl::assemble_csrf_prevention_token($username);
my $cap = $rpcenv->compute_api_permission($username);
@@ -243,7 +254,69 @@ __PACKAGE__->register_method ({
die PVE::Exception->new("authentication failure\n", code => 401);
}
- PVE::Cluster::log_msg('info', 'root@pam', "successful openid auth for user '$res->{username}'");
-
+ PVE::Cluster::log_msg('info', 'root@pam', "successful authentication (OpenID) for user '$res->{username}'");
return $res;
}});
+
+#function to create groups with lock user config and create group
+sub create_group {
+ my ($group, $comment) = @_;
+ my $param = {
+ groupid => $group,
+ comment => $comment,
+ };
+ eval {
+ PVE::AccessControl::lock_user_config(
+ sub {
+
+ my $usercfg = cfs_read_file("user.cfg");
+
+ my $group = $param->{groupid};
+
+ die "group '$group' already exists\n"
+ if $usercfg->{groups}->{$group};
+
+ $usercfg->{groups}->{$group} = { users => {} };
+
+ $usercfg->{groups}->{$group}->{comment} = $param->{comment} if $param->{comment};
+
+
+ cfs_write_file("user.cfg", $usercfg);
+ }, "create group failed");
+ };
+}
+## function to sync groups waiting update to move without API2
+sub sync_group {
+ my ($username, $info, $config, $groups) = @_;
+ my $usercfg = cfs_read_file("user.cfg");
+ # First Check if the group name respects our naming conventions
+ my @filtered_groups = grep { /^[a-zA-Z0-9_\-]+$/ } @{$groups};
+ # Then add Add filter regex to check and check the regex is valid
+ my $filter_regex = $config->{'groups-filter'};
+
+ if (defined($filter_regex)) {
+ eval { qr/$filter_regex/ };
+ if ($@) {
+ die "Invalid groups-filter regex: $@\n";
+ }
+ @filtered_groups = grep { /$filter_regex/ } @filtered_groups;
+ }
+ if (defined($config->{'autocreate-groups'})){
+
+ foreach my $group (@filtered_groups) {
+
+ unless ($usercfg->{groups}->{$group}) {
+
+ create_group($group, "Autocreated by OpenID Connect");
+ }
+ PVE::AccessControl::add_user_group($username, $usercfg, $group);
+ };
+ }
+ else{
+ foreach my $group (@filtered_groups) {
+ PVE::AccessControl::add_user_group($username, $usercfg, $group);
+ };
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/PVE/Auth/OpenId.pm b/src/PVE/Auth/OpenId.pm
index c8e4db9..6404b49 100755
--- a/src/PVE/Auth/OpenId.pm
+++ b/src/PVE/Auth/OpenId.pm
@@ -37,6 +37,18 @@ sub properties {
type => 'boolean',
default => 0,
},
+ "autocreate-groups" => {
+ description => "Automatically create users if they do not exist.",
+ optional => 1,
+ type => 'boolean',
+ default => 0,
+ },
+ "groups-filter" => {
+ description => "Only allow users in these groups.",
+ optional => 1,
+ type => 'string',
+ maxLength => 256,
+ },
"username-claim" => {
description => "OpenID claim used to generate the unique username.",
type => 'string',
@@ -62,7 +74,8 @@ sub properties {
type => 'string',
pattern => '^[^\x00-\x1F\x7F <>#"]*$', # Prohibit characters not allowed in URI RFC 2396.
optional => 1,
- },
+ },
+
};
}
@@ -72,12 +85,15 @@ sub options {
"client-id" => {},
"client-key" => { optional => 1 },
autocreate => { optional => 1 },
+ "autocreate-groups" => { optional => 1},
+ "groups-filter" => { optional => 1 },
"username-claim" => { optional => 1, fixed => 1 },
prompt => { optional => 1 },
scopes => { optional => 1 },
"acr-values" => { optional => 1 },
default => { optional => 1 },
comment => { optional => 1 },
+
};
}
--
2.43.0.windows.1
next reply other threads:[~2024-02-15 21:33 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-02-15 21:27 Alexis | Dawnalex [this message]
2024-02-15 21:27 ` [pve-devel] [PATCH manager] Update UI and backend integration for OpenID group creation Alexis | Dawnalex
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=20240215212739.602-1-alexis@danwalex.com \
--to=alexis@danwalex.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox