[pmg-devel] [PATCH pmg-api v3 4/8] config: add plugin system for realms & add openid type realms

Christoph Heiss c.heiss at proxmox.com
Fri Oct 18 14:07:40 CEST 2024


This patch should probably be split into two, one adding the actual
plugin system and the second one adding the openid realm definitions -
even the patch subject suggests that it does two completely different
things.

Would also make things a bit clearer.

On Mon, Jun 24, 2024 at 11:08:46AM GMT, Markus Frank wrote:
[..]
> diff --git a/src/PMG/Auth/Plugin.pm b/src/PMG/Auth/Plugin.pm
> new file mode 100755
> index 0000000..dc88aff
> --- /dev/null
> +++ b/src/PMG/Auth/Plugin.pm
> @@ -0,0 +1,193 @@
> +package PMG::Auth::Plugin;
> +
> +use strict;
> +use warnings;
> +
> +use Digest::SHA;
> +use Encode;
> +
> +use PMG::Utils;
> +use PVE::INotify;
> +use PVE::JSONSchema qw(get_standard_option);
> +use PVE::Schema::Auth;
> +use PVE::SectionConfig;
> +use PVE::Tools;
> +
> +use base qw(PVE::SectionConfig);
> +
> +my $domainconfigfile = "realms.cfg";
> +my $lockfile = "/var/lock/realms.lck";

Should be /var/lock/pmg-realms.lck, to make it clear that it belongs to
PMG - in line with all the other lockfiles PMG creates/uses.

> +
> +sub read_realms_conf {
> +    my ($filename, $fh) = @_;
> +
> +    my $raw;
> +    $raw = do { local $/ = undef; <$fh> } if defined($fh);
> +
> +    return  PMG::Auth::Plugin->parse_config($filename, $raw);
              ^
Unnecessary whitespace

> +}
> +
> +sub write_realms_conf {
> +    my ($filename, $fh, $cfg) = @_;
> +
> +    my $raw = PMG::Auth::Plugin->write_config($filename, $cfg);
> +
> +    PVE::Tools::safe_print($filename, $fh, $raw);
> +}
> +
> +PVE::INotify::register_file(
> +    $domainconfigfile,
> +    "/etc/pmg/realms.cfg",
> +    \&read_realms_conf,
> +    \&write_realms_conf,
> +    undef,
> +    always_call_parser => 1,
> +);
> +
> +sub lock_domain_config {
> +    my ($code, $errmsg) = @_;
> +
> +    PVE::Tools::lock_file($lockfile, undef, $code);
> +    if (my $err = $@) {
> +	$errmsg ? die "$errmsg: $err" : die $err;
> +    }
> +}
> +
> +my $realm_regex = qr/[A-Za-z][A-Za-z0-9\.\-_]+/;
> +
> +sub pmg_verify_realm {

Can be a `my sub`, since it's not used anywhere else AFAICS, right?

> +    my ($realm, $noerr) = @_;
> +
> +    if ($realm !~ m/^${realm_regex}$/) {
> +	return undef if $noerr;
> +	die "value does not look like a valid realm\n";
> +    }
> +    return $realm;
> +}
> +
> +my $defaultData = {
> +    propertyList => {
> +	type => { description => "Realm type." },
> +	realm => get_standard_option('realm'),
> +    },
> +};
> +
> +sub private {
> +    return $defaultData;
> +}
> +
> +sub parse_section_header {
> +    my ($class, $line) = @_;
> +
> +    if ($line =~ m/^(\S+):\s*(\S+)\s*$/) {
> +	my ($type, $realm) = (lc($1), $2);
> +	my $errmsg = undef; # set if you want to skip whole section
> +	eval { pmg_verify_realm($realm); };
> +	$errmsg = $@ if $@;
> +	my $config = {}; # to return additional attributes
> +	return ($type, $realm, $errmsg, $config);
> +    }
> +    return undef;
> +}
> +
> +sub parse_config {
> +    my ($class, $filename, $raw) = @_;
> +
> +    my $cfg = $class->SUPER::parse_config($filename, $raw);
> +
> +    my $default;
> +    foreach my $realm (keys %{$cfg->{ids}}) {
> +	my $data = $cfg->{ids}->{$realm};
> +	# make sure there is only one default marker
> +	if ($data->{default}) {
> +	    if ($default) {
> +		delete $data->{default};
> +	    } else {
> +		$default = $realm;
> +	    }
> +	}
> +
> +	if ($data->{comment}) {
> +	    $data->{comment} = PVE::Tools::decode_text($data->{comment});
> +	}
> +
> +    }
> +
> +    # add default domains
> +    $cfg->{ids}->{pmg}->{type} = 'pmg'; # force type
> +    $cfg->{ids}->{pmg}->{comment} = "Proxmox Mail Gateway authentication server"
> +	if !$cfg->{ids}->{pmg}->{comment};

As noted in the cover letter, there should be separate PAM and PMG
realms, much like PVE/PBS.




More information about the pmg-devel mailing list