#include <algorithm>
+#include <boost/regex.hpp>
+#include "include/assert.h"
+
static inline bool is_not_alnum_space(char c)
{
return !(isalpha(c) || isdigit(c) || (c == '-') || (c == '_'));
ostream& operator<<(ostream& out, const StringConstraint& c)
{
- if (c.prefix.length())
- return out << "prefix " << c.prefix;
- else
+ switch (c.match_type) {
+ case StringConstraint::MATCH_TYPE_EQUAL:
return out << "value " << c.value;
+ case StringConstraint::MATCH_TYPE_PREFIX:
+ return out << "prefix " << c.value;
+ case StringConstraint::MATCH_TYPE_REGEX:
+ return out << "regex " << c.value;
+ default:
+ break;
+ }
+ return out;
}
ostream& operator<<(ostream& out, const MonCapGrant& m)
for (map<string,StringConstraint>::const_iterator p = m.command_args.begin();
p != m.command_args.end();
++p) {
- if (p->second.value.length())
- out << " " << maybe_quote_string(p->first) << "=" << maybe_quote_string(p->second.value);
- else
- out << " " << maybe_quote_string(p->first) << " prefix " << maybe_quote_string(p->second.prefix);
+ switch (p->second.match_type) {
+ case StringConstraint::MATCH_TYPE_EQUAL:
+ out << " " << maybe_quote_string(p->first) << "="
+ << maybe_quote_string(p->second.value);
+ break;
+ case StringConstraint::MATCH_TYPE_PREFIX:
+ out << " " << maybe_quote_string(p->first) << " prefix "
+ << maybe_quote_string(p->second.value);
+ break;
+ case StringConstraint::MATCH_TYPE_REGEX:
+ out << " " << maybe_quote_string(p->first) << " regex "
+ << maybe_quote_string(p->second.value);
+ break;
+ default:
+ break;
+ }
}
}
}
(mon_rwxa_t, allow))
BOOST_FUSION_ADAPT_STRUCT(StringConstraint,
- (std::string, value)
- (std::string, prefix))
+ (StringConstraint::MatchType, match_type)
+ (std::string, value))
// </magic>
profile_grants.push_back(MonCapGrant("osd", MON_CAP_R | MON_CAP_W));
profile_grants.push_back(MonCapGrant("auth", MON_CAP_R | MON_CAP_X));
profile_grants.push_back(MonCapGrant("config-key", MON_CAP_R | MON_CAP_W));
- string prefix = string("daemon-private/mgr/");
- profile_grants.push_back(MonCapGrant("config-key get", "key",
- StringConstraint("", prefix)));
- profile_grants.push_back(MonCapGrant("config-key put", "key",
- StringConstraint("", prefix)));
- profile_grants.push_back(MonCapGrant("config-key exists", "key",
- StringConstraint("", prefix)));
- profile_grants.push_back(MonCapGrant("config-key delete", "key",
- StringConstraint("", prefix)));
+ StringConstraint constraint(StringConstraint::MATCH_TYPE_PREFIX,
+ "daemon-private/mgr/");
+ profile_grants.push_back(MonCapGrant("config-key get", "key", constraint));
+ profile_grants.push_back(MonCapGrant("config-key set", "key", constraint));
+ profile_grants.push_back(MonCapGrant("config-key put", "key", constraint));
+ profile_grants.push_back(MonCapGrant("config-key exists", "key", constraint));
+ profile_grants.push_back(MonCapGrant("config-key delete", "key", constraint));
}
if (profile == "osd" || profile == "mds" || profile == "mon" ||
profile == "mgr") {
+ StringConstraint constraint(StringConstraint::MATCH_TYPE_PREFIX,
+ string("daemon-private/") + stringify(name) +
+ string("/"));
string prefix = string("daemon-private/") + stringify(name) + string("/");
- profile_grants.push_back(MonCapGrant("config-key get", "key", StringConstraint("", prefix)));
- profile_grants.push_back(MonCapGrant("config-key put", "key", StringConstraint("", prefix)));
- profile_grants.push_back(MonCapGrant("config-key exists", "key", StringConstraint("", prefix)));
- profile_grants.push_back(MonCapGrant("config-key delete", "key", StringConstraint("", prefix)));
+ profile_grants.push_back(MonCapGrant("config-key get", "key", constraint));
+ profile_grants.push_back(MonCapGrant("config-key put", "key", constraint));
+ profile_grants.push_back(MonCapGrant("config-key set", "key", constraint));
+ profile_grants.push_back(MonCapGrant("config-key exists", "key", constraint));
+ profile_grants.push_back(MonCapGrant("config-key delete", "key", constraint));
}
if (profile == "bootstrap-osd") {
- string prefix = "dm-crypt/osd";
- profile_grants.push_back(MonCapGrant("config-key put", "key", StringConstraint("", prefix)));
profile_grants.push_back(MonCapGrant("mon", MON_CAP_R)); // read monmap
profile_grants.push_back(MonCapGrant("osd", MON_CAP_R)); // read osdmap
profile_grants.push_back(MonCapGrant("mon getmap"));
- profile_grants.push_back(MonCapGrant("osd create"));
- profile_grants.push_back(MonCapGrant("auth get-or-create"));
- profile_grants.back().command_args["entity"] = StringConstraint("", "client.");
- prefix = "allow command \"config-key get\" with key=\"dm-crypt/osd/";
- profile_grants.back().command_args["caps_mon"] = StringConstraint("", prefix);
- profile_grants.push_back(MonCapGrant("auth add"));
- profile_grants.back().command_args["entity"] = StringConstraint("", "osd.");
- profile_grants.back().command_args["caps_mon"] = StringConstraint("allow profile osd", "");
- profile_grants.back().command_args["caps_osd"] = StringConstraint("allow *", "");
+ profile_grants.push_back(MonCapGrant("osd new"));
}
if (profile == "bootstrap-mds") {
profile_grants.push_back(MonCapGrant("mon", MON_CAP_R)); // read monmap
profile_grants.push_back(MonCapGrant("osd", MON_CAP_R)); // read osdmap
profile_grants.push_back(MonCapGrant("mon getmap"));
profile_grants.push_back(MonCapGrant("auth get-or-create")); // FIXME: this can expose other mds keys
- profile_grants.back().command_args["entity"] = StringConstraint("", "mds.");
- profile_grants.back().command_args["caps_mon"] = StringConstraint("allow profile mds", "");
- profile_grants.back().command_args["caps_osd"] = StringConstraint("allow rwx", "");
- profile_grants.back().command_args["caps_mds"] = StringConstraint("allow", "");
+ profile_grants.back().command_args["entity"] = StringConstraint(
+ StringConstraint::MATCH_TYPE_PREFIX, "mds.");
+ profile_grants.back().command_args["caps_mon"] = StringConstraint(
+ StringConstraint::MATCH_TYPE_EQUAL, "allow profile mds");
+ profile_grants.back().command_args["caps_osd"] = StringConstraint(
+ StringConstraint::MATCH_TYPE_EQUAL, "allow rwx");
+ profile_grants.back().command_args["caps_mds"] = StringConstraint(
+ StringConstraint::MATCH_TYPE_EQUAL, "allow");
}
if (profile == "bootstrap-mgr") {
profile_grants.push_back(MonCapGrant("mon", MON_CAP_R)); // read monmap
profile_grants.push_back(MonCapGrant("osd", MON_CAP_R)); // read osdmap
profile_grants.push_back(MonCapGrant("mon getmap"));
profile_grants.push_back(MonCapGrant("auth get-or-create")); // FIXME: this can expose other mgr keys
- profile_grants.back().command_args["entity"] = StringConstraint("", "mgr.");
- profile_grants.back().command_args["caps_mon"] = StringConstraint("allow profile mgr", "");
+ profile_grants.back().command_args["entity"] = StringConstraint(
+ StringConstraint::MATCH_TYPE_PREFIX, "mgr.");
+ profile_grants.back().command_args["caps_mon"] = StringConstraint(
+ StringConstraint::MATCH_TYPE_EQUAL, "allow profile mgr");
}
if (profile == "bootstrap-rgw") {
profile_grants.push_back(MonCapGrant("mon", MON_CAP_R)); // read monmap
profile_grants.push_back(MonCapGrant("osd", MON_CAP_R)); // read osdmap
profile_grants.push_back(MonCapGrant("mon getmap"));
profile_grants.push_back(MonCapGrant("auth get-or-create")); // FIXME: this can expose other mds keys
- profile_grants.back().command_args["entity"] = StringConstraint("", "client.rgw.");
- profile_grants.back().command_args["caps_mon"] = StringConstraint("allow rw", "");
- profile_grants.back().command_args["caps_osd"] = StringConstraint("allow rwx", "");
+ profile_grants.back().command_args["entity"] = StringConstraint(
+ StringConstraint::MATCH_TYPE_PREFIX, "client.rgw.");
+ profile_grants.back().command_args["caps_mon"] = StringConstraint(
+ StringConstraint::MATCH_TYPE_EQUAL, "allow rw");
+ profile_grants.back().command_args["caps_osd"] = StringConstraint(
+ StringConstraint::MATCH_TYPE_EQUAL, "allow rwx");
}
if (profile == "fs-client") {
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));
}
+ if (profile == "rbd") {
+ 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));
+
+ // exclusive lock dead-client blacklisting (IP+nonce required)
+ profile_grants.push_back(MonCapGrant("osd blacklist"));
+ profile_grants.back().command_args["blacklistop"] = StringConstraint(
+ StringConstraint::MATCH_TYPE_EQUAL, "add");
+ profile_grants.back().command_args["addr"] = StringConstraint(
+ StringConstraint::MATCH_TYPE_REGEX, "^[^/]/[0-9]*$");
+ }
if (profile == "role-definer") {
// grants ALL caps to the auth subsystem, read-only on the
// argument must be present if a constraint exists
if (q == c_args.end())
return 0;
- if (p->second.value.length()) {
- // match value
+ switch (p->second.match_type) {
+ case StringConstraint::MATCH_TYPE_EQUAL:
if (p->second.value != q->second)
return 0;
- } else {
- // match prefix
- if (q->second.find(p->second.prefix) != 0)
+ break;
+ case StringConstraint::MATCH_TYPE_PREFIX:
+ if (q->second.find(p->second.value) != 0)
return 0;
+ break;
+ case StringConstraint::MATCH_TYPE_REGEX:
+ {
+ boost::regex pattern(p->second.value,
+ boost::regex::basic | boost::regex::no_except);
+ if (pattern.empty() || !boost::regex_match(q->second, pattern))
+ return 0;
+ }
+ break;
+ default:
+ break;
}
}
return MON_CAP_ALL;
spaces = +(lit(' ') | lit('\n') | lit('\t'));
// command := command[=]cmd [k1=v1 k2=v2 ...]
- str_match = '=' >> str >> qi::attr(string());
- str_prefix = spaces >> lit("prefix") >> spaces >> qi::attr(string()) >> str;
- kv_pair = str >> (str_match | str_prefix);
+ str_match = '=' >> qi::attr(StringConstraint::MATCH_TYPE_EQUAL) >> str;
+ str_prefix = spaces >> lit("prefix") >> spaces >>
+ qi::attr(StringConstraint::MATCH_TYPE_PREFIX) >> str;
+ str_regex = spaces >> lit("regex") >> spaces >>
+ qi::attr(StringConstraint::MATCH_TYPE_REGEX) >> str;
+ kv_pair = str >> (str_match | str_prefix | str_regex);
kv_map %= kv_pair >> *(spaces >> kv_pair);
command_match = -spaces >> lit("allow") >> spaces >> lit("command") >> (lit('=') | spaces)
>> qi::attr(string()) >> qi::attr(string())
>> spaces >> rwxa;
// profile foo
- profile_match %= -spaces >> lit("allow") >> spaces >> lit("profile") >> (lit('=') | spaces)
+ profile_match %= -spaces >> -(lit("allow") >> spaces)
+ >> lit("profile") >> (lit('=') | spaces)
>> qi::attr(string())
>> str
>> qi::attr(string())
qi::rule<Iterator, string()> unquoted_word;
qi::rule<Iterator, string()> str;
- qi::rule<Iterator, StringConstraint()> str_match, str_prefix;
+ qi::rule<Iterator, StringConstraint()> str_match, str_prefix, str_regex;
qi::rule<Iterator, pair<string, StringConstraint>()> kv_pair;
qi::rule<Iterator, map<string, StringConstraint>()> kv_map;