These are the two main functions that a plugin should offer. Setup creates the endpoint at which Letsencrypt does the validation, teardown does the cleanup.
Signed-off-by: Wolfgang Link <w.l...@proxmox.com> --- src/PVE/ACME.pm | 43 ++++++++++++++++++++++++++++++++++++++ src/PVE/ACME/StandAlone.pm | 16 +++++--------- 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/src/PVE/ACME.pm b/src/PVE/ACME.pm index 114eb41..c10dca2 100644 --- a/src/PVE/ACME.pm +++ b/src/PVE/ACME.pm @@ -23,6 +23,9 @@ file_set_contents file_get_contents ); +use PVE::ACME::Challenge; +use PVE::ACME::StandAlone; + Crypt::OpenSSL::RSA->import_random_seed(); my $LETSENCRYPT_STAGING = 'https://acme-staging-v02.api.letsencrypt.org/directory'; @@ -493,6 +496,46 @@ sub request_challenge_validation { return $return; } +# Setup the challange +# At the moment two plugin types are supproted +# standalone: start an webserver an wait for the challenge +# dns: add an txt record over the given API +sub setup { + my ($acme, $auth, $node_config) = @_; + + my $fqdn = $auth->{identifier}->{value}; + my $plugin_data = {}; + my $plugin_type = "standalone"; + my $plugin_conf = PVE::ACME::Challenge->load_config(); + + # default is standalone if no plugin is set (old config) + my $index = 0; + while (defined($node_config->{$index})) { + if ($node_config->{$index}->{domain} eq $fqdn && + defined($node_config->{$index}->{plugin})) { + $plugin_data = $plugin_conf->{ids}->{$node_config->{$index}->{plugin}}; + $plugin_type = $plugin_data->{type}; + + # Alias mode is only supported for DNSChallange + $plugin_data->{alias} = $node_config->{$index}->{alias} if + $node_config->{$index}->{alias}; + last; + } + $index++; + } + die if $plugin_type eq "standalone"; + my $plugin = PVE::ACME::Challenge->lookup($plugin_data->{type}); + return $plugin->setup($acme, $auth, $plugin_data); +} + +# +# +sub teardown { + my ($self) = @_; + + $self->teardown(); +} + # actually 'do' a $method request on $url # $data: input for JWS, optional # $use_jwk: use JWK instead of KID in JWD (see sub jws) diff --git a/src/PVE/ACME/StandAlone.pm b/src/PVE/ACME/StandAlone.pm index ac75184..8fc8dc9 100644 --- a/src/PVE/ACME/StandAlone.pm +++ b/src/PVE/ACME/StandAlone.pm @@ -31,15 +31,8 @@ sub options { sub setup { my ($class, $acme, $authorization) = @_; - my $challenges = $authorization->{challenges}; - die "no challenges defined in authorization\n" if !$challenges; - - my $http_challenges = [ grep {$_->{type} eq 'http-01'} @$challenges ]; - die "no http-01 challenge defined in authorization\n" - if ! scalar $http_challenges; - - my $http_challenge = $http_challenges->[0]; - + print "Setting up webserver\n"; + my $http_challenge = PVE::ACME::extract_challenge($authorization->{challenges}, "http-01"); die "no token found in http-01 challenge\n" if !$http_challenge->{token}; my $key_authorization = $acme->key_authorization($http_challenge->{token}); @@ -47,7 +40,7 @@ sub setup { my $server = HTTP::Daemon->new( LocalPort => 80, ReuseAddr => 1, - ) or die "Failed to initialize HTTP daemon\n"; + ) or die "Failed to initialize HTTP daemon\n"; my $pid = fork() // die "Failed to fork HTTP daemon - $!\n"; if ($pid) { my $self = { @@ -62,7 +55,8 @@ sub setup { } else { while (my $c = $server->accept()) { while (my $r = $c->get_request()) { - if ($r->method() eq 'GET' and $r->uri->path eq "/.well-known/acme-challenge/$http_challenge->{token}") { + if ($r->method() eq 'GET' and + $r->uri->path eq "/.well-known/acme-challenge/$http_challenge->{token}") { my $resp = HTTP::Response->new(200, 'OK', undef, $key_authorization); $resp->request($r); $c->send_response($resp); -- 2.20.1 _______________________________________________ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel