[pve-devel] [v3 manager 5/7] add certificates API endpoints
Fabian Grünbichler
f.gruenbichler at proxmox.com
Fri Apr 27 14:02:12 CEST 2018
to allow retrieval of certificate information, and uploading or removing
of custom certificate files.
Signed-off-by: Fabian Grünbichler <f.gruenbichler at proxmox.com>
---
PVE/API2/Makefile | 1 +
PVE/API2/Certificates.pm | 207 +++++++++++++++++++++++++++++++++++++++++++++++
PVE/API2/Nodes.pm | 8 ++
3 files changed, 216 insertions(+)
create mode 100644 PVE/API2/Certificates.pm
diff --git a/PVE/API2/Makefile b/PVE/API2/Makefile
index 44b9cf7c..9862e498 100644
--- a/PVE/API2/Makefile
+++ b/PVE/API2/Makefile
@@ -14,6 +14,7 @@ PERLSOURCE = \
Pool.pm \
Tasks.pm \
Network.pm \
+ Certificates.pm \
ACME.pm \
ACMEAccount.pm \
NodeConfig.pm \
diff --git a/PVE/API2/Certificates.pm b/PVE/API2/Certificates.pm
new file mode 100644
index 00000000..fd75ba85
--- /dev/null
+++ b/PVE/API2/Certificates.pm
@@ -0,0 +1,207 @@
+package PVE::API2::Certificates;
+
+use strict;
+use warnings;
+
+use PVE::API2::ACME;
+use PVE::Certificate;
+use PVE::CertHelpers;;
+use PVE::Exception qw(raise_param_exc);
+use PVE::JSONSchema qw(get_standard_option);
+use PVE::Tools qw(extract_param file_get_contents file_set_contents);
+
+use base qw(PVE::RESTHandler);
+
+
+__PACKAGE__->register_method ({
+ subclass => "PVE::API2::ACME",
+ path => 'acme',
+});
+
+__PACKAGE__->register_method ({
+ name => 'index',
+ path => '',
+ method => 'GET',
+ permissions => { user => 'all' },
+ description => "Node index.",
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option('pve-node'),
+ },
+ },
+ returns => {
+ type => 'array',
+ items => {
+ type => "object",
+ properties => {},
+ },
+ links => [ { rel => 'child', href => "{name}" } ],
+ },
+ code => sub {
+ my ($param) = @_;
+
+ return [
+ { name => 'acme' },
+ { name => 'custom' },
+ { name => 'info' },
+ ];
+ },
+});
+
+__PACKAGE__->register_method ({
+ name => 'info',
+ path => 'info',
+ method => 'GET',
+ permissions => { user => 'all' },
+ proxyto => 'node',
+ description => "Get information about node's certificates.",
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option('pve-node'),
+ },
+ },
+ returns => {
+ type => 'array',
+ items => get_standard_option('pve-certificate-info'),
+ },
+ code => sub {
+ my ($param) = @_;
+
+ my $node_path = "/etc/pve/nodes/$param->{node}";
+
+ my $res = [];
+ my $cert_paths = [
+ '/etc/pve/pve-root-ca.pem',
+ "$node_path/pve-ssl.pem",
+ "$node_path/pveproxy-ssl.pem",
+ ];
+ for my $path (@$cert_paths) {
+ eval {
+ my $info = PVE::Certificate::get_certificate_info($path);
+ push @$res, $info if $info;
+ };
+ }
+ return $res;
+ },
+});
+
+__PACKAGE__->register_method ({
+ name => 'upload_custom_cert',
+ path => 'custom',
+ method => 'POST',
+ description => 'Upload or update custom certificate chain and key.',
+ protected => 1,
+ proxyto => 'node',
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option('pve-node'),
+ certificates => {
+ type => 'string',
+ format => 'pem-certificate-chain',
+ description => 'PEM encoded certificate (chain).',
+ },
+ key => {
+ type => 'string',
+ description => 'PEM encoded private key.',
+ format => 'pem-string',
+ optional => 1,
+ },
+ force => {
+ type => 'boolean',
+ description => 'Overwrite existing custom or ACME certificate files.',
+ optional => 1,
+ default => 0,
+ },
+ restart => {
+ type => 'boolean',
+ description => 'Restart pveproxy.',
+ optional => 1,
+ default => 0,
+ },
+ },
+ },
+ returns => get_standard_option('pve-certificate-info'),
+ code => sub {
+ my ($param) = @_;
+
+ my $node = extract_param($param, 'node');
+ my $cert_prefix = PVE::CertHelpers::cert_path_prefix($node);
+
+ my $certs = extract_param($param, 'certificates');
+ $certs = PVE::Certificate::strip_leading_text($certs);
+
+ my $key = extract_param($param, 'key');
+ if ($key) {
+ $key = PVE::Certificate::strip_leading_text($key);
+ } else {
+ raise_param_exc({'key' => "Attempted to upload custom certificate without (existing) key."})
+ if ! -e "${cert_prefix}.key";
+ }
+
+ my $info;
+
+ my $code = sub {
+ print "Setting custom certificate files\n";
+ $info = PVE::CertHelpers::set_cert_files($certs, $key, $cert_prefix, $param->{force});
+
+ if ($param->{restart}) {
+ print "Restarting pveproxy\n";
+ PVE::Tools::run_command(['systemctl', 'reload-or-restart', 'pveproxy']);
+ }
+ };
+
+ PVE::CertHelpers::cert_lock(10, $code);
+ die "$@\n" if $@;
+
+ return $info;
+ }});
+
+__PACKAGE__->register_method ({
+ name => 'remove_custom_cert',
+ path => 'custom',
+ method => 'DELETE',
+ description => 'DELETE custom certificate chain and key.',
+ protected => 1,
+ proxyto => 'node',
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option('pve-node'),
+ restart => {
+ type => 'boolean',
+ description => 'Restart pveproxy.',
+ optional => 1,
+ default => 0,
+ },
+ },
+ },
+ returns => {
+ type => 'null',
+ },
+ code => sub {
+ my ($param) = @_;
+
+ my $node = extract_param($param, 'node');
+ my $cert_prefix = PVE::CertHelpers::cert_path_prefix($node);
+
+ my $code = sub {
+ print "Deleting custom certificate files\n";
+ unlink "${cert_prefix}.pem";
+ unlink "${cert_prefix}.key";
+
+ if ($param->{restart}) {
+ print "Restarting pveproxy\n";
+ PVE::Tools::run_command(['systemctl', 'reload-or-restart', 'pveproxy']);
+ }
+ };
+
+ PVE::CertHelpers::cert_lock(10, $code);
+ die "$@\n" if $@;
+
+ return undef;
+ }});
+
+1;
diff --git a/PVE/API2/Nodes.pm b/PVE/API2/Nodes.pm
index 42b932cf..25f0e180 100644
--- a/PVE/API2/Nodes.pm
+++ b/PVE/API2/Nodes.pm
@@ -41,6 +41,7 @@ use PVE::API2::APT;
use PVE::API2::Ceph;
use PVE::API2::Firewall::Host;
use PVE::API2::Replication;
+use PVE::API2::Certificates;
use PVE::API2::NodeConfig;
use Digest::MD5;
use Digest::SHA;
@@ -119,6 +120,12 @@ __PACKAGE__->register_method ({
path => 'replication',
});
+__PACKAGE__->register_method ({
+ subclass => "PVE::API2::Certificates",
+ path => 'certificates',
+});
+
+
__PACKAGE__->register_method ({
subclass => "PVE::API2::NodeConfig",
path => 'config',
@@ -177,6 +184,7 @@ __PACKAGE__->register_method ({
{ name => 'stopall' },
{ name => 'netstat' },
{ name => 'firewall' },
+ { name => 'certificates' },
{ name => 'config' },
];
--
2.14.2
More information about the pve-devel
mailing list