From: Mira Limbeck <m.limbeck@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: Re: [pve-devel] [PATCH access-control v3 1/1] fix #4411: openid: add logic for openid groups support
Date: Wed, 12 Feb 2025 15:51:39 +0100 [thread overview]
Message-ID: <f3732723-d617-47a9-a7be-652f0893b6ed@proxmox.com> (raw)
In-Reply-To: <20250211054029.1269099-4-thomas@atskinner.net>
On 2/11/25 06:40, Thomas Skinner wrote:
> Signed-off-by: Thomas Skinner <thomas@atskinner.net>
> ---
> src/PVE/API2/OpenId.pm | 79 ++++++++++++++++++++++++++++++++++++++++
> src/PVE/AccessControl.pm | 2 +-
> src/PVE/Auth/OpenId.pm | 33 +++++++++++++++++
> src/PVE/Auth/Plugin.pm | 1 +
> 4 files changed, 114 insertions(+), 1 deletion(-)
>
> diff --git a/src/PVE/API2/OpenId.pm b/src/PVE/API2/OpenId.pm
> index 77410e6..818175e 100644
> --- a/src/PVE/API2/OpenId.pm
> +++ b/src/PVE/API2/OpenId.pm
> @@ -13,6 +13,7 @@ use PVE::Cluster qw(cfs_read_file cfs_write_file);
> use PVE::AccessControl;
> use PVE::JSONSchema qw(get_standard_option);
> use PVE::Auth::Plugin;
> +use PVE::Auth::OpenId;
>
> use PVE::RESTHandler;
>
> @@ -220,6 +221,84 @@ __PACKAGE__->register_method ({
> $rpcenv->check_user_enabled($username);
> }
>
> + if (defined(my $groups_claim = $config->{'groups-claim'})) {
> + if (defined(my $groups_list = $info->{$groups_claim})) {
> + if (ref($groups_list) eq 'ARRAY') {
> + PVE::AccessControl::lock_user_config(sub {
> + my $usercfg = cfs_read_file("user.cfg");
> +
> + # replace any invalid characters with
> + my $replace_character = $config->{'groups-replace-character'} // '_';
> + my $oidc_groups = { map {
> + $_ =~ s/[^$PVE::Auth::Plugin::groupname_regex_chars]/$replace_character/gr => 1
> + } $groups_list->@* };
maybe we could log any of those replacements here? doing this silently
may lead to confusion when groups don't match
> +
> + # add realm name as suffix to group
> + my $suffixed_oidc_groups;
> + for my $group (keys %$oidc_groups) {
> + $suffixed_oidc_groups->{"$group-$realm"} = 1;
> + }
> + $oidc_groups = $suffixed_oidc_groups;
> +
> + # get groups that exist in OIDC and PVE
> + my $groups_intersect;
> + for my $group (keys %$oidc_groups) {
> + $groups_intersect->{$group} = 1 if $usercfg->{groups}->{$group};
> + }
> +
> + if ($config->{'groups-autocreate'}) {
> + # populate all groups in claim
> + $groups_intersect = $oidc_groups;
> + my $groups_to_create;
> + for my $group (keys %$oidc_groups) {
> + $groups_to_create->{$group} = 1 if !$usercfg->{groups}->{$group};
> + }
> + if ($groups_to_create) {
> + # log a messages about created groups here
> + my $groups_to_create_string = join(', ', sort keys %$groups_to_create);
> + syslog(
> + 'info',
> + "groups created automatically from openid claim: $groups_to_create_string"
> + );
> + }
> + }
> +
> + # if groups should be overwritten, delete all the users groups first
> + if ( $config->{'groups-overwrite'} ) {
> + PVE::AccessControl::delete_user_group(
> + $username,
> + $usercfg,
> + );
> + syslog(
> + 'info',
> + "openid overwrite groups enabled; user '$username' removed from all groups"
> + );
> + }
> +
> + # ensure user is a member of the groups
> + for my $group (keys %$groups_intersect) {
> + PVE::AccessControl::add_user_group(
> + $username,
> + $usercfg,
> + $group
> + );
> + }
> + my $groups_intersect_string = join(', ', sort keys %$groups_intersect);
> + syslog(
> + 'info',
> + "openid user '$username' added to groups: $groups_intersect_string"
> + );
> +
> + cfs_write_file("user.cfg", $usercfg);
> + }, "openid group mapping failed");
> + } else {
> + syslog('err', "openid groups list is not an array; groups will not be updated");
> + }
> + } else {
> + syslog('err', "openid groups claim '$groups_claim' is not found in claims");
> + }
> + }
> +
> my $ticket = PVE::AccessControl::assemble_ticket($username);
> my $csrftoken = PVE::AccessControl::assemble_csrf_prevention_token($username);
> my $cap = $rpcenv->compute_api_permission($username);
> diff --git a/src/PVE/AccessControl.pm b/src/PVE/AccessControl.pm
> index 47f2d38..7493c57 100644
> --- a/src/PVE/AccessControl.pm
> +++ b/src/PVE/AccessControl.pm
> @@ -1293,7 +1293,7 @@ PVE::JSONSchema::register_format('pve-groupid', \&verify_groupname);
> sub verify_groupname {
> my ($groupname, $noerr) = @_;
>
> - if ($groupname !~ m/^[A-Za-z0-9\.\-_]+$/) {
> + if ($groupname !~ m/^[$PVE::Auth::Plugin::groupname_regex_chars]+$/) {
>
> die "group name '$groupname' contains invalid characters\n" if !$noerr;
>
> diff --git a/src/PVE/Auth/OpenId.pm b/src/PVE/Auth/OpenId.pm
> index c8e4db9..fd1cd6f 100755
> --- a/src/PVE/Auth/OpenId.pm
> +++ b/src/PVE/Auth/OpenId.pm
> @@ -9,6 +9,9 @@ use PVE::Cluster qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file
>
> use base qw(PVE::Auth::Plugin);
>
> +# include all printable ascii characters
> +my $openid_claim_regex = qr/[ -~]+/;
> +
> sub type {
> return 'openid';
> }
> @@ -42,6 +45,32 @@ sub properties {
> type => 'string',
> optional => 1,
> },
> + "groups-claim" => {
> + description => "OpenID claim used to retrieve groups with.",
> + type => 'string',
> + pattern => $openid_claim_regex,
> + maxLength => 256,
> + optional => 1,
> + },
> + "groups-autocreate" => {
> + description => "Automatically create groups if they do not exist.",
> + optional => 1,
> + type => 'boolean',
> + default => 0,
> + },
> + "groups-overwrite" => {
> + description => "All groups will be overwritten for the user on login.",
> + type => 'boolean',
> + default => 0,
> + optional => 1,
> + },
> + "groups-replace-character" => {
> + description => "Character used to replace any invalid characters in groups from provider.",
> + type => 'string',
> + pattern => qr/^[$PVE::Auth::Plugin::groupname_regex_chars]$/,
> + default => '_',
> + optional => 1,
> + },
> prompt => {
> description => "Specifies whether the Authorization Server prompts the End-User for"
> ." reauthentication and consent.",
> @@ -73,6 +102,10 @@ sub options {
> "client-key" => { optional => 1 },
> autocreate => { optional => 1 },
> "username-claim" => { optional => 1, fixed => 1 },
> + "groups-claim" => { optional => 1 },
> + "groups-autocreate" => { optional => 1 },
> + "groups-overwrite" => { optional => 1 },
> + "groups-replace-character" => { optional => 1},
> prompt => { optional => 1 },
> scopes => { optional => 1 },
> "acr-values" => { optional => 1 },
> diff --git a/src/PVE/Auth/Plugin.pm b/src/PVE/Auth/Plugin.pm
> index 763239f..7617044 100755
> --- a/src/PVE/Auth/Plugin.pm
> +++ b/src/PVE/Auth/Plugin.pm
> @@ -31,6 +31,7 @@ sub lock_domain_config {
>
> our $realm_regex = qr/[A-Za-z][A-Za-z0-9\.\-_]+/;
> our $user_regex = qr![^\s:/]+!;
> +our $groupname_regex_chars = qr/A-Za-z0-9\.\-_/;
>
> PVE::JSONSchema::register_format('pve-realm', \&pve_verify_realm);
> sub pve_verify_realm {
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
next prev parent reply other threads:[~2025-02-12 14:51 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-11 5:40 [pve-devel] [PATCH SERIES access-control/docs/manager/proxmox-openid v3] fix #4411: add support for openid groups Thomas Skinner
2025-02-11 5:40 ` [pve-devel] [PATCH docs v3 1/1] fix #4411: openid: add docs for openid groups support Thomas Skinner
2025-02-11 5:40 ` [pve-devel] [PATCH proxmox-openid v3 1/1] fix #4411: openid: add library code for generic id token claim support Thomas Skinner
2025-02-11 5:40 ` [pve-devel] [PATCH access-control v3 1/1] fix #4411: openid: add logic for openid groups support Thomas Skinner
2025-02-12 14:51 ` Mira Limbeck [this message]
2025-02-13 11:03 ` Fabian Grünbichler
2025-03-17 12:18 ` Fabian Grünbichler
2025-03-18 9:34 ` Mira Limbeck
2025-03-19 10:30 ` Thomas Skinner
2025-02-11 5:40 ` [pve-devel] [PATCH manager v3 1/1] fix #4411: openid: add ui config " Thomas Skinner
2025-02-12 14:47 ` [pve-devel] [PATCH SERIES access-control/docs/manager/proxmox-openid v3] fix #4411: add support for openid groups Mira Limbeck
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=f3732723-d617-47a9-a7be-652f0893b6ed@proxmox.com \
--to=m.limbeck@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.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal