]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mon/OSDMonitor: relax cap enforcement for unmanaged snapshots
authorIlya Dryomov <idryomov@gmail.com>
Fri, 24 Jan 2025 19:47:11 +0000 (20:47 +0100)
committerIlya Dryomov <idryomov@gmail.com>
Tue, 28 Jan 2025 09:17:06 +0000 (10:17 +0100)
Since commit 4972e054b32c ("mon/OSDMonitor: enforce caps when
creating/deleting unmanaged snapshots"), a) write access to the MON
service, b) write access to the OSD service for a pool or c) permission
for "osd pool op unmanaged-snap" command for a pool is required.  For
"profile rbd" we configure read-only access to the MON service and rely
on write access to the OSD service, however the corresponding check in
is_osd_writable() is too strict.

A OSD cap like "profile rbd namespace=myns" or "allow w namespace=myns"
allows write access to myns namespace of any pool, but is_osd_writable()
disallows operations with unmanaged snapshots with such a cap because
its match.pool_namespace.pool_name.empty() is true.  This condition
appears to serve as the "doesn't include support for the application
tag" guard, but it should actually be match.pool_tag.is_match_all()
(or match.pool_tag.application.empty() if open-coded) -- no restriction
on the pool name doesn't automatically mean that there is a restriction
on the application tag.

Fixes: https://tracker.ceph.com/issues/69679
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
qa/workunits/rbd/permissions.sh
src/mon/OSDMonitor.cc

index f8a9aaa7128ef86f9941568d3da94fddf6966668..dfa33bf45f74e4f73ce81277d82be40d7b7de1cc 100755 (executable)
@@ -49,8 +49,13 @@ create_users() {
     ceph auth get-or-create client.snap_none mon 'allow r' >> $KEYRING
     ceph auth get-or-create client.snap_all mon 'allow r' osd 'allow w' >> $KEYRING
     ceph auth get-or-create client.snap_pool mon 'allow r' osd 'allow w pool=images' >> $KEYRING
+    ceph auth get-or-create client.snap_pool_namespace mon 'allow r' osd 'allow w pool=images namespace=foo' >> $KEYRING
+    ceph auth get-or-create client.snap_namespace mon 'allow r' osd 'allow w namespace=foo' >> $KEYRING
+    ceph auth get-or-create client.snap_tag mon 'allow r' osd 'allow w tag fooapp *=*' >> $KEYRING
     ceph auth get-or-create client.snap_profile_all mon 'allow r' osd 'profile rbd' >> $KEYRING
     ceph auth get-or-create client.snap_profile_pool mon 'allow r' osd 'profile rbd pool=images' >> $KEYRING
+    ceph auth get-or-create client.snap_profile_pool_namespace mon 'allow r' osd 'profile rbd pool=images namespace=foo' >> $KEYRING
+    ceph auth get-or-create client.snap_profile_namespace mon 'allow r' osd 'profile rbd namespace=foo' >> $KEYRING
 
     ceph auth get-or-create client.mon_write mon 'allow *' >> $KEYRING
 }
@@ -208,12 +213,27 @@ test_remove_self_managed_snapshots() {
     create_self_managed_snapshot snap_pool images
     expect 1 create_self_managed_snapshot snap_pool volumes
 
+    create_self_managed_snapshot snap_pool_namespace images
+    expect 1 create_self_managed_snapshot snap_pool_namespace volumes
+
+    create_self_managed_snapshot snap_namespace images
+    create_self_managed_snapshot snap_namespace volumes
+
+    expect 1 create_self_managed_snapshot snap_tag images
+    expect 1 create_self_managed_snapshot snap_tag volumes
+
     create_self_managed_snapshot snap_profile_all images
     create_self_managed_snapshot snap_profile_all volumes
 
     create_self_managed_snapshot snap_profile_pool images
     expect 1 create_self_managed_snapshot snap_profile_pool volumes
 
+    create_self_managed_snapshot snap_profile_pool_namespace images
+    expect 1 create_self_managed_snapshot snap_profile_pool_namespace volumes
+
+    create_self_managed_snapshot snap_profile_namespace images
+    create_self_managed_snapshot snap_profile_namespace volumes
+
     # Ensure users cannot delete self-managed snapshots w/o permissions
     expect 1 remove_self_managed_snapshot snap_none images
     expect 1 remove_self_managed_snapshot snap_none volumes
@@ -224,11 +244,26 @@ test_remove_self_managed_snapshots() {
     remove_self_managed_snapshot snap_pool images
     expect 1 remove_self_managed_snapshot snap_pool volumes
 
+    remove_self_managed_snapshot snap_pool_namespace images
+    expect 1 remove_self_managed_snapshot snap_pool_namespace volumes
+
+    remove_self_managed_snapshot snap_namespace images
+    remove_self_managed_snapshot snap_namespace volumes
+
+    expect 1 remove_self_managed_snapshot snap_tag images
+    expect 1 remove_self_managed_snapshot snap_tag volumes
+
     remove_self_managed_snapshot snap_profile_all images
     remove_self_managed_snapshot snap_profile_all volumes
 
     remove_self_managed_snapshot snap_profile_pool images
     expect 1 remove_self_managed_snapshot snap_profile_pool volumes
+
+    remove_self_managed_snapshot snap_profile_pool_namespace images
+    expect 1 remove_self_managed_snapshot snap_profile_pool_namespace volumes
+
+    remove_self_managed_snapshot snap_profile_namespace images
+    remove_self_managed_snapshot snap_profile_namespace volumes
 }
 
 test_rbd_support() {
index 69be79b3a8fb3d945e03eaf2d72f08a689558da5..a97f81c36b5699156c23cf1be385c6955711ad88 100644 (file)
@@ -270,10 +270,14 @@ bool is_osd_writable(const OSDCapGrant& grant, const std::string* pool_name) {
     auto& match = grant.match;
     if (match.is_match_all()) {
       return true;
-    } else if (pool_name != nullptr &&
-               !match.pool_namespace.pool_name.empty() &&
-               match.pool_namespace.pool_name == *pool_name) {
-      return true;
+    } else if (pool_name != nullptr) {
+      if (!match.pool_namespace.pool_name.empty()) {
+        if (match.pool_namespace.pool_name == *pool_name) {
+          return true;
+        }
+      } else if (match.pool_tag.is_match_all()) {
+        return true;
+      }
     }
   }
   return false;