mirror of
https://github.com/ceph/ceph
synced 2025-02-21 01:47:25 +00:00
Merge PR #17678 into master
* refs/pull/17678/head: mon/AuthMonitor: improve error message mon/OSDMonitor: disallow "all" as a key or value name cephfs, mon/AuthMonitor, OSD/osdcap: make 'all' a synonym for '*' vstart.sh: Create an admin user for each CephFS mon/AuthMonitor: Allow * wildcard for filesystem name OSD/OSDCap: Allow namespace and pool tag to be combined OSD/OSDCap: Namespace globbing mon/AuthMonitor: Use new osd auth caps for ceph fs authorize OSD/auth caps: Add OSD auth caps based on pool tag mon/FSCommands: Tag pools used for cephfs by default mon/OSDMonitor: Add key/value arguments for pool tagging Reviewed-by: Patrick Donnelly <pdonnell@redhat.com>
This commit is contained in:
commit
06e2cec1ea
@ -33,6 +33,14 @@ for example, to restrict client ``foo`` to writing only in the ``bar`` directory
|
||||
|
||||
ceph fs authorize cephfs client.foo / r /bar rw
|
||||
|
||||
results in:
|
||||
|
||||
client.foo
|
||||
key: *key*
|
||||
caps: [mds] allow r, allow rw path=/bar
|
||||
caps: [mon] allow r
|
||||
caps: [osd] allow rw tag cephfs data=cephfs_a
|
||||
|
||||
To completely restrict the client to the ``bar`` directory, omit the
|
||||
root directory ::
|
||||
|
||||
@ -42,6 +50,9 @@ Note that if a client's read access is restricted to a path, they will only
|
||||
be able to mount the filesystem when specifying a readable path in the
|
||||
mount command (see below).
|
||||
|
||||
Supplying ``all`` or ``*`` as the filesystem name will grant access to every
|
||||
file system. Note that it is usually necessary to quote ``*`` to protect it from
|
||||
the shell.
|
||||
|
||||
See `User Management - Add a User to a Keyring`_. for additional details on user management
|
||||
|
||||
@ -81,8 +92,8 @@ This restricts all the attributes that are set by special extended attributes
|
||||
with a "ceph." prefix, as well as restricting other means of setting
|
||||
these fields (such as openc operations with layouts).
|
||||
|
||||
For example, in the following snippet client.0 can modify layouts and quotas,
|
||||
but client.1 cannot.
|
||||
For example, in the following snippet client.0 can modify layouts and quotas
|
||||
on the filesystem cephfs_a, but client.1 cannot.
|
||||
|
||||
::
|
||||
|
||||
@ -90,13 +101,13 @@ but client.1 cannot.
|
||||
key: AQAz7EVWygILFRAAdIcuJ12opU/JKyfFmxhuaw==
|
||||
caps: [mds] allow rwp
|
||||
caps: [mon] allow r
|
||||
caps: [osd] allow rw pool=data
|
||||
caps: [osd] allow rw tag cephfs data=cephfs_a
|
||||
|
||||
client.1
|
||||
key: AQAz7EVWygILFRAAdIcuJ12opU/JKyfFmxhuaw==
|
||||
caps: [mds] allow rw
|
||||
caps: [mon] allow r
|
||||
caps: [osd] allow rw pool=data
|
||||
caps: [osd] allow rw tag cephfs data=cephfs_a
|
||||
|
||||
|
||||
.. _User Management - Add a User to a Keyring: ../../rados/operations/user-management/#add-a-user-to-a-keyring
|
||||
|
@ -139,7 +139,9 @@ In general, an osd capability follows the grammar::
|
||||
|
||||
osdcap := grant[,grant...]
|
||||
grant := allow (match capspec | capspec match)
|
||||
match := [pool[=]<poolname> | object_prefix <prefix>]
|
||||
match := [ pool[=]<poolname> | object_prefix <prefix>
|
||||
| namespace[=]<rados-namespace>
|
||||
| tag <application-name> <key>=<value> ]
|
||||
capspec := * | [r][w][x] [class-read] [class-write]
|
||||
|
||||
The capspec determines what kind of operations the entity can perform::
|
||||
@ -149,7 +151,7 @@ The capspec determines what kind of operations the entity can perform::
|
||||
x = can call any class method (same as class-read class-write)
|
||||
class-read = can call class methods that are reads
|
||||
class-write = can call class methods that are writes
|
||||
* = equivalent to rwx, plus the ability to run osd admin commands,
|
||||
* or "all" = equivalent to rwx, plus the ability to run osd admin commands,
|
||||
i.e. ceph osd tell ...
|
||||
|
||||
The match criteria restrict a grant based on the pool being accessed.
|
||||
|
@ -92,9 +92,10 @@ Authorization (Capabilities)
|
||||
|
||||
Ceph uses the term "capabilities" (caps) to describe authorizing an
|
||||
authenticated user to exercise the functionality of the monitors, OSDs and
|
||||
metadata servers. Capabilities can also restrict access to data within a pool or
|
||||
a namespace within a pool. A Ceph administrative user sets a user's
|
||||
capabilities when creating or updating a user.
|
||||
metadata servers. Capabilities can also restrict access to data within a pool,
|
||||
a namespace within a pool, or a set of pools based on their application tags.
|
||||
A Ceph administrative user sets a user's capabilities when creating or updating
|
||||
a user.
|
||||
|
||||
Capability syntax follows the form::
|
||||
|
||||
@ -110,7 +111,7 @@ Capability syntax follows the form::
|
||||
``class-write`` access settings or ``profile {name}``. Additionally, OSD
|
||||
capabilities also allow for pool and namespace settings. ::
|
||||
|
||||
osd 'allow {access} [pool={pool-name} [namespace={namespace-name}]]'
|
||||
osd 'allow {access} [pool={pool-name} [namespace={namespace-name}]] [tag {application} {key}={value}]'
|
||||
osd 'profile {name} [pool={pool-name} [namespace={namespace-name}]]'
|
||||
|
||||
- **Metadata Server Caps:** For administrators, use ``allow *``. For all
|
||||
@ -216,6 +217,12 @@ OpenStack, a typical deployment would have pools for volumes, images, backups
|
||||
and virtual machines, and users such as ``client.glance``, ``client.cinder``,
|
||||
etc.
|
||||
|
||||
Application Tags
|
||||
----------------
|
||||
|
||||
Access may be restricted to specific pools as defined by their application
|
||||
metadata. The ``*`` wildcard may be used for the ``key`` argument, the
|
||||
``value`` argument, or both. ``all`` is a synony for ``*``.
|
||||
|
||||
Namespace
|
||||
---------
|
||||
@ -241,6 +248,11 @@ namespace to the object name with out the computational overhead of a separate
|
||||
pool. Rather than creating a separate pool for a user or set of users, you may
|
||||
use a namespace. **Note:** Only available using ``librados`` at this time.
|
||||
|
||||
Access may be restricted to specific RADOS namespaces using the ``namespace``
|
||||
capability. Limited globbing of namespaces is supported; if the last character
|
||||
of the specified namespace is ``*``, then access is granted to any namespace
|
||||
starting with the provided argument.
|
||||
|
||||
|
||||
Managing Users
|
||||
==============
|
||||
|
@ -72,6 +72,8 @@ struct MDSCapParser : qi::grammar<Iterator, MDSAuthCaps()>
|
||||
capspec = spaces >> (
|
||||
lit("*")[_val = MDSCapSpec(true, true, true, true)]
|
||||
|
|
||||
lit("all")[_val = MDSCapSpec(true, true, true, true)]
|
||||
|
|
||||
(lit("rwp"))[_val = MDSCapSpec(true, true, false, true)]
|
||||
|
|
||||
(lit("rw"))[_val = MDSCapSpec(true, true, false, false)]
|
||||
|
@ -1300,19 +1300,19 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op)
|
||||
}
|
||||
}
|
||||
|
||||
auto fs = mon->mdsmon()->get_fsmap().get_filesystem(filesystem);
|
||||
if (!fs) {
|
||||
ss << "filesystem " << filesystem << " does not exist.";
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
if (filesystem != "*" && filesystem != "all") {
|
||||
auto fs = mon->mdsmon()->get_fsmap().get_filesystem(filesystem);
|
||||
if (!fs) {
|
||||
ss << "filesystem " << filesystem << " does not exist.";
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
auto data_pools = fs->mds_map.get_data_pools();
|
||||
for (auto p : data_pools) {
|
||||
const string &pool_name = mon->osdmon()->osdmap.get_pool_name(p);
|
||||
osd_cap_string += osd_cap_string.empty() ? "" : ", ";
|
||||
osd_cap_string += "allow " + osd_cap_wanted + " pool=" + pool_name;
|
||||
}
|
||||
osd_cap_string += osd_cap_string.empty()? "" : ", ";
|
||||
osd_cap_string += "allow " + osd_cap_wanted
|
||||
+ " tag " + pg_pool_t::APPLICATION_NAME_CEPHFS
|
||||
+ " data=" + filesystem;
|
||||
|
||||
std::map<string, bufferlist> wanted_caps = {
|
||||
{ "mon", _encode_cap("allow r") },
|
||||
@ -1325,8 +1325,8 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op)
|
||||
for (const auto &sys_cap : wanted_caps) {
|
||||
if (entity_auth.caps.count(sys_cap.first) == 0 ||
|
||||
!entity_auth.caps[sys_cap.first].contents_equal(sys_cap.second)) {
|
||||
ss << "key for " << entity << " exists but cap " << sys_cap.first
|
||||
<< " does not match";
|
||||
ss << entity << " already has fs capabilities that differ from those supplied. To generate a new auth key for "
|
||||
<< entity << ", first remove " << entity << " from configuration files, execute 'ceph auth rm " << entity << "', then execute this command again.";
|
||||
err = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
@ -195,9 +195,11 @@ class FsNewHandler : public FileSystemCommandHandler
|
||||
return -EAGAIN;
|
||||
}
|
||||
mon->osdmon()->do_application_enable(data,
|
||||
pg_pool_t::APPLICATION_NAME_CEPHFS);
|
||||
pg_pool_t::APPLICATION_NAME_CEPHFS,
|
||||
"data", fs_name);
|
||||
mon->osdmon()->do_application_enable(metadata,
|
||||
pg_pool_t::APPLICATION_NAME_CEPHFS);
|
||||
pg_pool_t::APPLICATION_NAME_CEPHFS,
|
||||
"metadata", fs_name);
|
||||
mon->osdmon()->propose_pending();
|
||||
|
||||
// All checks passed, go ahead and create.
|
||||
@ -522,7 +524,9 @@ class AddDataPoolHandler : public FileSystemCommandHandler
|
||||
mon->osdmon()->wait_for_writeable(op, new PaxosService::C_RetryMessage(mon->mdsmon(), op));
|
||||
return -EAGAIN;
|
||||
}
|
||||
mon->osdmon()->do_application_enable(poolid, pg_pool_t::APPLICATION_NAME_CEPHFS);
|
||||
mon->osdmon()->do_application_enable(poolid,
|
||||
pg_pool_t::APPLICATION_NAME_CEPHFS,
|
||||
"data", poolname);
|
||||
mon->osdmon()->propose_pending();
|
||||
|
||||
fsmap.modify_filesystem(
|
||||
|
@ -530,6 +530,7 @@ struct MonCapParser : qi::grammar<Iterator, MonCap()>
|
||||
// rwxa := * | [r][w][x]
|
||||
rwxa =
|
||||
(lit("*")[_val = MON_CAP_ANY]) |
|
||||
(lit("all")[_val = MON_CAP_ANY]) |
|
||||
( eps[_val = 0] >>
|
||||
( lit('r')[_val |= MON_CAP_R] ||
|
||||
lit('w')[_val |= MON_CAP_W] ||
|
||||
|
@ -3080,7 +3080,9 @@ void OSDMonitor::check_pg_creates_sub(Subscription *sub)
|
||||
}
|
||||
|
||||
void OSDMonitor::do_application_enable(int64_t pool_id,
|
||||
const std::string &app_name)
|
||||
const std::string &app_name,
|
||||
const std::string &app_key,
|
||||
const std::string &app_value)
|
||||
{
|
||||
assert(paxos->is_plugged() && is_writeable());
|
||||
|
||||
@ -3097,7 +3099,11 @@ void OSDMonitor::do_application_enable(int64_t pool_id,
|
||||
p = pending_inc.new_pools[pool_id];
|
||||
}
|
||||
|
||||
p.application_metadata.insert({app_name, {}});
|
||||
if (app_key.empty()) {
|
||||
p.application_metadata.insert({app_name, {}});
|
||||
} else {
|
||||
p.application_metadata.insert({app_name, {{app_key, app_value}}});
|
||||
}
|
||||
p.last_change = pending_inc.epoch;
|
||||
pending_inc.new_pools[pool_id] = p;
|
||||
}
|
||||
@ -6088,6 +6094,20 @@ int OSDMonitor::prepare_command_pool_application(const string &prefix,
|
||||
cmd_getval(cct, cmdmap, "app", app);
|
||||
bool app_exists = (p.application_metadata.count(app) > 0);
|
||||
|
||||
string key;
|
||||
cmd_getval(cct, cmdmap, "key", key);
|
||||
if (key == "all") {
|
||||
ss << "key cannot be 'all'";
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
string value;
|
||||
cmd_getval(cct, cmdmap, "value", value);
|
||||
if (value == "all") {
|
||||
ss << "value cannot be 'all'";
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (boost::algorithm::ends_with(prefix, "enable")) {
|
||||
if (app.empty()) {
|
||||
ss << "application name must be provided";
|
||||
|
@ -539,7 +539,9 @@ public:
|
||||
void check_osdmap_sub(Subscription *sub);
|
||||
void check_pg_creates_sub(Subscription *sub);
|
||||
|
||||
void do_application_enable(int64_t pool_id, const std::string &app_name);
|
||||
void do_application_enable(int64_t pool_id, const std::string &app_name,
|
||||
const std::string &app_key="",
|
||||
const std::string &app_value="");
|
||||
|
||||
void add_flag(int flag) {
|
||||
if (!(osdmap.flags & flag)) {
|
||||
|
@ -6702,11 +6702,13 @@ bool OSD::ms_verify_authorizer(Connection *con, int peer_type,
|
||||
catch (buffer::error& e) {
|
||||
isvalid = false;
|
||||
}
|
||||
bool success = s->caps.parse(str);
|
||||
stringstream ss;
|
||||
bool success = s->caps.parse(str, &ss);
|
||||
if (success)
|
||||
dout(10) << " session " << s << " " << s->entity_name << " has caps " << s->caps << " '" << str << "'" << dendl;
|
||||
else {
|
||||
dout(10) << " session " << s << " " << s->entity_name << " failed to parse caps '" << str << "'" << dendl;
|
||||
dout(20) << "parser returned " << ss.str() << dendl;
|
||||
isvalid = false;
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/phoenix_operator.hpp>
|
||||
#include <boost/spirit/include/phoenix.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
#include "OSDCap.h"
|
||||
#include "common/config.h"
|
||||
@ -70,14 +71,27 @@ ostream& operator<<(ostream& out, const OSDCapPoolNamespace& pns)
|
||||
return out;
|
||||
}
|
||||
|
||||
ostream& operator<<(ostream &out, const OSDCapPoolTag &pt)
|
||||
{
|
||||
out << "app " << pt.application << " key " << pt.key << " val " << pt.value
|
||||
<< " ";
|
||||
return out;
|
||||
}
|
||||
|
||||
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) {
|
||||
out << m.pool_namespace;
|
||||
}
|
||||
|
||||
if (!m.pool_tag.application.empty()) {
|
||||
out << m.pool_tag;
|
||||
}
|
||||
|
||||
if (m.object_prefix.length()) {
|
||||
out << "object_prefix " << m.object_prefix << " ";
|
||||
}
|
||||
@ -100,6 +114,11 @@ bool OSDCapPoolNamespace::is_match(const std::string& pn,
|
||||
}
|
||||
}
|
||||
if (nspace) {
|
||||
if ((*nspace)[nspace->length() - 1] == '*' &&
|
||||
boost::starts_with(ns, nspace->substr(0, nspace->length() - 1))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (*nspace != ns) {
|
||||
return false;
|
||||
}
|
||||
@ -116,14 +135,52 @@ bool OSDCapPoolNamespace::is_match_all() const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OSDCapPoolTag::is_match(const app_map_t& app_map) const
|
||||
{
|
||||
if (application.empty()) {
|
||||
return true;
|
||||
}
|
||||
auto kv_map = app_map.find(application);
|
||||
if (kv_map == app_map.end()) {
|
||||
return false;
|
||||
}
|
||||
if (!key.compare("*") && !value.compare("*")) {
|
||||
return true;
|
||||
}
|
||||
if (!key.compare("*")) {
|
||||
for (auto it : kv_map->second) {
|
||||
if (it.second == value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
auto kv_val = kv_map->second.find(key);
|
||||
if (kv_val == kv_map->second.end()) {
|
||||
return false;
|
||||
}
|
||||
if (!value.compare("*")) {
|
||||
return true;
|
||||
}
|
||||
return kv_val->second == value;
|
||||
}
|
||||
|
||||
bool OSDCapPoolTag::is_match_all() const {
|
||||
return application.empty();
|
||||
}
|
||||
|
||||
bool OSDCapMatch::is_match(const string& pn, const string& ns,
|
||||
int64_t pool_auid, const string& object) const
|
||||
int64_t pool_auid,
|
||||
const OSDCapPoolTag::app_map_t& app_map,
|
||||
const string& object) const
|
||||
{
|
||||
if (auid >= 0) {
|
||||
if (auid != pool_auid)
|
||||
return false;
|
||||
} else if (!pool_namespace.is_match(pn, ns)) {
|
||||
return false;
|
||||
} else if (!pool_tag.is_match(app_map)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (object_prefix.length()) {
|
||||
@ -139,6 +196,8 @@ bool OSDCapMatch::is_match_all() const
|
||||
return false;
|
||||
} else if (!pool_namespace.is_match_all()) {
|
||||
return false;
|
||||
} else if (!pool_tag.is_match_all()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (object_prefix.length()) {
|
||||
@ -180,7 +239,9 @@ bool OSDCapGrant::allow_all() const
|
||||
}
|
||||
|
||||
bool OSDCapGrant::is_capable(const string& pool_name, const string& ns,
|
||||
int64_t pool_auid, const string& object,
|
||||
int64_t pool_auid,
|
||||
const OSDCapPoolTag::app_map_t& application_metadata,
|
||||
const string& object,
|
||||
bool op_may_read, bool op_may_write,
|
||||
const std::vector<OpRequest::ClassInfo>& classes,
|
||||
std::vector<bool>* class_allowed) const
|
||||
@ -189,11 +250,14 @@ bool OSDCapGrant::is_capable(const string& pool_name, const string& ns,
|
||||
if (profile.is_valid()) {
|
||||
return std::any_of(profile_grants.cbegin(), profile_grants.cend(),
|
||||
[&](const OSDCapGrant& grant) {
|
||||
return grant.is_capable(pool_name, ns, pool_auid, object, op_may_read,
|
||||
op_may_write, classes, class_allowed);
|
||||
});
|
||||
return grant.is_capable(pool_name, ns, pool_auid,
|
||||
application_metadata,
|
||||
object, op_may_read,
|
||||
op_may_write, classes,
|
||||
class_allowed);
|
||||
});
|
||||
} else {
|
||||
if (match.is_match(pool_name, ns, pool_auid, object)) {
|
||||
if (match.is_match(pool_name, ns, pool_auid, application_metadata, object)) {
|
||||
allow = allow | spec.allow;
|
||||
if ((op_may_read && !(allow & OSD_CAP_R)) ||
|
||||
(op_may_write && !(allow & OSD_CAP_W))) {
|
||||
@ -283,14 +347,17 @@ void OSDCap::set_allow_all()
|
||||
}
|
||||
|
||||
bool OSDCap::is_capable(const string& pool_name, const string& ns,
|
||||
int64_t pool_auid, const string& object,
|
||||
int64_t pool_auid,
|
||||
const OSDCapPoolTag::app_map_t& application_metadata,
|
||||
const string& object,
|
||||
bool op_may_read, bool op_may_write,
|
||||
const std::vector<OpRequest::ClassInfo>& classes) const
|
||||
{
|
||||
std::vector<bool> class_allowed(classes.size(), false);
|
||||
for (auto &grant : grants) {
|
||||
if (grant.is_capable(pool_name, ns, pool_auid, 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;
|
||||
}
|
||||
}
|
||||
@ -331,21 +398,32 @@ struct OSDCapParser : qi::grammar<Iterator, OSDCap()>
|
||||
|
||||
spaces = +ascii::space;
|
||||
|
||||
wildcard = (lit('*') | lit("all")) [_val = "*"];
|
||||
|
||||
pool_name %= -(spaces >> lit("pool") >> (lit('=') | spaces) >> str);
|
||||
nspace %= (spaces >> lit("namespace") >> (lit('=') | spaces) >> estr);
|
||||
nspace %= (spaces >> lit("namespace")
|
||||
>> (lit('=') | spaces)
|
||||
>> estr >> -char_('*'));
|
||||
|
||||
// match := [pool[=]<poolname> [namespace[=]<namespace>] | auid <123>] [object_prefix <prefix>]
|
||||
auid %= (spaces >> lit("auid") >> spaces >> int_);
|
||||
object_prefix %= -(spaces >> lit("object_prefix") >> spaces >> str);
|
||||
pooltag %= (spaces >> lit("tag")
|
||||
>> spaces >> str // application
|
||||
>> spaces >> (wildcard | str) // key
|
||||
>> -spaces >> lit('=') >> -spaces >> (wildcard | str)); // value
|
||||
|
||||
match = (
|
||||
pooltag [_val = phoenix::construct<OSDCapMatch>(_1)] |
|
||||
(nspace >> pooltag) [_val = phoenix::construct<OSDCapMatch>(_1, _2)] |
|
||||
(auid >> object_prefix) [_val = phoenix::construct<OSDCapMatch>(_1, _2)] |
|
||||
(pool_name >> nspace >> object_prefix) [_val = phoenix::construct<OSDCapMatch>(_1, _2, _3)] |
|
||||
(pool_name >> object_prefix) [_val = phoenix::construct<OSDCapMatch>(_1, _2)]);
|
||||
(pool_name >> object_prefix) [_val = phoenix::construct<OSDCapMatch>(_1, _2)]
|
||||
);
|
||||
|
||||
// rwxa := * | [r][w][x] [class-read] [class-write]
|
||||
rwxa =
|
||||
(spaces >> lit("*")[_val = OSD_CAP_ANY]) |
|
||||
(spaces >> wildcard[_val = OSD_CAP_ANY]) |
|
||||
( eps[_val = 0] >>
|
||||
(
|
||||
spaces >>
|
||||
@ -383,6 +461,7 @@ struct OSDCapParser : qi::grammar<Iterator, OSDCap()>
|
||||
qi::rule<Iterator, string()> quoted_string, equoted_string;
|
||||
qi::rule<Iterator, string()> unquoted_word;
|
||||
qi::rule<Iterator, string()> str, estr;
|
||||
qi::rule<Iterator, string()> wildcard;
|
||||
qi::rule<Iterator, int()> auid;
|
||||
qi::rule<Iterator, string()> class_name;
|
||||
qi::rule<Iterator, string()> class_cap;
|
||||
@ -390,6 +469,7 @@ struct OSDCapParser : qi::grammar<Iterator, OSDCap()>
|
||||
qi::rule<Iterator, string()> pool_name;
|
||||
qi::rule<Iterator, string()> nspace;
|
||||
qi::rule<Iterator, string()> object_prefix;
|
||||
qi::rule<Iterator, OSDCapPoolTag()> pooltag;
|
||||
qi::rule<Iterator, OSDCapMatch()> match;
|
||||
qi::rule<Iterator, string()> profile_name;
|
||||
qi::rule<Iterator, OSDCapProfile()> profile;
|
||||
@ -417,4 +497,3 @@ bool OSDCap::parse(const string& str, ostream *err)
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,7 @@ using std::ostream;
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/fusion/include/adapt_struct.hpp>
|
||||
|
||||
static const __u8 OSD_CAP_R = (1 << 1); // read
|
||||
static const __u8 OSD_CAP_W = (1 << 2); // write
|
||||
@ -95,14 +96,38 @@ struct OSDCapPoolNamespace {
|
||||
|
||||
ostream& operator<<(ostream& out, const OSDCapPoolNamespace& pns);
|
||||
|
||||
struct OSDCapPoolTag {
|
||||
typedef std::map<std::string, std::map<std::string, std::string> > app_map_t;
|
||||
std::string application;
|
||||
std::string key;
|
||||
std::string value;
|
||||
|
||||
OSDCapPoolTag () {}
|
||||
OSDCapPoolTag(const std::string& application, const std::string& key,
|
||||
const std::string& value) :
|
||||
application(application), key(key), value(value) {}
|
||||
|
||||
bool is_match(const app_map_t& app_map) const;
|
||||
bool is_match_all() const;
|
||||
};
|
||||
// adapt for parsing with boost::spirit::qi in OSDCapParser
|
||||
BOOST_FUSION_ADAPT_STRUCT(OSDCapPoolTag,
|
||||
(std::string, application)
|
||||
(std::string, key)
|
||||
(std::string, value))
|
||||
|
||||
ostream& operator<<(ostream& out, const OSDCapPoolTag& pt);
|
||||
|
||||
struct OSDCapMatch {
|
||||
typedef std::map<std::string, std::map<std::string, std::string> > app_map_t;
|
||||
// auid and pool_name/nspace are mutually exclusive
|
||||
int64_t auid = CEPH_AUTH_UID_DEFAULT;
|
||||
OSDCapPoolNamespace pool_namespace;
|
||||
OSDCapPoolTag pool_tag;
|
||||
std::string object_prefix;
|
||||
|
||||
OSDCapMatch() {}
|
||||
OSDCapMatch(const OSDCapPoolTag& pt) : pool_tag(pt) {}
|
||||
OSDCapMatch(const OSDCapPoolNamespace& pns) : pool_namespace(pns) {}
|
||||
OSDCapMatch(const std::string& pl, const std::string& pre)
|
||||
: pool_namespace(pl), object_prefix(pre) {}
|
||||
@ -111,6 +136,11 @@ struct OSDCapMatch {
|
||||
: pool_namespace(pl, ns), object_prefix(pre) {}
|
||||
OSDCapMatch(uint64_t auid, const std::string& pre)
|
||||
: auid(auid), object_prefix(pre) {}
|
||||
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
|
||||
@ -122,7 +152,8 @@ struct OSDCapMatch {
|
||||
* @return true if we match, false otherwise
|
||||
*/
|
||||
bool is_match(const std::string& pool_name, const std::string& nspace_name,
|
||||
int64_t pool_auid, const std::string& object) const;
|
||||
int64_t pool_auid, const app_map_t& app_map,
|
||||
const std::string& object) const;
|
||||
bool is_match_all() const;
|
||||
};
|
||||
|
||||
@ -165,6 +196,7 @@ struct OSDCapGrant {
|
||||
|
||||
bool allow_all() const;
|
||||
bool is_capable(const string& pool_name, const string& ns, int64_t pool_auid,
|
||||
const OSDCapPoolTag::app_map_t& application_metadata,
|
||||
const string& object, bool op_may_read, bool op_may_write,
|
||||
const std::vector<OpRequest::ClassInfo>& classes,
|
||||
std::vector<bool>* class_allowed) const;
|
||||
@ -202,6 +234,7 @@ struct OSDCap {
|
||||
* @return true if the operation is allowed, false otherwise
|
||||
*/
|
||||
bool is_capable(const string& pool_name, const string& ns, int64_t pool_auid,
|
||||
const OSDCapPoolTag::app_map_t& application_metadata,
|
||||
const string& object, bool op_may_read, bool op_may_write,
|
||||
const std::vector<OpRequest::ClassInfo>& classes) const;
|
||||
};
|
||||
|
@ -1879,7 +1879,9 @@ bool PG::op_has_sufficient_caps(OpRequestRef& op)
|
||||
req->get_hobj().get_key();
|
||||
|
||||
bool cap = caps.is_capable(pool.name, req->get_hobj().nspace,
|
||||
pool.auid, key,
|
||||
pool.auid,
|
||||
pool.info.application_metadata,
|
||||
key,
|
||||
op->need_read_cap(),
|
||||
op->need_write_cap(),
|
||||
op->classes());
|
||||
@ -1889,6 +1891,7 @@ bool PG::op_has_sufficient_caps(OpRequestRef& op)
|
||||
<< " pool=" << pool.id << " (" << pool.name
|
||||
<< " " << req->get_hobj().nspace
|
||||
<< ") owner=" << pool.auid
|
||||
<< " pool_app_metadata=" << pool.info.application_metadata
|
||||
<< " need_read_cap=" << op->need_read_cap()
|
||||
<< " need_write_cap=" << op->need_write_cap()
|
||||
<< " classes=" << op->classes()
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -558,6 +558,12 @@ start_mon() {
|
||||
--cap mgr 'allow *' \
|
||||
"$keyring_fn"
|
||||
|
||||
prun $SUDO "$CEPH_BIN/ceph-authtool" --gen-key --name=client.fs --set-uid=0 \
|
||||
--cap mon 'allow r' \
|
||||
--cap osd 'allow rw tag cephfs data=*' \
|
||||
--cap mds 'allow rwp' \
|
||||
"$keyring_fn"
|
||||
|
||||
prun $SUDO "$CEPH_BIN/ceph-authtool" --gen-key --name=client.rgw \
|
||||
--cap mon 'allow rw' \
|
||||
--cap osd 'allow rwx' \
|
||||
@ -705,7 +711,7 @@ EOF
|
||||
EOF
|
||||
fi
|
||||
prun $SUDO "$CEPH_BIN/ceph-authtool" --create-keyring --gen-key --name="mds.$name" "$key_fn"
|
||||
ceph_adm -i "$key_fn" auth add "mds.$name" mon 'allow profile mds' osd 'allow *' mds 'allow' mgr 'allow profile mds'
|
||||
ceph_adm -i "$key_fn" auth add "mds.$name" mon 'allow profile mds' osd 'allow rw tag cephfs *=*' mds 'allow' mgr 'allow profile mds'
|
||||
if [ "$standby" -eq 1 ]; then
|
||||
prun $SUDO "$CEPH_BIN/ceph-authtool" --create-keyring --gen-key --name="mds.${name}s" \
|
||||
"$CEPH_DEV_DIR/mds.${name}s/keyring"
|
||||
@ -736,6 +742,7 @@ EOF
|
||||
ceph_adm osd pool create "cephfs_data_${name}" 8
|
||||
ceph_adm osd pool create "cephfs_metadata_${name}" 8
|
||||
ceph_adm fs new "cephfs_${name}" "cephfs_metadata_${name}" "cephfs_data_${name}"
|
||||
ceph_adm fs authorize "cephfs_${name}" "client.fs_${name}" / rwp
|
||||
fs=$(($fs + 1))
|
||||
[ $fs -eq $CEPH_NUM_FS ] && break
|
||||
done
|
||||
|
Loading…
Reference in New Issue
Block a user