* [pmg-devel] [PATCH api 0/4] ACME updates @ 2021-03-17 10:02 Wolfgang Bumiller 2021-03-17 10:02 ` [pmg-devel] [PATCH api 1/4] add missing use statement Wolfgang Bumiller ` (4 more replies) 0 siblings, 5 replies; 7+ messages in thread From: Wolfgang Bumiller @ 2021-03-17 10:02 UTC (permalink / raw) To: pmg-devel This series contains a fixup and adds acme certificate renewal in pmg-daily. The pmg-daily code is based on the code in pveupdate. Wolfgang Bumiller (4): add missing use statement support forced account deactivation add PMG::NodeConfig::filter_domains_by_type helper check acme cert expiration in pmg-daily src/PMG/API2/ACME.pm | 27 ++++++++++++++++++++++----- src/PMG/API2/Certificates.pm | 13 +++++-------- src/PMG/NodeConfig.pm | 19 +++++++++++++++++++ src/bin/pmg-daily | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 82 insertions(+), 13 deletions(-) -- 2.20.1 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [pmg-devel] [PATCH api 1/4] add missing use statement 2021-03-17 10:02 [pmg-devel] [PATCH api 0/4] ACME updates Wolfgang Bumiller @ 2021-03-17 10:02 ` Wolfgang Bumiller 2021-03-17 10:02 ` [pmg-devel] [PATCH api 2/4] support forced account deactivation Wolfgang Bumiller ` (3 subsequent siblings) 4 siblings, 0 replies; 7+ messages in thread From: Wolfgang Bumiller @ 2021-03-17 10:02 UTC (permalink / raw) To: pmg-devel Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com> --- src/PMG/API2/Certificates.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PMG/API2/Certificates.pm b/src/PMG/API2/Certificates.pm index fc1025e..775d575 100644 --- a/src/PMG/API2/Certificates.pm +++ b/src/PMG/API2/Certificates.pm @@ -10,6 +10,7 @@ use PVE::Tools qw(extract_param file_get_contents file_set_contents); use PMG::CertHelpers; use PMG::NodeConfig; +use PMG::RS::Acme; use PMG::RS::CSR; use PMG::API2::ACMEPlugin; -- 2.20.1 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [pmg-devel] [PATCH api 2/4] support forced account deactivation 2021-03-17 10:02 [pmg-devel] [PATCH api 0/4] ACME updates Wolfgang Bumiller 2021-03-17 10:02 ` [pmg-devel] [PATCH api 1/4] add missing use statement Wolfgang Bumiller @ 2021-03-17 10:02 ` Wolfgang Bumiller 2021-03-17 10:33 ` Thomas Lamprecht 2021-03-17 10:02 ` [pmg-devel] [PATCH api 3/4] add PMG::NodeConfig::filter_domains_by_type helper Wolfgang Bumiller ` (2 subsequent siblings) 4 siblings, 1 reply; 7+ messages in thread From: Wolfgang Bumiller @ 2021-03-17 10:02 UTC (permalink / raw) To: pmg-devel Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com> --- src/PMG/API2/ACME.pm | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/PMG/API2/ACME.pm b/src/PMG/API2/ACME.pm index 60b5986..d6dbf2f 100644 --- a/src/PMG/API2/ACME.pm +++ b/src/PMG/API2/ACME.pm @@ -173,7 +173,7 @@ __PACKAGE__->register_method ({ }}); my $update_account = sub { - my ($param, $msg, %info) = @_; + my ($param, $msg, $force_deactivate, %info) = @_; my ($account_name, $account_file) = extract_account_name($param); @@ -190,7 +190,15 @@ my $update_account = sub { if ! -e $account_file; my $acme = PMG::RS::Acme->load($account_file); - $acme->update_account(\%info); + eval { + $acme->update_account(\%info); + }; + my $err = $@; + if ($force_deactivate) { + warn $err if $err; + } else { + die $2; + } if ($info{status} && $info{status} eq 'deactivated') { my $deactivated_name; for my $i (0..100) { @@ -239,9 +247,9 @@ __PACKAGE__->register_method ({ my $contact = $account_contact_from_param->($param); if (scalar @$contact) { - return $update_account->($param, 'update', contact => $contact); + return $update_account->($param, 'update', 0, contact => $contact); } else { - return $update_account->($param, 'refresh'); + return $update_account->($param, 'refresh', 0); } }}); @@ -311,6 +319,13 @@ __PACKAGE__->register_method ({ additionalProperties => 0, properties => { name => get_standard_option('pmg-acme-account-name'), + force => { + type => 'boolean', + description => + 'Delete account data even if the server refuses to deactivate the account.', + optional => 1, + default => 0, + }, }, }, returns => { @@ -319,7 +334,9 @@ __PACKAGE__->register_method ({ code => sub { my ($param) = @_; - return $update_account->($param, 'deactivate', status => 'deactivated'); + my $force_deactivate = extract_param($param, 'force'); + + return $update_account->($param, 'deactivate', $force_deactivate, status => 'deactivated'); }}); __PACKAGE__->register_method ({ -- 2.20.1 ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [pmg-devel] [PATCH api 2/4] support forced account deactivation 2021-03-17 10:02 ` [pmg-devel] [PATCH api 2/4] support forced account deactivation Wolfgang Bumiller @ 2021-03-17 10:33 ` Thomas Lamprecht 0 siblings, 0 replies; 7+ messages in thread From: Thomas Lamprecht @ 2021-03-17 10:33 UTC (permalink / raw) To: Wolfgang Bumiller, pmg-devel On 17.03.21 11:02, Wolfgang Bumiller wrote: > Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com> > --- > src/PMG/API2/ACME.pm | 27 ++++++++++++++++++++++----- > 1 file changed, 22 insertions(+), 5 deletions(-) > applied, thanks - squashed one change into it though. > diff --git a/src/PMG/API2/ACME.pm b/src/PMG/API2/ACME.pm > index 60b5986..d6dbf2f 100644 > --- a/src/PMG/API2/ACME.pm > +++ b/src/PMG/API2/ACME.pm > @@ -173,7 +173,7 @@ __PACKAGE__->register_method ({ > }}); > > my $update_account = sub { > - my ($param, $msg, %info) = @_; > + my ($param, $msg, $force_deactivate, %info) = @_; > > my ($account_name, $account_file) = extract_account_name($param); > > @@ -190,7 +190,15 @@ my $update_account = sub { > if ! -e $account_file; > > my $acme = PMG::RS::Acme->load($account_file); > - $acme->update_account(\%info); > + eval { > + $acme->update_account(\%info); > + }; > + my $err = $@; > + if ($force_deactivate) { > + warn $err if $err; > + } else { > + die $2; fixed up above typo and logic > + } > if ($info{status} && $info{status} eq 'deactivated') { > my $deactivated_name; > for my $i (0..100) { > @@ -239,9 +247,9 @@ __PACKAGE__->register_method ({ > > my $contact = $account_contact_from_param->($param); > if (scalar @$contact) { > - return $update_account->($param, 'update', contact => $contact); > + return $update_account->($param, 'update', 0, contact => $contact); > } else { > - return $update_account->($param, 'refresh'); > + return $update_account->($param, 'refresh', 0); > } > }}); > > @@ -311,6 +319,13 @@ __PACKAGE__->register_method ({ > additionalProperties => 0, > properties => { > name => get_standard_option('pmg-acme-account-name'), > + force => { > + type => 'boolean', > + description => > + 'Delete account data even if the server refuses to deactivate the account.', > + optional => 1, > + default => 0, > + }, > }, > }, > returns => { > @@ -319,7 +334,9 @@ __PACKAGE__->register_method ({ > code => sub { > my ($param) = @_; > > - return $update_account->($param, 'deactivate', status => 'deactivated'); > + my $force_deactivate = extract_param($param, 'force'); > + > + return $update_account->($param, 'deactivate', $force_deactivate, status => 'deactivated'); > }}); > > __PACKAGE__->register_method ({ > ^ permalink raw reply [flat|nested] 7+ messages in thread
* [pmg-devel] [PATCH api 3/4] add PMG::NodeConfig::filter_domains_by_type helper 2021-03-17 10:02 [pmg-devel] [PATCH api 0/4] ACME updates Wolfgang Bumiller 2021-03-17 10:02 ` [pmg-devel] [PATCH api 1/4] add missing use statement Wolfgang Bumiller 2021-03-17 10:02 ` [pmg-devel] [PATCH api 2/4] support forced account deactivation Wolfgang Bumiller @ 2021-03-17 10:02 ` Wolfgang Bumiller 2021-03-17 10:02 ` [pmg-devel] [PATCH api 4/4] check acme cert expiration in pmg-daily Wolfgang Bumiller 2021-03-17 10:34 ` [pmg-devel] applied-series: [PATCH api 0/4] ACME updates Thomas Lamprecht 4 siblings, 0 replies; 7+ messages in thread From: Wolfgang Bumiller @ 2021-03-17 10:02 UTC (permalink / raw) To: pmg-devel for reuse The private $filter_domains is still there to do the in-place modification it did before. Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com> --- src/PMG/API2/Certificates.pm | 12 ++++-------- src/PMG/NodeConfig.pm | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/PMG/API2/Certificates.pm b/src/PMG/API2/Certificates.pm index 775d575..b50addd 100644 --- a/src/PMG/API2/Certificates.pm +++ b/src/PMG/API2/Certificates.pm @@ -468,17 +468,13 @@ my $order_certificate = sub { my $filter_domains = sub { my ($acme_config, $type) = @_; - my $domains = $acme_config->{domains}; - foreach my $domain (sort keys %$domains) { - my $entry = $domains->{$domain}; - if (!(grep { $_ eq $type } PVE::Tools::split_list($entry->{usage}))) { - delete $domains->{$domain}; - } - } + my $domains = PMG::NodeConfig::filter_domains_by_type($acme_config->{domains}, $type); - if (!%$domains) { + if (!$domains) { raise("No domains configured for type '$type'\n", 400); } + + $acme_config->{domains} = $domains; }; __PACKAGE__->register_method ({ diff --git a/src/PMG/NodeConfig.pm b/src/PMG/NodeConfig.pm index 84c2141..19d23c3 100644 --- a/src/PMG/NodeConfig.pm +++ b/src/PMG/NodeConfig.pm @@ -222,4 +222,23 @@ sub get_acme_conf { return $res; } +# Helper to filter the domains hash. Returns `undef` if the list is empty. +sub filter_domains_by_type : prototype($$) { + my ($domains, $type) = @_; + + return undef if !$domains || !%$domains; + + my $out = {}; + + foreach my $domain (keys %$domains) { + my $entry = $domains->{$domain}; + if (grep { $_ eq $type } PVE::Tools::split_list($entry->{usage})) { + $out->{$domain} = $entry; + } + } + + return undef if !%$out; + return $out; +} + 1; -- 2.20.1 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [pmg-devel] [PATCH api 4/4] check acme cert expiration in pmg-daily 2021-03-17 10:02 [pmg-devel] [PATCH api 0/4] ACME updates Wolfgang Bumiller ` (2 preceding siblings ...) 2021-03-17 10:02 ` [pmg-devel] [PATCH api 3/4] add PMG::NodeConfig::filter_domains_by_type helper Wolfgang Bumiller @ 2021-03-17 10:02 ` Wolfgang Bumiller 2021-03-17 10:34 ` [pmg-devel] applied-series: [PATCH api 0/4] ACME updates Thomas Lamprecht 4 siblings, 0 replies; 7+ messages in thread From: Wolfgang Bumiller @ 2021-03-17 10:02 UTC (permalink / raw) To: pmg-devel Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com> --- src/bin/pmg-daily | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/bin/pmg-daily b/src/bin/pmg-daily index 8865c94..d454c62 100755 --- a/src/bin/pmg-daily +++ b/src/bin/pmg-daily @@ -8,6 +8,7 @@ use strict; use warnings; use Time::Local; +use PVE::Certificate; use PVE::SafeSyslog; use PVE::INotify; use PVE::RESTEnvironment; @@ -18,6 +19,9 @@ use PMG::ClusterConfig; use PMG::DBTools; use PMG::API2::Subscription; use PMG::API2::APT; +use PMG::API2::Certificates; +use PMG::CertHelpers; +use PMG::NodeConfig; $SIG{'__WARN__'} = sub { my $err = $@; @@ -89,5 +93,37 @@ PMG::Utils::service_cmd('pmg-smtp-filter', 'restart') if $restart_filter; # run bayes database maintainance system('sa-learn --force-expire >/dev/null 2>&1'); +eval { + my $node_config = PMG::NodeConfig::load_config(); + my $acme_node_config = PMG::NodeConfig::get_acme_conf($node_config); + my $acme_domains = $acme_node_config && $acme_node_config->{domains}; + if ($acme_domains) { + my %typed_domains = map { + $_ => PMG::NodeConfig::filter_domains_by_type($acme_domains, $_) + } qw(api smtp); + + foreach my $type (qw(api smtp)) { + next if !$typed_domains{$type}; + + # Guard both certificates separately. + eval { + my $cert = PMG::CertHelpers::cert_path($type); + if (!-e $cert) { + syslog ('info', "ACME config found for '$type' certificate, but no custom certificate exists. Skipping ACME renewal until initial certificate has been deployed."); + next; + } + + if (PVE::Certificate::check_expiry($cert, time() + 30*24*60*60)) { + PMG::API2::Certificates->renew_acme_cert({ node => $nodename, type => $type }); + } else { + syslog ('info', "Custom '$type' certificate does not expire soon, skipping ACME renewal."); + } + }; + syslog ('err', "Renewing '$type' ACME certificate failed: $@") if $@; + } + } +}; +syslog ('err', "Renewing ACME certificate failed: $@") if $@; + exit (0); -- 2.20.1 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [pmg-devel] applied-series: [PATCH api 0/4] ACME updates 2021-03-17 10:02 [pmg-devel] [PATCH api 0/4] ACME updates Wolfgang Bumiller ` (3 preceding siblings ...) 2021-03-17 10:02 ` [pmg-devel] [PATCH api 4/4] check acme cert expiration in pmg-daily Wolfgang Bumiller @ 2021-03-17 10:34 ` Thomas Lamprecht 4 siblings, 0 replies; 7+ messages in thread From: Thomas Lamprecht @ 2021-03-17 10:34 UTC (permalink / raw) To: Wolfgang Bumiller, pmg-devel On 17.03.21 11:02, Wolfgang Bumiller wrote: > This series contains a fixup and adds acme certificate renewal in > pmg-daily. The pmg-daily code is based on the code in pveupdate. > > Wolfgang Bumiller (4): > add missing use statement > support forced account deactivation > add PMG::NodeConfig::filter_domains_by_type helper > check acme cert expiration in pmg-daily > > src/PMG/API2/ACME.pm | 27 ++++++++++++++++++++++----- > src/PMG/API2/Certificates.pm | 13 +++++-------- > src/PMG/NodeConfig.pm | 19 +++++++++++++++++++ > src/bin/pmg-daily | 36 ++++++++++++++++++++++++++++++++++++ > 4 files changed, 82 insertions(+), 13 deletions(-) > applied series, thanks! ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2021-03-17 10:34 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2021-03-17 10:02 [pmg-devel] [PATCH api 0/4] ACME updates Wolfgang Bumiller 2021-03-17 10:02 ` [pmg-devel] [PATCH api 1/4] add missing use statement Wolfgang Bumiller 2021-03-17 10:02 ` [pmg-devel] [PATCH api 2/4] support forced account deactivation Wolfgang Bumiller 2021-03-17 10:33 ` Thomas Lamprecht 2021-03-17 10:02 ` [pmg-devel] [PATCH api 3/4] add PMG::NodeConfig::filter_domains_by_type helper Wolfgang Bumiller 2021-03-17 10:02 ` [pmg-devel] [PATCH api 4/4] check acme cert expiration in pmg-daily Wolfgang Bumiller 2021-03-17 10:34 ` [pmg-devel] applied-series: [PATCH api 0/4] ACME updates Thomas Lamprecht
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox