Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

osd: support class method whitelisting within caps #19786

Merged
merged 4 commits into from
Jan 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion admin/build-doc
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ if command -v dpkg >/dev/null; then
fi
elif command -v yum >/dev/null; then
for package in python-devel python-pip python-virtualenv doxygen ditaa ant libxml2-devel libxslt-devel Cython graphviz; do
if ! rpm -q $package >/dev/null ; then
if ! rpm -q --whatprovides $package >/dev/null ; then
missing="${missing:+$missing }$package"
fi
done
Expand Down
33 changes: 26 additions & 7 deletions doc/rados/operations/user-management.rst
Original file line number Diff line number Diff line change
Expand Up @@ -99,21 +99,39 @@ a user.

Capability syntax follows the form::

{daemon-type} '{capspec}[, {capspec} ...]'
{daemon-type} '{cap-spec}[, {cap-spec} ...]'

- **Monitor Caps:** Monitor capabilities include ``r``, ``w``, ``x`` access
settings or ``profile {name}``. For example::

mon 'allow rwx'
mon 'profile osd'
mon 'allow {access-spec}'

mon 'profile {name}'

The ``{access-spec}`` syntax is as follows: ::

* | all | [r][w][x]

- **OSD Caps:** OSD capabilities include ``r``, ``w``, ``x``, ``class-read``,
``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}]] [tag {application} {key}={value}]'
osd 'allow {access-spec} [{match-spec}]'

osd 'profile {name} [pool={pool-name} [namespace={namespace-name}]]'

The ``{access-spec}`` syntax is either of the following: ::

* | all | [r][w][x] [class-read] [class-write]

class {class name} [{method name}]

The optional ``{match-spec}`` syntax is either of the following: ::

pool={pool-name} [namespace={namespace-name}] [object_prefix {prefix}]

[namespace={namespace-name}] tag {application} {key}={value}

- **Metadata Server Caps:** For administrators, use ``allow *``. For all
other users, such as CephFS clients, consult :doc:`/cephfs/client-auth`

Expand All @@ -122,7 +140,7 @@ Capability syntax follows the form::
Ceph Storage Cluster, so it is not represented as a Ceph Storage
Cluster daemon type.

The following entries describe each capability.
The following entries describe each access capability.

``allow``

Expand Down Expand Up @@ -160,12 +178,13 @@ The following entries describe each capability.
Subset of ``x``.


``*``
``*``, ``all``

:Description: Gives the user read, write and execute permissions for a
particular daemon/pool, and the ability to execute
admin commands.

The following entries describe valid capability profiles:

``profile osd`` (Monitor only)

Expand Down Expand Up @@ -204,7 +223,7 @@ The following entries describe each capability.

``profile rbd-read-only`` (OSD only)

:Description: Gives a user read-only permissions to an RBD image.
:Description: Gives a user read-only permissions to RBD images.


Pool
Expand Down
3 changes: 2 additions & 1 deletion src/osd/OSD.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9676,7 +9676,8 @@ int OSD::init_op_flags(OpRequestRef& op)
op->set_class_write();
if (is_promote)
op->set_promote();
op->add_class(cname, is_read, is_write, cls->whitelisted);
op->add_class(std::move(cname), std::move(mname), is_read, is_write,
cls->whitelisted);
break;
}

Expand Down
25 changes: 16 additions & 9 deletions src/osd/OSDCap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,12 @@ ostream& operator<<(ostream& out, const OSDCapSpec& s)
{
if (s.allow)
return out << s.allow;
if (s.class_name.length())
return out << "class '" << s.class_name << "' '" << s.class_allow << "'";
if (s.class_name.length()) {
out << "class '" << s.class_name << "'";
if (!s.method_name.empty()) {
out << " '" << s.method_name << "'";
}
}
return out;
}

Expand Down Expand Up @@ -271,8 +275,11 @@ bool OSDCapGrant::is_capable(const string& pool_name, const string& ns,

// compare this grant to each class in the operation
for (size_t i = 0; i < classes.size(); ++i) {
// check 'allow class foo'
if (!spec.class_name.empty() && classes[i].name == spec.class_name) {
// check 'allow class foo [method_name]'
if (!spec.class_name.empty() &&
classes[i].class_name == spec.class_name &&
(spec.method_name.empty() ||
classes[i].method_name == spec.method_name)) {
(*class_allowed)[i] = true;
continue;
}
Expand Down Expand Up @@ -433,12 +440,12 @@ struct OSDCapParser : qi::grammar<Iterator, OSDCap()>
( (spaces >> lit("class-read")[_val |= OSD_CAP_CLS_R]) ||
(spaces >> lit("class-write")[_val |= OSD_CAP_CLS_W]) ));

// capspec := * | rwx | class <name> [classcap]
// capspec := * | rwx | class <name> [<method name>]
class_name %= (spaces >> lit("class") >> spaces >> str);
class_cap %= -(spaces >> str);
method_name %= -(spaces >> str);
capspec = (
(rwxa) [_val = phoenix::construct<OSDCapSpec>(_1)] |
(class_name >> class_cap) [_val = phoenix::construct<OSDCapSpec>(_1, _2)]);
(rwxa) [_val = phoenix::construct<OSDCapSpec>(_1)] |
(class_name >> method_name) [_val = phoenix::construct<OSDCapSpec>(_1, _2)]);

// profile := profile <name> [pool[=]<pool> [namespace[=]<namespace>]]
profile_name %= (lit("profile") >> (lit('=') | spaces) >> str);
Expand All @@ -464,7 +471,7 @@ struct OSDCapParser : qi::grammar<Iterator, OSDCap()>
qi::rule<Iterator, string()> wildcard;
qi::rule<Iterator, int()> auid;
qi::rule<Iterator, string()> class_name;
qi::rule<Iterator, string()> class_cap;
qi::rule<Iterator, string()> method_name;
qi::rule<Iterator, OSDCapSpec()> capspec;
qi::rule<Iterator, string()> pool_name;
qi::rule<Iterator, string()> nspace;
Expand Down
8 changes: 4 additions & 4 deletions src/osd/OSDCap.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@ ostream& operator<<(ostream& out, const osd_rwxa_t& p);
struct OSDCapSpec {
osd_rwxa_t allow;
std::string class_name;
std::string class_allow;
std::string method_name;

OSDCapSpec() : allow(0) {}
explicit OSDCapSpec(osd_rwxa_t v) : allow(v) {}
explicit OSDCapSpec(std::string n) : allow(0), class_name(std::move(n)) {}
OSDCapSpec(std::string n, std::string a) :
allow(0), class_name(std::move(n)), class_allow(std::move(a)) {}
OSDCapSpec(std::string class_name, std::string method_name)
: allow(0), class_name(std::move(class_name)),
method_name(std::move(method_name)) {}

bool allow_all() const {
return allow == OSD_CAP_ANY;
Expand Down
4 changes: 2 additions & 2 deletions src/osd/OpRequest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ bool OpRequest::filter_out(const set<string>& filters)

ostream& operator<<(ostream& out, const OpRequest::ClassInfo& i)
{
out << "class " << i.name << " rd " << i.read
<< " wr " << i.write << " wl " << i.whitelisted;
out << "class " << i.class_name << " method " << i.method_name
<< " rd " << i.read << " wr " << i.write << " wl " << i.whitelisted;
return out;
}
17 changes: 10 additions & 7 deletions src/osd/OpRequest.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,20 @@ struct OpRequest : public TrackedOp {
void set_force_rwordered();

struct ClassInfo {
ClassInfo(const std::string& name, bool read, bool write,
bool whitelisted) :
name(name), read(read), write(write), whitelisted(whitelisted)
ClassInfo(std::string&& class_name, std::string&& method_name,
bool read, bool write, bool whitelisted) :
class_name(std::move(class_name)), method_name(std::move(method_name)),
read(read), write(write), whitelisted(whitelisted)
{}
const std::string name;
const std::string class_name;
const std::string method_name;
const bool read, write, whitelisted;
};

void add_class(const std::string& name, bool read, bool write,
bool whitelisted) {
classes_.emplace_back(name, read, write, whitelisted);
void add_class(std::string&& class_name, std::string&& method_name,
bool read, bool write, bool whitelisted) {
classes_.emplace_back(std::move(class_name), std::move(method_name),
read, write, whitelisted);
}

std::vector<ClassInfo> classes() const {
Expand Down