From cd3cb7d3d1c00818a39635ad66b4201db4f0c44c Mon Sep 17 00:00:00 2001 From: Douglas Fuller Date: Mon, 9 Oct 2017 15:20:47 -0400 Subject: [PATCH] OSD/OSDCap: Allow namespace and pool tag to be combined Extend the OSD auth caps grammar to allow namespace and pool tag cap combinations. Namespace must be listed first. Example: allow rwx namespace ns* tag application key = value Signed-off-by: Douglas Fuller --- doc/man/8/ceph-authtool.rst | 6 +++--- src/osd/OSDCap.cc | 18 ++++++++++++------ src/osd/OSDCap.h | 2 ++ src/test/osd/osdcap.cc | 36 +++++++++++++++++++++++++++++++++++- 4 files changed, 52 insertions(+), 10 deletions(-) diff --git a/doc/man/8/ceph-authtool.rst b/doc/man/8/ceph-authtool.rst index a3e719e29b0..56a0639cc8b 100644 --- a/doc/man/8/ceph-authtool.rst +++ b/doc/man/8/ceph-authtool.rst @@ -139,9 +139,9 @@ In general, an osd capability follows the grammar:: osdcap := grant[,grant...] grant := allow (match capspec | capspec match) - match := [pool[=] | object_prefix - | tag = - | namespace[=] ] + match := [ pool[=] | object_prefix + | namespace[=] + | tag = ] capspec := * | [r][w][x] [class-read] [class-write] The capspec determines what kind of operations the entity can perform:: diff --git a/src/osd/OSDCap.cc b/src/osd/OSDCap.cc index e0d028d1770..95c94ebfef8 100644 --- a/src/osd/OSDCap.cc +++ b/src/osd/OSDCap.cc @@ -82,9 +82,13 @@ ostream& operator<<(ostream& out, const OSDCapMatch& m) { if (m.auid != -1LL) { out << "auid " << m.auid << " "; - } else if (!m.pool_namespace.pool_name.empty() || m.pool_namespace.nspace) { + } + + if (!m.pool_namespace.pool_name.empty() || m.pool_namespace.nspace) { out << m.pool_namespace; - } else if (!m.pool_tag.application.empty()) { + } + + if (!m.pool_tag.application.empty()) { out << m.pool_tag; } @@ -351,8 +355,9 @@ bool OSDCap::is_capable(const string& pool_name, const string& ns, { std::vector class_allowed(classes.size(), false); for (auto &grant : grants) { - if (grant.is_capable(pool_name, ns, pool_auid, application_metadata, object, op_may_read, - op_may_write, classes, &class_allowed)) { + if (grant.is_capable(pool_name, ns, pool_auid, application_metadata, + object, op_may_read, op_may_write, classes, + &class_allowed)) { return true; } } @@ -408,9 +413,11 @@ struct OSDCapParser : qi::grammar match = ( pooltag [_val = phoenix::construct(_1)] | + (nspace >> pooltag) [_val = phoenix::construct(_1, _2)] | (auid >> object_prefix) [_val = phoenix::construct(_1, _2)] | (pool_name >> nspace >> object_prefix) [_val = phoenix::construct(_1, _2, _3)] | - (pool_name >> object_prefix) [_val = phoenix::construct(_1, _2)]); + (pool_name >> object_prefix) [_val = phoenix::construct(_1, _2)] + ); // rwxa := * | [r][w][x] [class-read] [class-write] rwxa = @@ -487,4 +494,3 @@ bool OSDCap::parse(const string& str, ostream *err) return false; } - diff --git a/src/osd/OSDCap.h b/src/osd/OSDCap.h index 2a37a28d35f..59b8392f67e 100644 --- a/src/osd/OSDCap.h +++ b/src/osd/OSDCap.h @@ -139,6 +139,8 @@ struct OSDCapMatch { OSDCapMatch(const std::string& dummy, const std::string& app, const std::string& key, const std::string& val) : pool_tag(app, key, val) {} + OSDCapMatch(const std::string& ns, const OSDCapPoolTag& pt) + : pool_namespace("", ns), pool_tag(pt) {} /** * check if given request parameters match our constraints diff --git a/src/test/osd/osdcap.cc b/src/test/osd/osdcap.cc index 2fae9e3cf1d..2d7629d1088 100644 --- a/src/test/osd/osdcap.cc +++ b/src/test/osd/osdcap.cc @@ -68,6 +68,8 @@ const char *parse_good[] = { "allow pool foo namespace=nfoo rwx ; allow pool bar namespace=nbar r", "allow pool foo namespace nfoo rwx ;allow pool bar namespace nbar r", "allow pool foo namespace=nfoo rwx; allow pool bar namespace nbar object_prefix rbd r", + "allow rwx namespace=nfoo tag cephfs data=cephfs_a", + "allow rwx namespace foo tag cephfs data =cephfs_a", "allow pool foo namespace=nfoo* rwx", "allow pool foo namespace=\"\" rwx; allow pool bar namespace='' object_prefix rbd r", "allow pool foo namespace \"\" rwx; allow pool bar namespace '' object_prefix rbd r", @@ -827,6 +829,36 @@ TEST(OSDCap, PoolTagWildKV) ASSERT_TRUE(cap.is_capable("foo", "", 0, {{"application", {{"foo", "bar"}, {"key2", "value"}}}, {"app2", {{"foo", "bar"}}}}, "foo", true, true, {})); } +TEST(OSDCap, NSPool) +{ + OSDCap cap; + ASSERT_TRUE(cap.parse("allow rwx namespace ns tag application key=value", NULL)); + + ASSERT_TRUE(cap.is_capable("foo", "ns", 0, {{"application", {{"key", "value"}}}}, "foo", true, true, {})); + + ASSERT_FALSE(cap.is_capable("foo", "", 0, {{"application", {{"key", "value"}}}}, "foo", true, true, {})); + ASSERT_FALSE(cap.is_capable("foo", "ns", 0, {}, "foo", true, true, {})); + ASSERT_FALSE(cap.is_capable("foo", "ns2", 0, {{"application", {{"key", "value"}}}}, "foo", true, true, {})); + ASSERT_FALSE(cap.is_capable("foo", "ns", 0, {{"application", {{"key", "value2"}}}}, "foo", true, true, {})); + ASSERT_FALSE(cap.is_capable("foo", "ns", 0, {{"application", {{"key2", "value"}}}}, "foo", true, true, {})); + ASSERT_FALSE(cap.is_capable("foo", "", 0, {}, "foo", true, true, {})); +} + +TEST(OSDCap, NSPoolGlob) +{ + OSDCap cap; + ASSERT_TRUE(cap.parse("allow rwx namespace ns* tag application key=value", NULL)); + + ASSERT_TRUE(cap.is_capable("foo", "ns", 0, {{"application", {{"key", "value"}}}}, "foo", true, true, {})); + + ASSERT_TRUE(cap.is_capable("foo", "ns2", 0, {{"application", {{"key", "value"}}}}, "foo", true, true, {})); + ASSERT_FALSE(cap.is_capable("foo", "", 0, {{"application", {{"key", "value"}}}}, "foo", true, true, {})); + ASSERT_FALSE(cap.is_capable("foo", "ns", 0, {}, "foo", true, true, {})); + ASSERT_FALSE(cap.is_capable("foo", "ns", 0, {{"application", {{"key", "value2"}}}}, "foo", true, true, {})); + ASSERT_FALSE(cap.is_capable("foo", "ns", 0, {{"application", {{"key2", "value"}}}}, "foo", true, true, {})); + ASSERT_FALSE(cap.is_capable("foo", "", 0, {}, "foo", true, true, {})); +} + TEST(OSDCap, OutputParsed) { struct CapsTest { @@ -875,7 +907,9 @@ TEST(OSDCap, OutputParsed) {"allow class-read object_prefix rbd_children, allow pool libvirt-pool-test rwx", "osdcap[grant(object_prefix rbd_children class-read),grant(pool libvirt-pool-test rwx)]"}, {"allow rwx tag application key=value", - "osdcap[grant(app application key key val value rwx)]"} + "osdcap[grant(app application key key val value rwx)]"}, + {"allow rwx namespace ns* tag application key=value", + "osdcap[grant(namespace ns* app application key key val value rwx)]"} }; size_t num_tests = sizeof(test_values) / sizeof(*test_values); -- 2.39.5