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', permissions => { check => ['perm', '/nodes/{node}', [ 'Sys.Modify' ]], }, 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', permissions => { check => ['perm', '/nodes/{node}', [ 'Sys.Modify' ]], }, 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;