to allow retrieval of certificate information, and uploading or removing of custom certificate files.
Signed-off-by: Fabian Grünbichler <f.gruenbich...@proxmox.com> --- PVE/API2/Makefile | 1 + PVE/API2/Certificates.pm | 202 +++++++++++++++++++++++++++++++++++++++++++++++ PVE/API2/Nodes.pm | 8 ++ 3 files changed, 211 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..6b66ea67 --- /dev/null +++ b/PVE/API2/Certificates.pm @@ -0,0 +1,202 @@ +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' }, + description => "Get information about node's certificates.", + parameters => { + additionalProperties => 0, + properties => { + node => get_standard_option('pve-node'), + }, + }, + returns => { + type => 'object', + properties => { + clusterca => { + type => 'object', + }, + custom => { + type => 'object', + optional => 1, + } + }, + }, + code => sub { + my ($param) = @_; + + my $node_path = "/etc/pve/nodes/$param->{node}"; + + my $selfsigned_info = eval { PVE::Certificate::get_certificate_info("${node_path}/pve-ssl.pem")}; + $selfsigned_info = { error => "$@" } if $@; + my $custom_info = eval { PVE::Certificate::get_certificate_info("${node_path}/pveproxy-ssl.pem")}; + $custom_info = { error => "$@" } if $@; + return { + clusterca => $selfsigned_info, + custom => $custom_info, + }; + }, +}); + +__PACKAGE__->register_method ({ + name => 'upload_custom_cert', + path => 'custom', + method => 'POST', + description => 'Upload or update custom certificate chain and key.', + protected => 1, + parameters => { + additionalProperties => 0, + properties => { + node => get_standard_option('pve-node'), + certificates => { + type => 'string', + description => 'PEM encoded certificate (chain).', + }, + key => { + type => 'string', + description => 'PEM encoded private key.', + 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 => { + type => 'object', + }, + code => sub { + my ($param) = @_; + + my $certs = extract_param($param, 'certificates'); + $certs = eval { PVE::Certificate::check_pem($certs, multiple => 1); }; + raise_param_exc({ certificates => "Failed PEM format check - $@" }) if $@; + + my $key = extract_param($param, 'key'); + $key = eval { PVE::Certificate::check_pem($key, label => qr/.*?/); }; + raise_param_exc({ key => "Failed PEM format check - $@" }) if $@; + + my $node = extra_param($param, 'node'); + my $cert_prefix = PVE::CertHelpers::cert_path_prefix($node); + + my $info; + + my $code = sub { + print "Setting custom certificate files\n"; + $info = PVE::CertHelper::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, + parameters => { + additionalProperties => 0, + properties => { + node => get_standard_option('pve-node'), + restart => { + type => 'boolean', + description => 'Restart pveproxy.', + optional => 1, + default => 0, + }, + }, + }, + returns => { + type => 'object', + }, + code => sub { + my ($param) = @_; + + my $node = extra_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 $@; + }}); + +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 _______________________________________________ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel