public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
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




             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
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal