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. When used as an OSD cap, it
- provides read-write access to an RBD client application.
+ 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. The Manager cap supports optional
+ ``pool`` and ``namespace`` keyword arguments.
``profile rbd-mirror`` (Monitor only)
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
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(
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, {}));
+}