]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mon: added bootstrap-rbd-mirror/rbd-mirror mon profiles
authorJason Dillaman <dillaman@redhat.com>
Tue, 11 Sep 2018 15:55:52 +0000 (11:55 -0400)
committerJason Dillaman <dillaman@redhat.com>
Thu, 13 Sep 2018 13:58:34 +0000 (09:58 -0400)
The rbd-mirror daemon will require permission to read config-keys
from the "rbd/mirror/" prefix. These new profiles (and the new
associated bootstrap-rbd-mirror user) provide the required
permissions.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
doc/rados/operations/user-management.rst
doc/start/quick-ceph-deploy.rst
src/mon/AuthMonitor.cc
src/mon/MonCap.cc
src/test/mon/moncap.cc

index b190c29b77687286457a74adff39b356c67c307f..097911287690713cc831acb5b9b2f4790786f52e 100644 (file)
@@ -224,6 +224,20 @@ The following entries describe valid capability profiles:
               so they have permissions to add keys, etc. when bootstrapping
               a metadata server.
 
+``profile bootstrap-rbd`` (Monitor only)
+
+:Description: Gives a user permissions to bootstrap an RBD user.
+              Conferred on deployment tools such as ``ceph-deploy``, etc.
+              so they have permissions to add keys, etc. when bootstrapping
+              an RBD user.
+
+``profile bootstrap-rbd-mirror`` (Monitor only)
+
+:Description: Gives a user permissions to bootstrap an ``rbd-mirror`` daemon
+              user. Conferred on deployment tools such as ``ceph-deploy``, etc.
+              so they have permissions to add keys, etc. when bootstrapping
+              an ``rbd-mirror`` daemon.
+
 ``profile rbd`` (Monitor and OSD)
 
 :Description: Gives a user permissions to manipulate RBD images. When used
@@ -231,6 +245,12 @@ The following entries describe valid capability profiles:
               by an RBD client application. When used as an OSD cap, it
               provides read-write access to an RBD client application.
 
+``profile rbd-mirror`` (Monitor only)
+
+:Description: Gives a user permissions to manipulate RBD images and retrieve
+              RBD mirroring config-key secrets. It provides the minimal
+              privileges required for the ``rbd-mirror`` daemon.
+
 ``profile rbd-read-only`` (OSD only)
 
 :Description: Gives a user read-only permissions to RBD images.
index b27920f98dc60aff35a448d8161d0f3f56d41821..bb2bcc19f4ba6fbfb04c2052abd84c078ce01457 100644 (file)
@@ -102,6 +102,7 @@ configuration details, perform the following steps using ``ceph-deploy``.
    - ``ceph.bootstrap-mds.keyring``
    - ``ceph.bootstrap-rgw.keyring``
    - ``ceph.bootstrap-rbd.keyring``
+   - ``ceph.bootstrap-rbd-mirror.keyring``
 
    .. note:: If this process fails with a message similar to "Unable to
       find /etc/ceph/ceph.client.admin.keyring", please ensure that the
index 37640888696ef2d8dc5b32ac465849f6a0bc8a57..e98848aa1317be082943877404ecfe7528b3f838 100644 (file)
@@ -136,6 +136,9 @@ void _generate_bootstrap_keys(
     } },
     { "bootstrap-rbd", {
       { "mon", _encode_cap("allow profile bootstrap-rbd") }
+    } },
+    { "bootstrap-rbd-mirror", {
+      { "mon", _encode_cap("allow profile bootstrap-rbd-mirror") }
     } }
   };
 
index 1724a10ae5290f4081292e80b802018665483566..c5569369497f70f78e5952737beec14711f88c24 100644 (file)
@@ -265,13 +265,15 @@ void MonCapGrant::expand_profile_mon(const EntityName& name) const
     profile_grants.back().command_args["caps_osd"] = StringConstraint(
       StringConstraint::MATCH_TYPE_EQUAL, "allow rwx");
   }
-  if (profile == "bootstrap-rbd") {
+  if (profile == "bootstrap-rbd" || profile == "bootstrap-rbd-mirror") {
     profile_grants.push_back(MonCapGrant("mon", MON_CAP_R));  // read monmap
-    profile_grants.push_back(MonCapGrant("auth get-or-create"));  // FIXME: this can expose other mds keys
+    profile_grants.push_back(MonCapGrant("auth get-or-create"));  // FIXME: this can expose other rbd keys
     profile_grants.back().command_args["entity"] = StringConstraint(
       StringConstraint::MATCH_TYPE_PREFIX, "client.");
     profile_grants.back().command_args["caps_mon"] = StringConstraint(
-      StringConstraint::MATCH_TYPE_EQUAL, "profile rbd");
+      StringConstraint::MATCH_TYPE_EQUAL,
+      (profile == "bootstrap-rbd-mirror" ? "profile rbd-mirror" :
+                                           "profile rbd"));
     profile_grants.back().command_args["caps_osd"] = StringConstraint(
       StringConstraint::MATCH_TYPE_REGEX,
       "^([ ,]*profile(=|[ ]+)['\"]?rbd[^ ,'\"]*['\"]?([ ]+pool(=|[ ]+)['\"]?[^,'\"]+['\"]?)?)+$");
@@ -287,7 +289,7 @@ void MonCapGrant::expand_profile_mon(const EntityName& name) const
     profile_grants.push_back(MonCapGrant("osd", MON_CAP_R));
     profile_grants.push_back(MonCapGrant("pg", MON_CAP_R));
   }
-  if (profile == "rbd") {
+  if (profile == "rbd" || profile == "rbd-mirror") {
     profile_grants.push_back(MonCapGrant("mon", MON_CAP_R));
     profile_grants.push_back(MonCapGrant("osd", MON_CAP_R));
     profile_grants.push_back(MonCapGrant("pg", MON_CAP_R));
@@ -298,6 +300,12 @@ void MonCapGrant::expand_profile_mon(const EntityName& name) const
       StringConstraint::MATCH_TYPE_EQUAL, "add");
     profile_grants.back().command_args["addr"] = StringConstraint(
       StringConstraint::MATCH_TYPE_REGEX, "^[^/]+/[0-9]+$");
+
+  }
+  if (profile == "rbd-mirror") {
+    StringConstraint constraint(StringConstraint::MATCH_TYPE_PREFIX,
+                                "rbd/mirror/");
+    profile_grants.push_back(MonCapGrant("config-key get", "key", constraint));
   }
 
   if (profile == "role-definer") {
index 680266d7f06ffbe2beefbc1afe848b547e93075c..388227ccb808f5498b4938297996def7ae8c7cc7 100644 (file)
@@ -342,3 +342,66 @@ TEST(MonCap, ProfileBootstrapRBD) {
                               }, true, true, true,
                              entity_addr_t()));
 }
+
+TEST(MonCap, ProfileBootstrapRBDMirror) {
+  MonCap cap;
+  ASSERT_FALSE(cap.is_allow_all());
+  ASSERT_TRUE(cap.parse("profile bootstrap-rbd-mirror", NULL));
+
+  EntityName name;
+  name.from_str("mon.a");
+  ASSERT_TRUE(cap.is_capable(nullptr, CEPH_ENTITY_TYPE_MON, name, "",
+                             "auth get-or-create", {
+                               {"entity", "client.rbd"},
+                               {"caps_mon", "profile rbd-mirror"},
+                               {"caps_osd", "profile rbd pool=foo, profile rbd-read-only"},
+                             }, true, true, true,
+                            entity_addr_t()));
+  ASSERT_FALSE(cap.is_capable(nullptr, CEPH_ENTITY_TYPE_MON, name, "",
+                              "auth get-or-create", {
+                                {"entity", "client.rbd"},
+                                {"caps_mon", "profile rbd"},
+                                {"caps_osd", "profile rbd pool=foo, profile rbd-read-only"},
+                              }, true, true, true,
+                             entity_addr_t()));
+  ASSERT_FALSE(cap.is_capable(nullptr, CEPH_ENTITY_TYPE_MON, name, "",
+                              "auth get-or-create", {
+                                {"entity", "client.rbd"},
+                                {"caps_mon", "allow *"},
+                                {"caps_osd", "profile rbd"},
+                              }, true, true, true,
+                             entity_addr_t()));
+  ASSERT_FALSE(cap.is_capable(nullptr, CEPH_ENTITY_TYPE_MON, name, "",
+                              "auth get-or-create", {
+                                {"entity", "client.rbd"},
+                                {"caps_mon", "profile rbd-mirror"},
+                                {"caps_osd", "profile rbd pool=foo, allow *, profile rbd-read-only"},
+                              }, true, true, true,
+                             entity_addr_t()));
+}
+
+TEST(MonCap, ProfileRBD) {
+  MonCap cap;
+  ASSERT_FALSE(cap.is_allow_all());
+  ASSERT_TRUE(cap.parse("profile rbd", NULL));
+
+  EntityName name;
+  name.from_str("mon.a");
+  ASSERT_FALSE(cap.is_capable(nullptr, CEPH_ENTITY_TYPE_MON, name, "config-key",
+                              "config-key get", {
+                                {"key", "rbd/mirror/peer/1/1234"},
+                              }, true, false, false, entity_addr_t()));
+}
+
+TEST(MonCap, ProfileRBDMirror) {
+  MonCap cap;
+  ASSERT_FALSE(cap.is_allow_all());
+  ASSERT_TRUE(cap.parse("profile rbd-mirror", NULL));
+
+  EntityName name;
+  name.from_str("mon.a");
+  ASSERT_TRUE(cap.is_capable(nullptr, CEPH_ENTITY_TYPE_MON, name, "config-key",
+                             "config-key get", {
+                               {"key", "rbd/mirror/peer/1/1234"},
+                             }, true, false, false, entity_addr_t()));
+}