From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <a.lauterer@proxmox.com>
Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68])
 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
 key-exchange X25519 server-signature RSA-PSS (2048 bits))
 (No client certificate requested)
 by lists.proxmox.com (Postfix) with ESMTPS id BCE696ED3A
 for <pve-devel@lists.proxmox.com>; Thu, 26 Aug 2021 12:04:09 +0200 (CEST)
Received: from firstgate.proxmox.com (localhost [127.0.0.1])
 by firstgate.proxmox.com (Proxmox) with ESMTP id 91E9A1980F
 for <pve-devel@lists.proxmox.com>; Thu, 26 Aug 2021 12:03:39 +0200 (CEST)
Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com
 [94.136.29.106])
 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
 key-exchange X25519 server-signature RSA-PSS (2048 bits))
 (No client certificate requested)
 by firstgate.proxmox.com (Proxmox) with ESMTPS id D050E197AF
 for <pve-devel@lists.proxmox.com>; Thu, 26 Aug 2021 12:03:33 +0200 (CEST)
Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1])
 by proxmox-new.maurer-it.com (Proxmox) with ESMTP id A79F343A5A
 for <pve-devel@lists.proxmox.com>; Thu, 26 Aug 2021 12:03:33 +0200 (CEST)
From: Aaron Lauterer <a.lauterer@proxmox.com>
To: pve-devel@lists.proxmox.com
Date: Thu, 26 Aug 2021 12:03:32 +0200
Message-Id: <20210826100332.2003299-3-a.lauterer@proxmox.com>
X-Mailer: git-send-email 2.30.2
In-Reply-To: <20210826100332.2003299-1-a.lauterer@proxmox.com>
References: <20210826100332.2003299-1-a.lauterer@proxmox.com>
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
X-SPAM-LEVEL: Spam detection results:  0
 AWL 0.290 Adjusted score from AWL reputation of From: address
 BAYES_00                 -1.9 Bayes spam probability is 0 to 1%
 KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment
 SPF_HELO_NONE           0.001 SPF: HELO does not publish an SPF Record
 SPF_PASS               -0.001 SPF: sender matches SPF record
Subject: [pve-devel] [PATCH v3 storage 2/2] Ceph: add keyring parameter for
 external clusters
X-BeenThere: pve-devel@lists.proxmox.com
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: Proxmox VE development discussion <pve-devel.lists.proxmox.com>
List-Unsubscribe: <https://lists.proxmox.com/cgi-bin/mailman/options/pve-devel>, 
 <mailto:pve-devel-request@lists.proxmox.com?subject=unsubscribe>
List-Archive: <http://lists.proxmox.com/pipermail/pve-devel/>
List-Post: <mailto:pve-devel@lists.proxmox.com>
List-Help: <mailto:pve-devel-request@lists.proxmox.com?subject=help>
List-Subscribe: <https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel>, 
 <mailto:pve-devel-request@lists.proxmox.com?subject=subscribe>
X-List-Received-Date: Thu, 26 Aug 2021 10:04:09 -0000

By adding the keyring for RBD storage or the secret for CephFS ones, it
is possible to add an external Ceph cluster with only one API call.

Previously the keyring / secret file needed to be placed in
/etc/pve/priv/ceph/$storeID.{keyring,secret} manually.

Signed-off-by: Aaron Lauterer <a.lauterer@proxmox.com>
---
changes since v2: rebased on current master and hopefully not adding any
characters unintentionally ;)

changes since v1: add check if the keyring parameter exists before
deciding on whether to store or remove the file.

thx @thomas for catching that

 PVE/API2/Storage/Config.pm  |  2 +-
 PVE/CLI/pvesm.pm            | 12 ++++++++++--
 PVE/Storage/CephFSPlugin.pm | 22 ++++++++++++++++------
 PVE/Storage/RBDPlugin.pm    | 26 ++++++++++++++++++++------
 4 files changed, 47 insertions(+), 15 deletions(-)

diff --git a/PVE/API2/Storage/Config.pm b/PVE/API2/Storage/Config.pm
index ea655c5..bf38df3 100755
--- a/PVE/API2/Storage/Config.pm
+++ b/PVE/API2/Storage/Config.pm
@@ -112,7 +112,7 @@ __PACKAGE__->register_method ({
 	return &$api_storage_config($cfg, $param->{storage});
     }});
 
