]> git.proxmox.com Git - proxmox-acme.git/blob - src/PVE/ACME/DNSChallenge.pm
allow to get full DNS plugins list
[proxmox-acme.git] / src / PVE / ACME / DNSChallenge.pm
1 package PVE::ACME::DNSChallenge;
2
3 use strict;
4 use warnings;
5
6 use Digest::SHA qw(sha256);
7 use PVE::Tools;
8
9 use base qw(PVE::ACME::Challenge);
10
11 my $ACME_PATH = '/usr/share/proxmox-acme/proxmox-acme';
12
13 sub supported_challenge_types {
14 return ["dns-01"];
15 }
16
17 sub type {
18 return 'dns';
19 }
20
21 my $plugin_names = [
22 'acmedns',
23 'acmeproxy',
24 'active24',
25 'ad',
26 'ali',
27 'autodns',
28 'aws',
29 'azure',
30 'cf',
31 'clouddns',
32 'cloudns',
33 'cn',
34 'conoha',
35 'constellix',
36 'cx',
37 'cyon',
38 'da',
39 'ddnss',
40 'desec',
41 'dgon',
42 'dnsimple',
43 'do',
44 'doapi',
45 'domeneshop',
46 'dp',
47 'dpi',
48 'dreamhost',
49 'duckdns',
50 'durabledns',
51 'dyn',
52 'dynu',
53 'dynv6',
54 'easydns',
55 'euserv',
56 'exoscale',
57 'freedns',
58 'gandi_livedns',
59 'gcloud',
60 'gd',
61 'gdnsdk',
62 'he',
63 'hexonet',
64 'hostingde',
65 'infoblox',
66 'internetbs',
67 'inwx',
68 'ispconfig',
69 'jd',
70 'kas',
71 'kinghost',
72 'knot',
73 'leaseweb',
74 'lexicon',
75 'linode',
76 'linode_v4',
77 'loopia',
78 'lua',
79 'maradns',
80 'me',
81 'miab',
82 'misaka',
83 'myapi',
84 'mydevil',
85 'mydnsjp',
86 'namecheap',
87 'namecom',
88 'namesilo',
89 'nederhost',
90 'neodigit',
91 'netcup',
92 'nic',
93 'nsd',
94 'nsone',
95 'nsupdate',
96 'nw',
97 'one',
98 'online',
99 'openprovider',
100 'opnsense',
101 'ovh',
102 'pdns',
103 'pleskxml',
104 'pointhq',
105 'rackspace',
106 'rcode0',
107 'regru',
108 'schlundtech',
109 'selectel',
110 'servercow',
111 'tele3',
112 'ultra',
113 'unoeuro',
114 'variomedia',
115 'vscale',
116 'vultr',
117 'yandex',
118 'zilore',
119 'zone',
120 'zonomi',
121 ];
122 sub get_supported_plugins {
123 return $plugin_names;
124 }
125
126 sub properties {
127 return {
128 api => {
129 description => "API plugin name",
130 type => 'string',
131 enum => $plugin_names,
132 },
133 data => {
134 type => 'string',
135 description => 'DNS plugin data.',
136 },
137 };
138 }
139
140 sub options {
141 return {
142 api => {},
143 data => { optional => 1 },
144 nodes => { optional => 1 },
145 disable => { optional => 1 },
146 };
147 }
148
149 my $proxmox_acme_command = sub {
150 my ($self, $acme, $auth, $data, $action) = @_;
151
152 die "No plugin data for DNSChallenge\n" if !defined($data->{plugin});
153
154 my $alias = $data->{alias};
155 my $domain = $auth->{identifier}->{value};
156
157 my $challenge = $self->extract_challenge($auth->{challenges});
158 my $key_auth = $acme->key_authorization($challenge->{token});
159
160 my $txtvalue = PVE::ACME::encode(sha256($key_auth));
161 my $dnsplugin = $data->{plugin}->{api};
162 my $plugin_conf_string = $data->{plugin}->{data};
163
164 # for security reasons, we execute the command as nobody
165 # we can't verify that the code of the DNSPlugins are harmless.
166 my $cmd = ["setpriv", "--reuid", "nobody", "--regid", "nogroup", "--clear-groups", "--reset-env", "--"];
167
168 # The order of the parameters passed to proxmox-acme is important
169 # proxmox-acme <setup|teardown> $plugin <$domain|$alias> $txtvalue [$plugin_conf_string]
170 push @$cmd, "/bin/bash", $ACME_PATH, $action, $dnsplugin;
171 if ($alias) {
172 push @$cmd, $alias;
173 } else {
174 push @$cmd, $domain;
175 }
176 my $input = "$txtvalue\n";
177 $input .= "$plugin_conf_string\n" if $plugin_conf_string;
178
179 PVE::Tools::run_command($cmd, input => $input);
180
181 $data->{url} = $challenge->{url};
182
183 return $domain;
184 };
185
186 sub setup {
187 my ($self, $acme, $auth, $data) = @_;
188
189 my $domain = $proxmox_acme_command->($self, $acme, $auth, $data, 'setup');
190 print "Add TXT record: _acme-challenge.$domain\n";
191 }
192
193 sub teardown {
194 my ($self, $acme, $auth, $data) = @_;
195
196 my $domain = $proxmox_acme_command->($self, $acme, $auth, $data, 'teardown');
197 print "Remove TXT record: _acme-challenge.$domain\n";
198 }
199
200 1;