From: Stoiko Ivanov <s.ivanov@proxmox.com>
To: pmg-devel@lists.proxmox.com
Subject: [PATCH pve-common 02/15] pbs-client: add support for master public key
Date: Wed, 3 Jun 2026 20:03:04 +0200 [thread overview]
Message-ID: <20260603180445.98770-3-s.ivanov@proxmox.com> (raw)
In-Reply-To: <20260603180445.98770-1-s.ivanov@proxmox.com>
adapted from PVE::Storage::PBSPlugin
originally introduced there with
c56f7a7 ("pbs: allow setting up a master key")
Signed-off-by: Stoiko Ivanov <s.ivanov@proxmox.com>
---
src/PVE/PBSClient.pm | 59 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 58 insertions(+), 1 deletion(-)
diff --git a/src/PVE/PBSClient.pm b/src/PVE/PBSClient.pm
index d8dd3f0..34ce843 100644
--- a/src/PVE/PBSClient.pm
+++ b/src/PVE/PBSClient.pm
@@ -132,6 +132,51 @@ my sub open_encryption_key {
return $keyfd;
}
+sub master_pubkey_file_name {
+ my ($self) = @_;
+
+ return "$self->{secret_dir}/$self->{storeid}.master.pem";
+}
+
+sub set_master_pubkey {
+ my ($self, $key) = @_;
+
+ my $master_pubkey_file = $self->master_pubkey_file_name();
+ mkdir($self->{secret_dir});
+
+ PVE::Tools::file_set_contents($master_pubkey_file, "$key\n", 0600);
+}
+
+sub delete_master_pubkey {
+ my ($self) = @_;
+
+ my $master_pubkey_file = $self->master_pubkey_file_name();
+
+ if (!unlink($master_pubkey_file)) {
+ return if $! == ENOENT;
+ die "failed to delete the master public key! $!\n";
+ }
+}
+
+# Returns a file handle if there is a master key, or `undef` if there is not. Dies on error.
+sub open_master_pubkey {
+ my ($self) = @_;
+
+ my $master_pubkey_file = $self->master_pubkey_file_name();
+
+ my $keyfd;
+ if (!open($keyfd, '<', $master_pubkey_file)) {
+ if ($! == ENOENT) {
+ die "master public key configured but no key file found!\n"
+ if $self->{'master-pubkey'};
+ return undef;
+ }
+ die "failed to open master public key: $master_pubkey_file: $!\n";
+ }
+
+ return $keyfd;
+}
+
my $USE_CRYPT_PARAMS = {
'proxmox-backup-client' => {
backup => 1,
@@ -144,11 +189,16 @@ my $USE_CRYPT_PARAMS = {
},
};
+my $USE_MASTER_KEY = {
+ backup => 1,
+};
+
my sub do_raw_client_cmd {
my ($self, $client_cmd, $param, %opts) = @_;
my $client_bin = delete($opts{binary}) || 'proxmox-backup-client';
my $use_crypto = $USE_CRYPT_PARAMS->{$client_bin}->{$client_cmd} // 0;
+ my $use_master = $USE_MASTER_KEY->{$client_cmd};
my $client_exe = "/usr/bin/$client_bin";
die "executable not found '$client_exe'! $client_bin not installed?\n" if !-x $client_exe;
@@ -165,7 +215,7 @@ my sub do_raw_client_cmd {
push(@$cmd, $client_exe, $client_cmd);
# This must live in the top scope to not get closed before the `run_command`
- my $keyfd;
+ my ($keyfd, $master_fd);
if ($use_crypto) {
if (defined($keyfd = open_encryption_key($self))) {
my $flags = fcntl($keyfd, F_GETFD, 0)
@@ -173,6 +223,13 @@ my sub do_raw_client_cmd {
fcntl($keyfd, F_SETFD, $flags & ~FD_CLOEXEC)
or die "failed to remove FD_CLOEXEC from encryption key file descriptor\n";
push(@$cmd, '--crypt-mode=encrypt', '--keyfd=' . fileno($keyfd));
+ if ($use_master && defined($master_fd = $self->open_master_pubkey())) {
+ my $flags = fcntl($master_fd, F_GETFD, 0)
+ // die "failed to get file descriptor flags: $!\n";
+ fcntl($master_fd, F_SETFD, $flags & ~FD_CLOEXEC)
+ or die "failed to remove FD_CLOEXEC from master public key file descriptor\n";
+ push @$cmd, '--master-pubkey-fd=' . fileno($master_fd);
+ }
} else {
push(@$cmd, '--crypt-mode=none');
}
--
2.47.3
next prev parent reply other threads:[~2026-06-03 18:05 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-03 18:03 [PATCH pve-common/pmg-api/pmg-docs/pmg-gui 00/15] fix #3226: add support for encrypted backups Stoiko Ivanov
2026-06-03 18:03 ` [PATCH pve-common 01/15] pbs-client: autogen key: rename old one if existing Stoiko Ivanov
2026-06-03 18:03 ` Stoiko Ivanov [this message]
2026-06-03 18:03 ` [PATCH pmg-api 03/15] api: pbs remote: fix delete_password invocation Stoiko Ivanov
2026-06-03 18:03 ` [PATCH pmg-api 04/15] fix #3226: pbs backup: remote: add encryption key support Stoiko Ivanov
2026-06-03 18:03 ` [PATCH pmg-api 05/15] pbs: job: add encrypted state to snapshot listing Stoiko Ivanov
2026-06-03 18:03 ` [PATCH pmg-api 06/15] pbs: job: add verification " Stoiko Ivanov
2026-06-03 18:03 ` [PATCH pmg-api 07/15] pmgbackup: add encypted and verification state to output Stoiko Ivanov
2026-06-03 18:03 ` [PATCH pmg-api 08/15] api: pbs remote create/update: return parts of the configuration Stoiko Ivanov
2026-06-03 18:03 ` [PATCH pmg-api 09/15] api: pmgbackup: add master-pubkey properties Stoiko Ivanov
2026-06-03 18:03 ` [PATCH pmg-gui 10/15] pbs: snapshotview: add missing gettext invocations Stoiko Ivanov
2026-06-03 18:03 ` [PATCH pmg-gui 11/15] utils: copy pbs helpers from pve-manager Stoiko Ivanov
2026-06-03 18:03 ` [PATCH pmg-gui 12/15] fix #3326: ui: pbs remote: add encryption tab to edit window Stoiko Ivanov
2026-06-03 18:03 ` [PATCH pmg-gui 13/15] ui: pbs remote: allow to downloading/print new encryption key Stoiko Ivanov
2026-06-03 18:03 ` [PATCH pmg-gui 14/15] ui: pbs snapshotview: add encryption and verification state Stoiko Ivanov
2026-06-03 18:03 ` [PATCH pmg-docs 15/15] pmgbackup: minimally document support for encrypted backups Stoiko Ivanov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260603180445.98770-3-s.ivanov@proxmox.com \
--to=s.ivanov@proxmox.com \
--cc=pmg-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.