From: Jason Dillaman Date: Tue, 11 Sep 2018 15:55:52 +0000 (-0400) Subject: mon: added bootstrap-rbd-mirror/rbd-mirror mon profiles X-Git-Tag: v14.0.1~288^2~2 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=5e768d5d187f4428d3162ff6b86d85be29bfd3e0;p=ceph.git mon: added bootstrap-rbd-mirror/rbd-mirror mon profiles 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 --- diff --git a/doc/rados/operations/user-management.rst b/doc/rados/operations/user-management.rst index b190c29b77687..0979112876907 100644 --- a/doc/rados/operations/user-management.rst +++ b/doc/rados/operations/user-management.rst @@ -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. diff --git a/doc/start/quick-ceph-deploy.rst b/doc/start/quick-ceph-deploy.rst index b27920f98dc60..bb2bcc19f4ba6 100644 --- a/doc/start/quick-ceph-deploy.rst +++ b/doc/start/quick-ceph-deploy.rst @@ -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 diff --git a/src/mon/AuthMonitor.cc b/src/mon/AuthMonitor.cc index 37640888696ef..e98848aa1317b 100644 --- a/src/mon/AuthMonitor.cc +++ b/src/mon/AuthMonitor.cc @@ -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") } } } }; diff --git a/src/mon/MonCap.cc b/src/mon/MonCap.cc index 1724a10ae5290..c5569369497f7 100644 --- a/src/mon/MonCap.cc +++ b/src/mon/MonCap.cc @@ -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") { diff --git a/src/test/mon/moncap.cc b/src/test/mon/moncap.cc index 680266d7f06ff..388227ccb808f 100644 --- a/src/test/mon/moncap.cc +++ b/src/test/mon/moncap.cc @@ -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())); +}