mirror of
https://github.com/ceph/ceph
synced 2025-02-07 19:03:18 +00:00
mds/MDSAuthCaps: parse and enforce network restriction
Signed-off-by: Sage Weil <sage@redhat.com>
This commit is contained in:
parent
09bf0cd9a4
commit
6651b49863
@ -23,6 +23,7 @@
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "MDSAuthCaps.h"
|
||||
#include "include/ipaddr.h"
|
||||
|
||||
#define dout_subsys ceph_subsys_mds
|
||||
|
||||
@ -58,6 +59,7 @@ struct MDSCapParser : qi::grammar<Iterator, MDSAuthCaps()>
|
||||
lexeme[lit("\"") >> *(char_ - '"') >> '"'] |
|
||||
lexeme[lit("'") >> *(char_ - '\'') >> '\''];
|
||||
unquoted_path %= +char_("a-zA-Z0-9_./-");
|
||||
network_str %= +char_("/.:a-fA-F0-9][");
|
||||
|
||||
// match := [path=<path>] [uid=<uid> [gids=<gid>[,<gid>...]]
|
||||
path %= (spaces >> lit("path") >> lit('=') >> (quoted_path | unquoted_path));
|
||||
@ -86,12 +88,14 @@ struct MDSCapParser : qi::grammar<Iterator, MDSAuthCaps()>
|
||||
(lit("r"))[_val = MDSCapSpec(MDSCapSpec::READ)]
|
||||
);
|
||||
|
||||
grant = lit("allow") >> (capspec >> match)[_val = phoenix::construct<MDSCapGrant>(_1, _2)];
|
||||
grant = lit("allow") >> (capspec >> match >>
|
||||
-(spaces >> lit("network") >> spaces >> network_str))
|
||||
[_val = phoenix::construct<MDSCapGrant>(_1, _2, _3)];
|
||||
grants %= (grant % (*lit(' ') >> (lit(';') | lit(',')) >> *lit(' ')));
|
||||
mdscaps = grants [_val = phoenix::construct<MDSAuthCaps>(_1)];
|
||||
}
|
||||
qi::rule<Iterator> spaces;
|
||||
qi::rule<Iterator, string()> quoted_path, unquoted_path;
|
||||
qi::rule<Iterator, string()> quoted_path, unquoted_path, network_str;
|
||||
qi::rule<Iterator, MDSCapSpec()> capspec;
|
||||
qi::rule<Iterator, string()> path;
|
||||
qi::rule<Iterator, uint32_t()> uid;
|
||||
@ -163,6 +167,12 @@ bool MDSCapMatch::match_path(std::string_view target_path) const
|
||||
return true;
|
||||
}
|
||||
|
||||
void MDSCapGrant::parse_network()
|
||||
{
|
||||
network_valid = ::parse_network(network.c_str(), &network_parsed,
|
||||
&network_prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the client *potentially* able to access this path? Actual
|
||||
* permission will depend on uids/modes in the full is_capable.
|
||||
@ -207,6 +217,13 @@ bool MDSAuthCaps::is_capable(std::string_view inode_path,
|
||||
for (std::vector<MDSCapGrant>::const_iterator i = grants.begin();
|
||||
i != grants.end();
|
||||
++i) {
|
||||
if (i->network.size() &&
|
||||
(!i->network_valid ||
|
||||
!network_contains(i->network_parsed,
|
||||
i->network_prefix,
|
||||
addr))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i->match.match(inode_path, caller_uid, caller_gid, caller_gid_list) &&
|
||||
i->spec.allows(mask & (MAY_READ|MAY_EXECUTE), mask & MAY_WRITE)) {
|
||||
@ -287,7 +304,8 @@ bool MDSAuthCaps::is_capable(std::string_view inode_path,
|
||||
void MDSAuthCaps::set_allow_all()
|
||||
{
|
||||
grants.clear();
|
||||
grants.push_back(MDSCapGrant(MDSCapSpec(MDSCapSpec::ALL), MDSCapMatch()));
|
||||
grants.push_back(MDSCapGrant(MDSCapSpec(MDSCapSpec::ALL), MDSCapMatch(),
|
||||
{}));
|
||||
}
|
||||
|
||||
bool MDSAuthCaps::parse(CephContext *c, std::string_view str, ostream *err)
|
||||
@ -295,7 +313,8 @@ bool MDSAuthCaps::parse(CephContext *c, std::string_view str, ostream *err)
|
||||
// Special case for legacy caps
|
||||
if (str == "allow") {
|
||||
grants.clear();
|
||||
grants.push_back(MDSCapGrant(MDSCapSpec(MDSCapSpec::RWPS), MDSCapMatch()));
|
||||
grants.push_back(MDSCapGrant(MDSCapSpec(MDSCapSpec::RWPS), MDSCapMatch(),
|
||||
{}));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -308,6 +327,7 @@ bool MDSAuthCaps::parse(CephContext *c, std::string_view str, ostream *err)
|
||||
if (r && iter == end) {
|
||||
for (auto& grant : grants) {
|
||||
std::sort(grant.match.gids.begin(), grant.match.gids.end());
|
||||
grant.parse_network();
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
@ -390,7 +410,9 @@ ostream &operator<<(ostream &out, const MDSCapGrant &grant)
|
||||
if (!grant.match.is_match_all()) {
|
||||
out << " " << grant.match;
|
||||
}
|
||||
|
||||
if (grant.network.size()) {
|
||||
out << " network " << grant.network;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
@ -132,9 +132,23 @@ struct MDSCapGrant {
|
||||
MDSCapSpec spec;
|
||||
MDSCapMatch match;
|
||||
|
||||
MDSCapGrant(const MDSCapSpec &spec_, const MDSCapMatch &match_)
|
||||
: spec(spec_), match(match_) {}
|
||||
std::string network;
|
||||
|
||||
entity_addr_t network_parsed;
|
||||
unsigned network_prefix = 0;
|
||||
bool network_valid = true;
|
||||
|
||||
MDSCapGrant(const MDSCapSpec &spec_, const MDSCapMatch &match_,
|
||||
boost::optional<std::string> n)
|
||||
: spec(spec_), match(match_) {
|
||||
if (n) {
|
||||
network = *n;
|
||||
parse_network();
|
||||
}
|
||||
}
|
||||
MDSCapGrant() {}
|
||||
|
||||
void parse_network();
|
||||
};
|
||||
|
||||
class MDSAuthCaps
|
||||
|
@ -914,7 +914,7 @@ Session *MDSRank::get_session(Message *m)
|
||||
imported_session->info.auth_name = session->info.auth_name;
|
||||
//assert(session->info.auth_name == imported_session->info.auth_name);
|
||||
assert(session->info.inst == imported_session->info.inst);
|
||||
imported_session->connection = session->connection;
|
||||
imported_session->set_connection(session->connection);
|
||||
// send out any queued messages
|
||||
while (!session->preopen_out_queue.empty()) {
|
||||
imported_session->connection->send_message(session->preopen_out_queue.front());
|
||||
|
@ -44,6 +44,8 @@ const char *parse_good[] = {
|
||||
"allow r ; allow * uid=1",
|
||||
"allow r ; allow * uid=1",
|
||||
"allow r uid=1 gids=1,2,3, allow * uid=2",
|
||||
"allow r network 1.2.3.4/8",
|
||||
"allow rw path=/foo uid=1 gids=1,2,3 network 2.3.4.5/16",
|
||||
0
|
||||
};
|
||||
|
||||
@ -271,3 +273,17 @@ TEST(MDSAuthCaps, OutputParsed) {
|
||||
ASSERT_EQ(test_values[i].output, stringify(cap));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MDSAuthCaps, network) {
|
||||
entity_addr_t a, b, c;
|
||||
a.parse("10.1.2.3");
|
||||
b.parse("192.168.2.3");
|
||||
c.parse("192.167.2.3");
|
||||
|
||||
MDSAuthCaps cap;
|
||||
ASSERT_TRUE(cap.parse(g_ceph_context, "allow * network 192.168.0.0/16, allow * network 10.0.0.0/8", NULL));
|
||||
|
||||
ASSERT_TRUE(cap.is_capable("foo", 0, 0, 0777, 0, 0, NULL, MAY_READ, 0, 0, a));
|
||||
ASSERT_TRUE(cap.is_capable("foo", 0, 0, 0777, 0, 0, NULL, MAY_READ, 0, 0, b));
|
||||
ASSERT_FALSE(cap.is_capable("foo", 0, 0, 0777, 0, 0, NULL, MAY_READ, 0, 0, c));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user