--- /dev/null
+package PVE::API2::ACMEPlugin;
+
+use strict;
+use warnings;
+
+use PVE::ACME::Challenge;
+use PVE::ACME::DNSChallenge;
+use PVE::ACME::StandAlone;
+use PVE::Tools qw(extract_param);
+use PVE::Cluster qw(cfs_read_file cfs_write_file cfs_register_file);
+use MIME::Base64;
+
+use base qw(PVE::RESTHandler);
+
+my $FILENAME = "priv/acme/plugins.cfg";
+
+cfs_register_file ($FILENAME,
+ sub { PVE::ACME::Challenge->parse_config(@_); },
+ sub { PVE::ACME::Challenge->write_config(@_); });
+
+PVE::ACME::DNSChallenge->register();
+PVE::ACME::StandAlone->register();
+PVE::ACME::Challenge->init();
+
+__PACKAGE__->register_method({
+ name => 'get_plugin_config',
+ path => 'plugin',
+ method => 'GET',
+ description => "Get ACME DNS plugin configurations.",
+ permissions => {
+ check => ['perm', '/', [ 'Sys.Modily' ]],
+ },
+ protected => 1,
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ },
+ },
+ returns => {
+ type => 'object',
+ },
+ code => sub {
+
+ return load_config();
+ }});
+
+my $encode_data_field = sub {
+ my ($data) = @_;
+
+ my $encoded_data;
+ while ($data) {
+ $data =~ /^([a-zA-Z]\w*=)([\w.,-]*)(,([a-zA-Z]\w*=.*))?$/;
+ $encoded_data .= $1;
+ $encoded_data .= MIME::Base64::encode_base64($2, '');
+ $encoded_data .= "," if $4;
+ $data = $4 ? $4 : undef;
+ }
+ return $encoded_data;
+};
+
+my $update_config = sub {
+ my ($id, $op, $type, $param) = @_;
+
+ my $conf = load_config();
+
+ if ( $op eq "add" ) {
+ die "Section with ID: $id already exists\n"
+ if defined($conf->{ids}->{$id});
+ $conf->{ids}->{$id}->{type} = $type;
+ } elsif ($op eq "del") {
+ delete $conf->{ids}->{$id};
+ }
+
+ foreach my $opt (keys %$param) {
+ my $value = $param->{$opt};
+ if ($opt eq 'data'){
+ $value = &$encode_data_field($value);
+ }
+ $conf->{ids}->{$id}->{$opt} = $value;
+ }
+
+ PVE::Cluster::cfs_write_file($FILENAME, $conf);
+};
+
+__PACKAGE__->register_method({
+ name => 'add_plugin',
+ path => 'plugin',
+ method => 'POST',
+ description => "Add ACME DNS plugin configuration.",
+ permissions => {
+ check => ['perm', '/', [ 'Sys.Modify' ]],
+ },
+ protected => 1,
+ parameters => PVE::ACME::Challenge->createSchema(),
+ returns => { type => "null" },
+ code => sub {
+ my ($param) = @_;
+
+ my $id = extract_param($param, 'id');
+ my $type = extract_param($param, 'type');
+
+ PVE::Cluster::cfs_lock_file($FILENAME, undef, $update_config, $id, "add", $type, $param);
+
+ return undef;
+ }});
+
+__PACKAGE__->register_method({
+ name => 'delete_plugin',
+ path => 'plugin',
+ method => 'DELETE',
+ description => "Delete ACME DNS plugin configuration.",
+ permissions => {
+ check => ['perm', '/', [ 'Sys.Modify' ]],
+ },
+ protected => 1,
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ id => {
+ description => "Plugin configuration name",
+ type => 'string',
+ },
+ },
+ },
+ returns => { type => "null" },
+ code => sub {
+ my ($param) = @_;
+
+ my $id = extract_param($param, 'id');
+
+ PVE::Cluster::cfs_lock_file($FILENAME, undef, $update_config, $id, "del", undef, $param );
+
+ return undef;
+ }});
+
+sub load_config {
+
+ my $raw = eval { cfs_read_file($FILENAME); };
+ return !$raw ? {} : $raw;
+}
+
+sub write_conf {
+ my ($conf) = @_;
+
+ my $raw = PVE::ACME::Challenge->write_config($FILENAME, $conf);
+
+ cfs_write_file($FILENAME, $raw);
+}
+1;
use PVE::API2::ACME;
use PVE::API2::ACMEAccount;
+use PVE::API2::ACMEPlugin;
use PVE::API2::Certificates;
use PVE::API2::NodeConfig;
use PVE::API2::Nodes;
renew => [ 'PVE::API2::ACME', 'renew_certificate', [], { node => $nodename }, $upid_exit ],
revoke => [ 'PVE::API2::ACME', 'revoke_certificate', [], { node => $nodename }, $upid_exit ],
},
+ plugin => {
+ get => [ 'PVE::API2::ACMEPlugin', 'get_plugin_config', [], {},
+ sub {
+ my $conf = shift;
+ print "Name\tType\tStatus\tapi\tdata\n";
+ foreach my $key (keys %{$conf->{ids}} ) {
+ my $type = $conf->{ids}->{$key}->{type};
+ my $status = $conf->{ids}->{$key}->{disable} ?
+ "disabled" : "active";
+ my $api = $conf->{ids}->{$key}->{api} ?
+ $conf->{ids}->{$key}->{api} : "none";
+ my $data = $conf->{ids}->{$key}->{data} ?
+ $conf->{ids}->{$key}->{data} : "none";
+
+ print "$key\t$type\t$status\t$api\t$data\n";
+ }
+ } ],
+ add => [ 'PVE::API2::ACMEPlugin', 'add_plugin', ['type', 'id'] ],
+ del => [ 'PVE::API2::ACMEPlugin', 'delete_plugin', ['id'] ],
+ },
+
},
wakeonlan => [ 'PVE::API2::Nodes::Nodeinfo', 'wakeonlan', [ 'node' ], {}, sub {