From b0d73aed19a9f3f242d5a13757016759835c164c Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Mon, 14 Oct 2019 10:54:44 -0400 Subject: [PATCH] mgr: added 'profile rbd/rbd-read-only' cap These profiles can be further restricted via 'pool' and 'namespace' argument optionals. Signed-off-by: Jason Dillaman --- doc/rados/operations/user-management.rst | 11 ++++++--- src/mgr/MgrCap.cc | 20 +++++++++++++++ src/test/mgr/test_mgrcap.cc | 31 ++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/doc/rados/operations/user-management.rst b/doc/rados/operations/user-management.rst index ba15fb851fb..4d961d4be04 100644 --- a/doc/rados/operations/user-management.rst +++ b/doc/rados/operations/user-management.rst @@ -269,14 +269,15 @@ The following entries describe valid capability profiles: so they have permissions to add keys, etc. when bootstrapping an ``rbd-mirror`` daemon. -``profile rbd`` (Monitor and OSD) +``profile rbd`` (Manager, Monitor, and OSD) :Description: Gives a user permissions to manipulate RBD images. When used as a Monitor cap, it provides the minimal privileges required by an RBD client application; this includes the ability to blacklist other client users. When used as an OSD cap, it provides read-write access to the specified pool to an - RBD client application. + RBD client application. The Manager cap supports optional + ``pool`` and ``namespace`` keyword arguments. ``profile rbd-mirror`` (Monitor only) @@ -284,9 +285,11 @@ The following entries describe valid capability profiles: RBD mirroring config-key secrets. It provides the minimal privileges required for the ``rbd-mirror`` daemon. -``profile rbd-read-only`` (OSD only) +``profile rbd-read-only`` (Manager and OSD) -:Description: Gives a user read-only permissions to RBD images. +:Description: Gives a user read-only permissions to RBD images. The Manager + cap supports optional ``pool`` and ``namespace`` keyword + arguments. Pool diff --git a/src/mgr/MgrCap.cc b/src/mgr/MgrCap.cc index 37a256f3fe4..ed5ed46d62c 100644 --- a/src/mgr/MgrCap.cc +++ b/src/mgr/MgrCap.cc @@ -154,6 +154,26 @@ void MgrCapGrant::expand_profile() const { profile_grants.push_back({{}, {}, {}, "crash post", {}, {}}); return; } + + if (profile == "rbd" || profile == "rbd-read-only") { + Arguments filtered_arguments; + for (auto& [key, constraint] : arguments) { + if (key == "pool" || key == "namespace") { + filtered_arguments[key] = std::move(constraint); + } + } + + mgr_rwxa_t perms = mgr_rwxa_t{MGR_CAP_R}; + if (profile == "rbd") { + perms = mgr_rwxa_t{MGR_CAP_R | MGR_CAP_W}; + } + + // whitelist all 'rbd_support' commands (restricted by optional + // pool/namespace constraints) + profile_grants.push_back({{}, "rbd_support", {}, {}, + std::move(filtered_arguments), perms}); + return; + } } bool MgrCapGrant::validate_arguments( diff --git a/src/test/mgr/test_mgrcap.cc b/src/test/mgr/test_mgrcap.cc index c6c73b885ba..3c79d87906e 100644 --- a/src/test/mgr/test_mgrcap.cc +++ b/src/test/mgr/test_mgrcap.cc @@ -262,3 +262,34 @@ TEST(MgrCap, Module) { ASSERT_TRUE(cap.is_capable(nullptr, {}, "", "bcd", "", {}, false, true, false, {})); } + +TEST(MgrCap, Profile) { + MgrCap cap; + ASSERT_FALSE(cap.is_allow_all()); + + ASSERT_TRUE(cap.parse("profile rbd", nullptr)); + ASSERT_FALSE(cap.is_capable(nullptr, {}, "", "abc", "", {}, true, false, + false, {})); + ASSERT_TRUE(cap.is_capable(nullptr, {}, "", "rbd_support", "", {}, true, + true, false, {})); + ASSERT_TRUE(cap.is_capable(nullptr, {}, "", "rbd_support", "", {}, true, + false, false, {})); + + ASSERT_TRUE(cap.parse("profile rbd pool=abc namespace prefix def", nullptr)); + ASSERT_FALSE(cap.is_capable(nullptr, {}, "", "rbd_support", "", {}, + true, true, false, {})); + ASSERT_FALSE(cap.is_capable(nullptr, {}, "", "rbd_support", "", + {{"pool", "abc"}}, + true, true, false, {})); + ASSERT_TRUE(cap.is_capable(nullptr, {}, "", "rbd_support", "", + {{"pool", "abc"}, {"namespace", "defghi"}}, + true, true, false, {})); + + ASSERT_TRUE(cap.parse("profile rbd-read-only", nullptr)); + ASSERT_FALSE(cap.is_capable(nullptr, {}, "", "abc", "", {}, true, false, + false, {})); + ASSERT_FALSE(cap.is_capable(nullptr, {}, "", "rbd_support", "", {}, true, + true, false, {})); + ASSERT_TRUE(cap.is_capable(nullptr, {}, "", "rbd_support", "", {}, true, + false, false, {})); +} -- 2.39.5