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:
Patrick Donnelly 2017-11-21 13:49:24 -08:00
commit 06e2cec1ea
No known key found for this signature in database
GPG Key ID: 3A2A7E25BEA8AADB
15 changed files with 992 additions and 589 deletions

View File

@ -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

View File

@ -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.

View File

@ -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
==============

View File

@ -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)]

View File

@ -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;
}

View File

@ -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(

View File

@ -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] ||

View File

@ -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";

View File

@ -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)) {

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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

View File

@ -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