-my $sensitive_params = [qw(password encryption-key master-pubkey)];
+my $sensitive_params = [qw(password encryption-key master-pubkey keyring)];
 
 __PACKAGE__->register_method ({
     name => 'create',
diff --git a/PVE/CLI/pvesm.pm b/PVE/CLI/pvesm.pm
index 668170a..190de91 100755
--- a/PVE/CLI/pvesm.pm
+++ b/PVE/CLI/pvesm.pm
@@ -64,13 +64,21 @@ sub param_mapping {
 	}
     };
 
+    my $keyring_map = {
+	name => 'keyring',
+	desc => 'file containing the keyring to authenticate in the Ceph cluster',
+	func => sub {
+	    my ($value) = @_;
+	    return PVE::Tools::file_get_contents($value);
+	},
+    };
 
     my $mapping = {
 	'cifsscan' => [ $password_map ],
 	'cifs' => [ $password_map ],
 	'pbs' => [ $password_map ],
-	'create' => [ $password_map, $enc_key_map, $master_key_map ],
-	'update' => [ $password_map, $enc_key_map, $master_key_map ],
+	'create' => [ $password_map, $enc_key_map, $master_key_map, $keyring_map ],
+	'update' => [ $password_map, $enc_key_map, $master_key_map, $keyring_map ],
     };
     return $mapping->{$name};
 }
diff --git a/PVE/Storage/CephFSPlugin.pm b/PVE/Storage/CephFSPlugin.pm
index 2aaa450..3b9a791 100644
--- a/PVE/Storage/CephFSPlugin.pm
+++ b/PVE/Storage/CephFSPlugin.pm
@@ -146,6 +146,7 @@ sub options {
 	fuse => { optional => 1 },
 	bwlimit => { optional => 1 },
 	maxfiles => { optional => 1 },
+	keyring => { optional => 1 },
 	'prune-backups' => { optional => 1 },
     };
 }
@@ -163,20 +164,29 @@ sub check_config {
 sub on_add_hook {
     my ($class, $storeid, $scfg, %param) = @_;
 
-    return if defined($scfg->{monhost}); # nothing to do if not pve managed ceph
+    my $secret = $param{keyring} if defined $param{keyring} // undef;
+    PVE::CephConfig::ceph_create_keyfile($scfg->{type}, $storeid, $secret);
 
-    PVE::CephConfig::ceph_create_keyfile($scfg->{type}, $storeid);
+    return;
+}
+
+sub on_update_hook {
+    my ($class, $storeid, $scfg, %param) = @_;
+
+    if (exists($param{keyring})) {
+	if (defined($param{keyring})) {
+	    PVE::CephConfig::ceph_create_keyfile($scfg->{type}, $storeid, $param{keyring});
+	} else {
+	    PVE::CephConfig::ceph_remove_keyfile($scfg->{type}, $storeid);
+	}
+    }
 
     return;
 }
 
 sub on_delete_hook {
     my ($class, $storeid, $scfg) = @_;
-
-    return if defined($scfg->{monhost}); # nothing to do if not pve managed ceph
-
     PVE::CephConfig::ceph_remove_keyfile($scfg->{type}, $storeid);
-
     return;
 }
 
diff --git a/PVE/Storage/RBDPlugin.pm b/PVE/Storage/RBDPlugin.pm
index a8d1243..4bd43d5 100644
--- a/PVE/Storage/RBDPlugin.pm
+++ b/PVE/Storage/RBDPlugin.pm
@@ -305,6 +305,10 @@ sub properties {
 	    description => "Always access rbd through krbd kernel module.",
 	    type => 'boolean',
 	},
+	keyring => {
+	    description => "Client keyring contents (for external clusters).",
+	    type => 'string',
+	},
     };
 }
 
@@ -318,6 +322,7 @@ sub options {
 	username => { optional => 1 },
 	content => { optional => 1 },
 	krbd => { optional => 1 },
+	keyring => { optional => 1 },
 	bwlimit => { optional => 1 },
     };
 }
@@ -327,20 +332,29 @@ sub options {
 sub on_add_hook {
     my ($class, $storeid, $scfg, %param) = @_;
 
-    return if defined($scfg->{monhost}); # nothing to do if not pve managed ceph
+    my $secret = $param{keyring} if defined $param{keyring} // undef;
+    PVE::CephConfig::ceph_create_keyfile($scfg->{type}, $storeid, $secret);
 
-    PVE::CephConfig::ceph_create_keyfile($scfg->{type}, $storeid);
+    return;
+}
+
+sub on_update_hook {
+    my ($class, $storeid, $scfg, %param) = @_;
+
+    if (exists($param{keyring})) {
+	if (defined($param{keyring})) {
+	    PVE::CephConfig::ceph_create_keyfile($scfg->{type}, $storeid, $param{keyring});
+	} else {
+	    PVE::CephConfig::ceph_remove_keyfile($scfg->{type}, $storeid);
+	}
+    }
 
     return;
 }
 
 sub on_delete_hook {
     my ($class, $storeid, $scfg) = @_;
-
-    return if defined($scfg->{monhost}); # nothing to do if not pve managed ceph
-
     PVE::CephConfig::ceph_remove_keyfile($scfg->{type}, $storeid);
-
     return;
 }
 
-- 
2.30.2