From: Stoiko Ivanov <s.ivanov@proxmox.com>
To: Thomas Lamprecht <t.lamprecht@proxmox.com>
Cc: pmg-devel@lists.proxmox.com
Subject: Re: [pmg-devel] applied: [PATCH api] oidc realm: add more flexiple access-role assignment
Date: Thu, 27 Feb 2025 11:01:17 +0100 [thread overview]
Message-ID: <20250227110117.41c6b97b@rosa.proxmox.com> (raw)
In-Reply-To: <20250227095152.281531-1-t.lamprecht@proxmox.com>
Thanks! from a quick look - it seems sensible, and the naming is in order.
one typo and 2 minor nits inline:
On Thu, 27 Feb 2025 10:51:52 +0100
Thomas Lamprecht <t.lamprecht@proxmox.com> wrote:
> deprecate the fixed role assignment property and replace it with one
> that allows to select the source of the role, for now allow static,
> which is equivalent with what we had, and also to query the role from
> a role claim, so that the OIDC provider can return the correct role
> inside the returned user information.
>
> Tested the dynamic role assignment with keycload by setting up an
> 'User Attribute' Mapper for a client and added added the respective
> user attribute to some test user.
>
> Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
> ---
>
> It's not much code and most is schema and parsing, the implementation
> itself is pretty straigt forward, basically the only questionable thing
> is naming of properties.
>
> src/PMG/API2/OIDC.pm | 26 ++++++++++++++++++++-
> src/PMG/Auth/OIDC.pm | 54 +++++++++++++++++++++++++++++++++++++++++---
> 2 files changed, 76 insertions(+), 4 deletions(-)
>
> diff --git a/src/PMG/API2/OIDC.pm b/src/PMG/API2/OIDC.pm
> index 92ff88d..20acc41 100644
> --- a/src/PMG/API2/OIDC.pm
> +++ b/src/PMG/API2/OIDC.pm
> @@ -13,6 +13,7 @@ use PVE::JSONSchema qw(get_standard_option);
> use PVE::RESTHandler;
>
> use PMG::AccessControl;
> +use PMG::Auth::OIDC;
> use PMG::Auth::Plugin;
> use PMG::RESTEnvironment;
>
> @@ -204,7 +205,30 @@ __PACKAGE__->register_method ({
> if (defined(my $family_name = $info->{'family_name'})) {
> $entry->{lastname} = $family_name;
> }
> - $entry->{role} = $config->{'autocreate-role'} // 'audit';
> +
> + # NOTE: 'autocreate-role' is deprecated and has less priority than the more
> + # flexible 'autocreate-role-assignment'
> + $entry->{role} = $config->{'autocreate-role'} // 'audit'; # default
> + if (my $role_assignment_raw = $config->{'autocreate-role-assignment'}) {
> + my $role_assignment =
> + PMG::Auth::OIDC::parse_autocreate_role_assignment($role_assignment_raw);
> +
> + if ($role_assignment->{source} eq 'fixed') {
> + $entry->{role} = $role_assignment->{'fixed-role'};
> + } elsif ($role_assignment->{source} eq 'from-claim') {
> + my $role_attr = $role_assignment->{'role-claim'};
> + if (my $role = $info->{$role_attr}) {
> + $role = lc($role); # normalize to lower-case
> + die "required '$role_attr' role-claim attribute not found, cannot autocreate user\n"
> + if $role !~ /^(?:admin|qmanager|audit|helpdesk)$/;
> + $entry->{role} = $role;
> + } else {
> + die "required '$role_attr' role-claim attribute not found, cannot autocreate user\n";
> + }
> + } else {
> + die "unkown role assignment source '$role_assignment->{source}' - implement me";
> + }
> + }
> $entry->{userid} = $username;
> $entry->{username} = $unique_name;
> $entry->{realm} = $realm;
> diff --git a/src/PMG/Auth/OIDC.pm b/src/PMG/Auth/OIDC.pm
> index 4129d47..9082c75 100755
> --- a/src/PMG/Auth/OIDC.pm
> +++ b/src/PMG/Auth/OIDC.pm
> @@ -4,6 +4,8 @@ use strict;
> use warnings;
>
> use PVE::Tools;
> +use PVE::JSONSchema qw(parse_property_string);
> +
> use PMG::Auth::Plugin;
>
> use base qw(PMG::Auth::Plugin);
> @@ -12,6 +14,44 @@ sub type {
> return 'oidc';
> }
>
> +my $autocreate_role_assignment_format = {
> + source => {
> + type => 'string',
> + enum => ['fixed', 'from-claim'],
> + default => 'fixed',
> + description => "How the access role for a newly auto-created user should be selected.",
> + },
> + 'fixed-role' => {
> + type => 'string',
> + enum => ['admin', 'qmanager', 'audit', 'helpdesk'],
> + default => 'audit',
> + optional => 1,
> + description => "The fixed role that should be assigned to auto-created users.",
> + },
> + 'role-claim' => {
> + description => "OIDC claim used to assign the unique username.",
> + type => 'string',
> + default => 'role',
> + optional => 1,
> + pattern => qr/^[a-zA-Z0-9._:-]+$/,
> + },
> +};
> +
> +
> +sub parse_autocreate_role_assignment {
> + my ($raw) = @_;
> + return undef if !$raw or !length($raw);
> +
> + my $role_assignment = parse_property_string($autocreate_role_assignment_format, $raw);
> + $role_assignment->{'fixed-role'} = 'audit'
> + if $role_assignment->{'source'} eq 'fixed' && !defined($role_assignment->{'fixed-role'});
> +
> + $role_assignment->{'role-claim'} = 'role'
> + if $role_assignment->{'source'} eq 'from-clain' && !defined($role_assignment->{'role-claim'});
`s/from-clain/from-claim/`
> +
> + return $role_assignment;
> +}
> +
> sub properties {
> return {
> 'issuer-url' => {
> @@ -39,13 +79,20 @@ sub properties {
> type => 'boolean',
> default => 0,
> },
> - 'autocreate-role' => {
> - description => "Automatically create users with a specific role.",
> + 'autocreate-role' => { # NOTE: depreacated since the beginning, just here for compat
nit: `s/depreacated/deprecated/` (had to google myself, as I always get
that wrong)
> + description => "Automatically create users with a specific role."
> + ." NOTE: Depreacated, favor 'autocreate-role-assignment'",
nit: deprecated
> type => 'string',
> enum => ['admin', 'qmanager', 'audit', 'helpdesk'],
> default => 'audit',
> optional => 1,
> },
> + 'autocreate-role-assignment' => {
> + description => "Defines which role should be assigned to auto-created users.",
> + type => 'string', format => $autocreate_role_assignment_format,
> + default => 'source=fixed,fixed-role=auditor',
> + optional => 1,
> + },
> 'username-claim' => {
> description => "OpenID Connect claim used to generate the unique username.",
> type => 'string',
> @@ -84,7 +131,8 @@ sub options {
> 'client-id' => {},
> 'client-key' => { optional => 1 },
> autocreate => { optional => 1 },
> - 'autocreate-role' => { optional => 1 },
> + 'autocreate-role' => { optional => 1 }, # NOTE: depreacated in favor of 'autocreate-role-assignment'
nit: deprecated
> + 'autocreate-role-assignment' => { optional => 1 },
> 'username-claim' => { optional => 1, fixed => 1 },
> prompt => { optional => 1 },
> scopes => { optional => 1 },
_______________________________________________
pmg-devel mailing list
pmg-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pmg-devel
next prev parent reply other threads:[~2025-02-27 10:01 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-27 9:51 Thomas Lamprecht
2025-02-27 10:01 ` Stoiko Ivanov [this message]
2025-02-27 10:04 ` Thomas Lamprecht
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=20250227110117.41c6b97b@rosa.proxmox.com \
--to=s.ivanov@proxmox.com \
--cc=pmg-devel@lists.proxmox.com \
--cc=t.lamprecht@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