From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 82B7881ED3 for ; Fri, 26 Nov 2021 14:55:44 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 4DC8619230 for ; Fri, 26 Nov 2021 14:55:44 +0100 (CET) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id 44F7F191D5 for ; Fri, 26 Nov 2021 14:55:40 +0100 (CET) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 1BFA146AA6 for ; Fri, 26 Nov 2021 14:55:40 +0100 (CET) From: Wolfgang Bumiller To: pmg-devel@lists.proxmox.com Date: Fri, 26 Nov 2021 14:55:08 +0100 Message-Id: <20211126135524.117846-5-w.bumiller@proxmox.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211126135524.117846-1-w.bumiller@proxmox.com> References: <20211126135524.117846-1-w.bumiller@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.450 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [ruledb.pm, tfa.pm, tfaconfig.pm, accesscontrol.pm, objectgrouphelpers.pm, rules.pm, config.pm, quarantine.pm] Subject: [pmg-devel] [PATCH api 4/6] add tfa config api X-BeenThere: pmg-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Mail Gateway development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 26 Nov 2021 13:55:44 -0000 Signed-off-by: Wolfgang Bumiller --- src/Makefile | 1 + src/PMG/API2/Config.pm | 6 ++ src/PMG/API2/TFAConfig.pm | 142 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 src/PMG/API2/TFAConfig.pm diff --git a/src/Makefile b/src/Makefile index c2bf2c9..f08be0f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -149,6 +149,7 @@ LIBSOURCES = \ PMG/API2/Quarantine.pm \ PMG/API2/AccessControl.pm \ PMG/API2/TFA.pm \ + PMG/API2/TFAConfig.pm \ PMG/API2/ObjectGroupHelpers.pm \ PMG/API2/Rules.pm \ PMG/API2/RuleDB.pm \ diff --git a/src/PMG/API2/Config.pm b/src/PMG/API2/Config.pm index c5697e1..19ae8f1 100644 --- a/src/PMG/API2/Config.pm +++ b/src/PMG/API2/Config.pm @@ -27,6 +27,7 @@ use PMG::API2::DKIMSign; use PMG::API2::SACustom; use PMG::API2::PBS::Remote; use PMG::API2::ACME; +use PMG::API2::TFAConfig; use base qw(PVE::RESTHandler); @@ -105,6 +106,11 @@ __PACKAGE__->register_method ({ path => 'acme', }); +__PACKAGE__->register_method ({ + subclass => "PMG::API2::TFAConfig", + path => 'tfa', +}); + __PACKAGE__->register_method ({ name => 'index', path => '', diff --git a/src/PMG/API2/TFAConfig.pm b/src/PMG/API2/TFAConfig.pm new file mode 100644 index 0000000..dbe8969 --- /dev/null +++ b/src/PMG/API2/TFAConfig.pm @@ -0,0 +1,142 @@ +package PMG::API2::TFAConfig; + +use strict; +use warnings; + +use PVE::Exception qw(raise raise_perm_exc raise_param_exc); +use PVE::JSONSchema qw(get_standard_option); +use PVE::RESTHandler; +use PVE::Tools qw(extract_param); + +use PMG::AccessControl; +use PMG::RESTEnvironment; +use PMG::TFAConfig; +use PMG::UserConfig; +use PMG::Utils; + +use base qw(PVE::RESTHandler); + +my $wa_config_schema = { + type => 'object', + properties => { + rp => { + type => 'string', + description => + "Relying party name. Any text identifier.\n" + ."Changing this *may* break existing credentials.", + }, + origin => { + type => 'string', + optional => 1, + description => + 'Site origin. Must be a `https://` URL (or `http://localhost`).' + .' Should contain the address users type in their browsers to access the web' + ." interface.\n" + .'Changing this *may* break existing credentials.', + }, + id => { + type => 'string', + description => + "Relying part ID. Must be the domain name without protocol, port or location.\n" + .'Changing this *will* break existing credentials.', + }, + }, +}; + +my %return_properties = $wa_config_schema->{properties}->%*; +$return_properties{$_}->{optional} = 1 for keys %return_properties; + +my $wa_config_return_schema = { + type => 'object', + properties => \%return_properties, +}; + +__PACKAGE__->register_method({ + name => 'get_webauthn_config', + path => 'webauthn', + method => 'GET', + protected => 1, + permissions => { user => 'all' }, + description => "Read the webauthn configuration.", + parameters => { + additionalProperties => 0, + properties => {}, + }, + returns => { + optional => 1, + $wa_config_schema->%*, + }, + code => sub { + my ($param) = @_; + + my $cfg = PMG::TFAConfig->new(); + return $cfg->get_webauthn_config(); + }}); + +__PACKAGE__->register_method({ + name => 'update_webauthn_config', + path => 'webauthn', + method => 'PUT', + protected => 1, + proxyto => 'master', + permissions => { check => [ 'admin' ] }, + description => "Read the webauthn configuration.", + parameters => { + additionalProperties => 0, + properties => { + $wa_config_schema->{properties}->%*, + delete => { + type => 'string', enum => [keys $wa_config_schema->{properties}->%*], + description => "A list of settings you want to delete.", + optional => 1, + }, + digest => { + type => 'string', + description => 'Prevent changes if current configuration file has different SHA1 digest.' + .' This can be used to prevent concurrent modifications.', + maxLength => 40, + optional => 1, + }, + }, + }, + returns => { type => 'null' }, + code => sub { + my ($param) = @_; + + my $digest = extract_param($param, 'digest'); + my $delete = extract_param($param, 'delete'); + + PMG::TFAConfig::lock_config(sub { + my $cfg = PMG::TFAConfig->new(); + + my ($config_digest, $wa) = $cfg->get_webauthn_config(); + if (defined($digest)) { + PVE::Tools::assert_if_modified($digest, $config_digest); + } + + foreach my $opt (PVE::Tools::split_list($delete)) { + delete $wa->{$opt}; + } + foreach my $opt (keys %$param) { + my $value = $param->{$opt}; + if (length($value)) { + $wa->{$opt} = $value; + } else { + delete $wa->{$opt}; + } + } + + # to remove completely, pass `undef`: + if (!%$wa) { + $wa = undef; + } + + $cfg->set_webauthn_config($wa); + + $cfg->write(); + }); + + return; + }}); + +1; -- 2.30.2