]> git.proxmox.com Git - proxmox-acme.git/blob - src/PVE/ACME/StandAlone.pm
plugins: refactor setup/teardown signatures
[proxmox-acme.git] / src / PVE / ACME / StandAlone.pm
1 package PVE::ACME::StandAlone;
2
3 use strict;
4 use warnings;
5
6 use HTTP::Daemon;
7 use HTTP::Response;
8
9 use base qw(PVE::ACME::Challenge);
10
11 sub supported_challenge_types {
12 return { 'http-01' => 1 };
13 }
14
15 sub type {
16 return 'standalone';
17 }
18
19 sub properties {
20 return {};
21 }
22
23 sub options {
24 return {
25 nodes => { optional => 1 },
26 disable => { optional => 1 },
27 };
28 }
29
30 sub extract_challenge {
31 my ($self, $challenge) = @_;
32
33 return PVE::ACME::Challenge->extract_challenge($challenge, 'http-01');
34 }
35
36 sub get_subplugins {
37 return [];
38 }
39
40 sub setup {
41 my ($self, $acme, $auth, $data) = @_;
42
43 print "Setting up webserver\n";
44
45 my $challenge = $self->extract_challenge($auth->{challenges});
46 my $key_auth = $acme->key_authorization($challenge->{token});
47
48 my $server = HTTP::Daemon->new(
49 LocalPort => 80,
50 ReuseAddr => 1,
51 ) or die "Failed to initialize HTTP daemon\n";
52 my $pid = fork() // die "Failed to fork HTTP daemon - $!\n";
53 if ($pid) {
54 $data->{server} = $server;
55 $data->{pid} = $pid;
56 $data->{url} = $challenge->{url};
57 } else {
58 while (my $c = $server->accept()) {
59 while (my $r = $c->get_request()) {
60 if ($r->method() eq 'GET' and
61 $r->uri->path eq "/.well-known/acme-challenge/$challenge->{token}") {
62 my $resp = HTTP::Response->new(200, 'OK', undef, $key_auth);
63 $resp->request($r);
64 $c->send_response($resp);
65 } else {
66 $c->send_error(404, 'Not found.')
67 }
68 }
69 $c->close();
70 $c = undef;
71 }
72 }
73 }
74
75 sub teardown {
76 my ($self, $acme, $auth, $data) = @_;
77
78 eval { $data->{server}->close() };
79 kill('KILL', $data->{pid});
80 waitpid($data->{pid}, 0);
81 }
82
83 1;