]>
git.proxmox.com Git - pmg-api.git/blob - src/PMG/CertHelpers.pm
1 package PMG
::CertHelpers
;
11 API_CERT
=> '/etc/pmg/pmg-api.pem',
12 SMTP_CERT
=> '/etc/pmg/pmg-tls.pem',
15 my $account_prefix = '/etc/pmg/acme/accounts';
17 # TODO: Move `pve-acme-account-name` to common and reuse instead of this.
18 PVE
::JSONSchema
::register_standard_option
('pmg-acme-account-name', {
19 description
=> 'ACME account config file name.',
21 format
=> 'pve-configid',
22 format_description
=> 'name',
27 PVE
::JSONSchema
::register_standard_option
('pmg-acme-account-contact', {
29 format
=> 'email-list',
30 description
=> 'Contact email addresses.',
33 PVE
::JSONSchema
::register_standard_option
('pmg-acme-directory-url', {
35 description
=> 'URL of ACME CA directory endpoint.',
36 pattern
=> '^https?://.*',
39 PVE
::JSONSchema
::register_format
('pmg-certificate-type', sub {
40 my ($type, $noerr) = @_;
42 if ($type =~ /^(?: api | smtp )$/x) {
45 return undef if $noerr;
46 die "value '$type' does not look like a valid certificate type\n";
49 PVE
::JSONSchema
::register_standard_option
('pmg-certificate-type', {
51 description
=> 'The TLS certificate type (API or SMTP certificate).',
52 enum
=> ['api', 'smtp'],
55 PVE
::JSONSchema
::register_format
('pmg-acme-domain', sub {
56 my ($domain, $noerr) = @_;
58 my $label = qr/[a-z0-9][a-z0-9_-]*/i;
60 return $domain if $domain =~ /^(?:\*\.)?$label(?:\.$label)+$/;
61 return undef if $noerr;
62 die "value '$domain' does not look like a valid domain name!\n";
65 PVE
::JSONSchema
::register_format
('pmg-acme-alias', sub {
66 my ($alias, $noerr) = @_;
68 my $label = qr/[a-z0-9_][a-z0-9_-]*/i;
70 return $alias if $alias =~ /^$label(?:\.$label)+$/;
71 return undef if $noerr;
72 die "value '$alias' does not look like a valid alias name!\n";
75 my $local_cert_lock = '/var/lock/pmg-certs.lock';
76 my $local_acme_lock = '/var/lock/pmg-acme.lock';
78 sub cert_path
: prototype($) {
82 } elsif ($type eq 'smtp') {
85 die "unknown certificate type '$type'\n";
90 my ($timeout, $code, @param) = @_;
92 my $res = PVE
::Tools
::lock_file
($local_cert_lock, $timeout, $code, @param);
98 my ($cert, $cert_path, $force) = @_;
100 my ($old_cert, $info);
102 my $cert_path_old = "${cert_path}.old";
104 die "Custom certificate file exists but force flag is not set.\n"
105 if !$force && -e
$cert_path;
107 PVE
::Tools
::file_copy
($cert_path, $cert_path_old) if -e
$cert_path;
111 if ($cert_path eq &API_CERT
) {
112 $gid = getgrnam('www-data') ||
113 die "user www-data not in group file\n";
117 my $cert_path_tmp = "${cert_path}.tmp";
118 PVE
::Tools
::file_set_contents
($cert_path_tmp, $cert, 0640);
119 if (!chown(-1, $gid, $cert_path_tmp)) {
121 "failed to change group ownership of '$cert_path_tmp' to www-data ($gid): $!\n";
122 unlink($cert_path_tmp);
125 if (!rename($cert_path_tmp, $cert_path)) {
127 "failed to rename '$cert_path_tmp' to '$cert_path': $!\n";
128 unlink($cert_path_tmp);
132 PVE
::Tools
::file_set_contents
($cert_path, $cert, 0600);
135 $info = PVE
::Certificate
::get_certificate_info
($cert_path);
140 if (-e
$cert_path_old) {
142 warn "Attempting to restore old certificate file..\n";
143 PVE
::Tools
::file_copy
($cert_path_old, $cert_path);
147 die "Setting certificate files failed - $err\n"
150 unlink $cert_path_old;
156 my ($account_name, $timeout, $code, @param) = @_;
158 my $file = "$local_acme_lock.$account_name";
160 my $res = PVE
::Tools
::lock_file
($file, $timeout, $code, @param);
165 sub acme_account_dir
{
166 return $account_prefix;
169 sub list_acme_accounts
{
172 return $accounts if ! -d
$account_prefix;
174 PVE
::Tools
::dir_glob_foreach
($account_prefix, qr/[^.]+.*/, sub {
177 push @$accounts, $name
178 if PVE
::JSONSchema
::pve_verify_configid
($name, 1);