]>
git.proxmox.com Git - ceph.git/blob - ceph/src/osd/OSDCap.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2009-2011 New Dream Network
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
15 #include <boost/config/warning_disable.hpp>
16 #include <boost/spirit/include/qi.hpp>
17 #include <boost/spirit/include/phoenix_operator.hpp>
18 #include <boost/spirit/include/phoenix.hpp>
21 #include "common/config.h"
22 #include "common/debug.h"
27 ostream
& operator<<(ostream
& out
, const osd_rwxa_t
& p
)
36 if ((p
& OSD_CAP_X
) == OSD_CAP_X
) {
39 if (p
& OSD_CAP_CLS_R
)
41 if (p
& OSD_CAP_CLS_W
)
42 out
<< " class-write";
47 ostream
& operator<<(ostream
& out
, const OSDCapSpec
& s
)
50 return out
<< s
.allow
;
51 if (s
.class_name
.length())
52 return out
<< "class '" << s
.class_name
<< "' '" << s
.class_allow
<< "'";
56 ostream
& operator<<(ostream
& out
, const OSDCapMatch
& m
)
59 out
<< "auid " << m
.auid
<< " ";
61 if (m
.object_prefix
.length()) {
62 out
<< "object_prefix " << m
.object_prefix
<< " ";
64 if (m
.pool_name
.length()) {
65 out
<< "pool " << m
.pool_name
<< " ";
69 if (m
.nspace
.length() == 0)
78 bool OSDCapMatch::is_match(const string
& pn
, const string
& ns
, int64_t pool_auid
, const string
& object
) const
81 if (auid
!= pool_auid
)
84 if (pool_name
.length()) {
92 if (object_prefix
.length()) {
93 if (object
.find(object_prefix
) != 0)
99 bool OSDCapMatch::is_match_all() const
103 if (pool_name
.length())
107 if (object_prefix
.length())
112 ostream
& operator<<(ostream
& out
, const OSDCapGrant
& g
)
114 return out
<< "grant(" << g
.match
<< g
.spec
<< ")";
118 bool OSDCap::allow_all() const
120 for (vector
<OSDCapGrant
>::const_iterator p
= grants
.begin(); p
!= grants
.end(); ++p
)
121 if (p
->match
.is_match_all() && p
->spec
.allow_all())
126 void OSDCap::set_allow_all()
129 grants
.push_back(OSDCapGrant(OSDCapMatch(), OSDCapSpec(OSD_CAP_ANY
)));
132 bool OSDCap::is_capable(const string
& pool_name
, const string
& ns
, int64_t pool_auid
,
133 const string
& object
, bool op_may_read
, bool op_may_write
,
134 const std::vector
<OpRequest::ClassInfo
>& classes
) const
136 const size_t num_classes
= classes
.size();
137 std::vector
<bool> class_allowed(num_classes
, false);
138 osd_rwxa_t allow
= 0;
139 for (vector
<OSDCapGrant
>::const_iterator p
= grants
.begin();
140 p
!= grants
.end(); ++p
) {
141 if (p
->match
.is_match(pool_name
, ns
, pool_auid
, object
)) {
142 allow
= allow
| p
->spec
.allow
;
143 if ((op_may_read
&& !(allow
& OSD_CAP_R
)) ||
144 (op_may_write
&& !(allow
& OSD_CAP_W
)))
148 if (p
->spec
.allow_all())
150 // compare this grant to each class in the operation
151 for (size_t i
= 0; i
< num_classes
; i
++) {
152 // check 'allow class foo'
153 if (classes
[i
].name
== p
->spec
.class_name
&&
154 !p
->spec
.class_name
.empty()) {
155 class_allowed
[i
] = true;
158 // check 'allow x | class-{rw}': must be on whitelist
159 if (!classes
[i
].whitelisted
)
161 if ((classes
[i
].read
&& !(allow
& OSD_CAP_CLS_R
)) ||
162 (classes
[i
].write
&& !(allow
& OSD_CAP_CLS_W
))) {
165 class_allowed
[i
] = true;
167 if (std::all_of(class_allowed
.cbegin(), class_allowed
.cend(),
168 [](bool v
) { return v
; }))
181 namespace qi
= boost::spirit::qi
;
182 namespace ascii
= boost::spirit::ascii
;
183 namespace phoenix
= boost::phoenix
;
185 template <typename Iterator
>
186 struct OSDCapParser
: qi::grammar
<Iterator
, OSDCap()>
188 OSDCapParser() : OSDCapParser::base_type(osdcap
)
202 lexeme
['"' >> +(char_
- '"') >> '"'] |
203 lexeme
['\'' >> +(char_
- '\'') >> '\''];
205 lexeme
['"' >> *(char_
- '"') >> '"'] |
206 lexeme
['\'' >> *(char_
- '\'') >> '\''];
207 unquoted_word
%= +char_("a-zA-Z0-9_.-");
208 str
%= quoted_string
| unquoted_word
;
209 estr
%= equoted_string
| unquoted_word
;
211 spaces
= +ascii::space
;
214 // match := [pool[=]<poolname> [namespace[=]<namespace>] | auid <123>] [object_prefix <prefix>]
215 pool_name
%= -(spaces
>> lit("pool") >> (lit('=') | spaces
) >> str
);
216 nspace
%= (spaces
>> lit("namespace") >> (lit('=') | spaces
) >> estr
);
217 auid
%= (spaces
>> lit("auid") >> spaces
>> int_
);
218 object_prefix
%= -(spaces
>> lit("object_prefix") >> spaces
>> str
);
220 match
= ( (auid
>> object_prefix
) [_val
= phoenix::construct
<OSDCapMatch
>(_1
, _2
)] |
221 (pool_name
>> nspace
>> object_prefix
) [_val
= phoenix::construct
<OSDCapMatch
>(_1
, _2
, _3
)] |
222 (pool_name
>> object_prefix
) [_val
= phoenix::construct
<OSDCapMatch
>(_1
, _2
)]);
224 // rwxa := * | [r][w][x] [class-read] [class-write]
226 (spaces
>> lit("*")[_val
= OSD_CAP_ANY
]) |
230 ( lit('r')[_val
|= OSD_CAP_R
] ||
231 lit('w')[_val
|= OSD_CAP_W
] ||
232 lit('x')[_val
|= OSD_CAP_X
] )) ||
233 ( (spaces
>> lit("class-read")[_val
|= OSD_CAP_CLS_R
]) ||
234 (spaces
>> lit("class-write")[_val
|= OSD_CAP_CLS_W
]) ));
236 // capspec := * | rwx | class <name> [classcap]
238 rwxa
[_val
= phoenix::construct
<OSDCapSpec
>(_1
)] |
239 ( spaces
>> lit("class") >> spaces
>> ((str
>> spaces
>> str
) [_val
= phoenix::construct
<OSDCapSpec
>(_1
, _2
)] |
240 str
[_val
= phoenix::construct
<OSDCapSpec
>(_1
, string())] ));
242 // grant := allow match capspec
243 grant
= (*ascii::blank
>> lit("allow") >>
244 ((capspec
>> match
) [_val
= phoenix::construct
<OSDCapGrant
>(_2
, _1
)] |
245 (match
>> capspec
) [_val
= phoenix::construct
<OSDCapGrant
>(_1
, _2
)]) >>
247 // osdcap := grant [grant ...]
248 grants
%= (grant
% (lit(';') | lit(',')));
249 osdcap
= grants
[_val
= phoenix::construct
<OSDCap
>(_1
)];
251 qi::rule
<Iterator
> spaces
;
252 qi::rule
<Iterator
, unsigned()> rwxa
;
253 qi::rule
<Iterator
, string()> quoted_string
, equoted_string
;
254 qi::rule
<Iterator
, string()> unquoted_word
;
255 qi::rule
<Iterator
, string()> str
, estr
;
256 qi::rule
<Iterator
, int()> auid
;
257 qi::rule
<Iterator
, OSDCapSpec()> capspec
;
258 qi::rule
<Iterator
, string()> pool_name
;
259 qi::rule
<Iterator
, string()> nspace
;
260 qi::rule
<Iterator
, string()> object_prefix
;
261 qi::rule
<Iterator
, OSDCapMatch()> match
;
262 qi::rule
<Iterator
, OSDCapGrant()> grant
;
263 qi::rule
<Iterator
, std::vector
<OSDCapGrant
>()> grants
;
264 qi::rule
<Iterator
, OSDCap()> osdcap
;
267 bool OSDCap::parse(const string
& str
, ostream
*err
)
269 OSDCapParser
<string::const_iterator
> g
;
270 string::const_iterator iter
= str
.begin();
271 string::const_iterator end
= str
.end();
273 bool r
= qi::phrase_parse(iter
, end
, g
, ascii::space
, *this);
274 if (r
&& iter
== end
)
277 // Make sure no grants are kept after parsing failed!
281 *err
<< "osdcap parse failed, stopped at '" << std::string(iter
, end
)
282 << "' of '" << str
<< "'\n";