This plugin calls the custom script acme.sh and uses the implementation of the DNS API.
Signed-off-by: Wolfgang Link <w.l...@proxmox.com> --- debian/control | 3 +- src/Makefile | 1 + src/PVE/ACME.pm | 1 + src/PVE/ACME/DNSChallenge.pm | 197 +++++++++++++++++++++++++++++++++++ 4 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 src/PVE/ACME/DNSChallenge.pm diff --git a/debian/control b/debian/control index 87ba731..bb85c98 100644 --- a/debian/control +++ b/debian/control @@ -13,5 +13,6 @@ Description: easy and small shell script to automatically issue and renew the free certificates from Let's Encrypt. Depends: curl (>= 7.64.0-1), coreutils (>= 8.30-1), - sed (>= 4.7-1) + sed (>= 4.7-1), + libpve-common-perl, Recommends: idn diff --git a/src/Makefile b/src/Makefile index c56a354..11b35ff 100644 --- a/src/Makefile +++ b/src/Makefile @@ -107,6 +107,7 @@ LIB_SOURCES = \ ACME.pm \ ACME/Challenge.pm \ ACME/StandAlone.pm \ + ACME/DNSChallenge.pm \ all: diff --git a/src/PVE/ACME.pm b/src/PVE/ACME.pm index 7c0794a..86fb9b0 100644 --- a/src/PVE/ACME.pm +++ b/src/PVE/ACME.pm @@ -25,6 +25,7 @@ file_get_contents use PVE::ACME::Challenge; use PVE::ACME::StandAlone; +use PVE::ACME::DNSChallenge; Crypt::OpenSSL::RSA->import_random_seed(); diff --git a/src/PVE/ACME/DNSChallenge.pm b/src/PVE/ACME/DNSChallenge.pm new file mode 100644 index 0000000..77d143f --- /dev/null +++ b/src/PVE/ACME/DNSChallenge.pm @@ -0,0 +1,197 @@ +package PVE::ACME::DNSChallenge; + +use strict; +use warnings; + +use Digest::SHA qw(sha256); +use PVE::Tools; + +use base qw(PVE::ACME::Challenge); + +my $ACME_PATH = '/usr/share/proxmox-ve/proxmox-acme/proxmox-acme'; + +sub supported_challenge_types { + return { 'dns-01' => 1 }; +} + +sub type { + return 'dns'; +} + +my $api_name_list = [ + 'acmedns', + 'acmeproxy', + 'active24', + 'ad', + 'ali', + 'autodns', + 'aws', + 'azure', + 'cf', + 'clouddns', + 'cloudns', + 'cn', + 'conoha', + 'constellix', + 'cx', + 'cyon', + 'da', + 'ddnss', + 'desec', + 'dgon', + 'dnsimple', + 'do', + 'doapi', + 'domeneshop', + 'dp', + 'dpi', + 'dreamhost', + 'duckdns', + 'durabledns', + 'dyn', + 'dynu', + 'dynv6', + 'easydns', + 'euserv', + 'exoscale', + 'freedns', + 'gandi_livedns', + 'gcloud', + 'gd', + 'gdnsdk', + 'he', + 'hexonet', + 'hostingde', + 'infoblox', + 'internetbs', + 'inwx', + 'ispconfig', + 'jd', + 'kas', + 'kinghost', + 'knot', + 'leaseweb', + 'lexicon', + 'linode', + 'linode_v4', + 'loopia', + 'lua', + 'maradns', + 'me', + 'miab', + 'misaka', + 'myapi', + 'mydevil', + 'mydnsjp', + 'namecheap', + 'namecom', + 'namesilo', + 'nederhost', + 'neodigit', + 'netcup', + 'nic', + 'nsd', + 'nsone', + 'nsupdate', + 'nw', + 'one', + 'online', + 'openprovider', + 'opnsense', + 'ovh', + 'pdns', + 'pleskxml', + 'pointhq', + 'rackspace', + 'rcode0', + 'regru', + 'schlundtech', + 'selectel', + 'servercow', + 'tele3', + 'ultra', + 'unoeuro', + 'variomedia', + 'vscale', + 'vultr', + 'yandex', + 'zilore', + 'zone', + 'zonomi', +]; + +sub properties { + return { + api => { + description => "API plugin name", + type => 'string', + enum => $api_name_list, + }, + data => { + type => 'string', + description => 'DNS plugin data.', + }, + }; +} + +sub options { + return { + api => {}, + data => {}, + nodes => { optional => 1 }, + disable => { optional => 1 }, + }; +} + +my $outfunc = sub { + my $line = shift; + print "$line\n"; +}; + +# The order of the parameters passed to proxmox-acme is important +# proxmox-acme setup $plugin [$domain|$alias] $txtvalue $plugin_conf_string +sub setup { + my ($class, $acme, $authorization, $plugin) = @_; + + my $plugin_conf_string = PVE::Tools::decode_text($plugin->{data}); + + my $dns_challenge = + PVE::ACME::extract_challenge($authorization->{'challenges'}, "dns-01"); + my $url = $dns_challenge->{'url'}; + + my $domain = $plugin->{alias} ? + $plugin->{'alias'} : $authorization->{'identifier'}->{'value'}; + + my $key_auth = $acme->key_authorization($dns_challenge->{'token'}); + my $txtvalue = PVE::ACME::encode(sha256($key_auth)); + + my $dns_plugin = $plugin->{api}; + my $cmd = ["bash", $ACME_PATH, "setup", $dns_plugin, $domain]; + push @$cmd, $txtvalue, $plugin_conf_string; + + PVE::Tools::run_command($cmd, outfunc => $outfunc); + print "Add TXT record: _acme-challenge.$domain\n"; + my $self = { + dnsplugin => $dns_plugin, + domain => $domain, + txtvalue => $txtvalue, + plugin_conf_string => $plugin_conf_string, + url => $url, + }; + + return bless $self, $class; +} + +# The order of the parameters passed to proxmox-acme is important +# proxmox-acme teardown $plugin [$domain|$alias] $txtvalue $plugin_conf_string +sub teardown { + my ($class) = @_; + + my $domain = $class->{domain}; + my $cmd = ["bash", "$ACME_PATH", "teardown", $class->{dnsplugin}]; + push @$cmd, $domain, $class->{txtvalue}, $class->{plugin_conf_string}; + PVE::Tools::run_command($cmd, outfunc => $outfunc); + print "Remove TXT record: _acme-challenge.$domain\n"; +} + +1; -- 2.20.1 _______________________________________________ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel