mirror of
https://git.proxmox.com/git/proxmox-acme
synced 2025-05-11 02:28:17 +00:00
Add DNSChallenge Plugin
This plugin calls the custom script acme.sh and uses the implementation of the DNS API. Signed-off-by: Wolfgang Link <w.link@proxmox.com>
This commit is contained in:
parent
d18383f0d3
commit
98b96d9ee7
3
debian/control
vendored
3
debian/control
vendored
@ -13,5 +13,6 @@ Description: easy and small shell script to automatically issue
|
|||||||
and renew the free certificates from Let's Encrypt.
|
and renew the free certificates from Let's Encrypt.
|
||||||
Depends: curl (>= 7.64.0-1),
|
Depends: curl (>= 7.64.0-1),
|
||||||
coreutils (>= 8.30-1),
|
coreutils (>= 8.30-1),
|
||||||
sed (>= 4.7-1)
|
sed (>= 4.7-1),
|
||||||
|
libpve-common-perl,
|
||||||
Recommends: idn
|
Recommends: idn
|
||||||
|
@ -107,6 +107,7 @@ LIB_SOURCES = \
|
|||||||
ACME.pm \
|
ACME.pm \
|
||||||
ACME/Challenge.pm \
|
ACME/Challenge.pm \
|
||||||
ACME/StandAlone.pm \
|
ACME/StandAlone.pm \
|
||||||
|
ACME/DNSChallenge.pm \
|
||||||
|
|
||||||
all:
|
all:
|
||||||
|
|
||||||
|
@ -23,6 +23,8 @@ file_set_contents
|
|||||||
file_get_contents
|
file_get_contents
|
||||||
);
|
);
|
||||||
|
|
||||||
|
use PVE::ACME::DNSChallenge;
|
||||||
|
|
||||||
Crypt::OpenSSL::RSA->import_random_seed();
|
Crypt::OpenSSL::RSA->import_random_seed();
|
||||||
|
|
||||||
my $LETSENCRYPT_STAGING = 'https://acme-staging-v02.api.letsencrypt.org/directory';
|
my $LETSENCRYPT_STAGING = 'https://acme-staging-v02.api.letsencrypt.org/directory';
|
||||||
|
198
src/PVE/ACME/DNSChallenge.pm
Normal file
198
src/PVE/ACME/DNSChallenge.pm
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
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-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";
|
||||||
|
};
|
||||||
|
|
||||||
|
sub extract_challenge {
|
||||||
|
my ($self, $challenge) = @_;
|
||||||
|
|
||||||
|
return PVE::ACME::Challenge->extract_challenge($challenge, 'dns-01');
|
||||||
|
}
|
||||||
|
|
||||||
|
# The order of the parameters passed to proxmox-acme is important
|
||||||
|
# proxmox-acme setup $plugin [$domain|$alias] $txtvalue $plugin_conf_string
|
||||||
|
sub setup {
|
||||||
|
my ($self, $data) = @_;
|
||||||
|
|
||||||
|
die "No plugin data for DNSChallenge\n" if !defined($data->{plugin});
|
||||||
|
my $domain = $data->{plugin}->{alias} ? $data->{plugin}->{alias} : $data->{domain};
|
||||||
|
my $txtvalue = PVE::ACME::encode(sha256($data->{key_authorization}));
|
||||||
|
my $dnsplugin = $data->{plugin}->{api};
|
||||||
|
my $plugin_conf_string = $data->{plugin}->{data};
|
||||||
|
|
||||||
|
# for security reasons, we execute the command as nobody
|
||||||
|
# we can't verify that the code of the DNSPlugins are harmless.
|
||||||
|
my $cmd = ["setpriv", "--reuid", "nobody", "--regid", "nogroup", "--clear-groups", "--"];
|
||||||
|
push @$cmd, "/usr/bin/bash", $ACME_PATH, "setup", $dnsplugin, $domain;
|
||||||
|
push @$cmd, $txtvalue, $plugin_conf_string;
|
||||||
|
|
||||||
|
PVE::Tools::run_command($cmd, outfunc => $outfunc);
|
||||||
|
print "Add TXT record: _acme-challenge.$domain\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
# The order of the parameters passed to proxmox-acme is important
|
||||||
|
# proxmox-acme teardown $plugin [$domain|$alias] $txtvalue $plugin_conf_string
|
||||||
|
sub teardown {
|
||||||
|
my ($self, $data) = @_;
|
||||||
|
|
||||||
|
die "No plugin data for DNSChallenge\n" if !defined($data->{plugin});
|
||||||
|
my $domain = $data->{plugin}->{alias} ? $data->{plugin}->{alias} : $data->{domain};
|
||||||
|
my $txtvalue = PVE::ACME::encode(sha256($data->{key_authorization}));
|
||||||
|
my $dnsplugin = $data->{plugin}->{api};
|
||||||
|
my $plugin_conf_string = $data->{plugin}->{data};
|
||||||
|
|
||||||
|
# for security reasons, we execute the command as nobody
|
||||||
|
# we can't verify that the code of the DNSPlugins are harmless.
|
||||||
|
my $cmd = ["setpriv", "--reuid", "nobody", "--regid", "nogroup", "--clear-groups", "--"];
|
||||||
|
push @$cmd, "/usr/bin/bash", "$ACME_PATH", "teardown", $dnsplugin, $domain ;
|
||||||
|
push @$cmd, $txtvalue, $plugin_conf_string;
|
||||||
|
PVE::Tools::run_command($cmd, outfunc => $outfunc);
|
||||||
|
print "Remove TXT record: _acme-challenge.$domain\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
Loading…
Reference in New Issue
Block a user