[pve-devel] [Patch V2 acme 09/12] Add function setup and teardown.
Wolfgang Link
w.link at proxmox.com
Tue Mar 31 12:08:48 CEST 2020
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.link at 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
More information about the pve-devel
mailing list