]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #ifndef CEPH_MONCAP_H | |
5 | #define CEPH_MONCAP_H | |
6 | ||
7 | #include <ostream> | |
7c673cae | 8 | |
9f95a23c | 9 | #include "include/common_fwd.h" |
7c673cae FG |
10 | #include "include/types.h" |
11 | #include "common/entity_name.h" | |
f67539c2 | 12 | #include "mds/mdstypes.h" |
7c673cae | 13 | |
7c673cae FG |
14 | static const __u8 MON_CAP_R = (1 << 1); // read |
15 | static const __u8 MON_CAP_W = (1 << 2); // write | |
16 | static const __u8 MON_CAP_X = (1 << 3); // execute | |
17 | static const __u8 MON_CAP_ALL = MON_CAP_R | MON_CAP_W | MON_CAP_X; | |
18 | static const __u8 MON_CAP_ANY = 0xff; // * | |
19 | ||
20 | struct mon_rwxa_t { | |
21 | __u8 val; | |
22 | ||
23 | // cppcheck-suppress noExplicitConstructor | |
24 | mon_rwxa_t(__u8 v = 0) : val(v) {} | |
25 | mon_rwxa_t& operator=(__u8 v) { | |
26 | val = v; | |
27 | return *this; | |
28 | } | |
29 | operator __u8() const { | |
30 | return val; | |
31 | } | |
32 | }; | |
33 | ||
9f95a23c | 34 | std::ostream& operator<<(std::ostream& out, const mon_rwxa_t& p); |
7c673cae FG |
35 | |
36 | struct StringConstraint { | |
c07f9fc5 FG |
37 | enum MatchType { |
38 | MATCH_TYPE_NONE, | |
39 | MATCH_TYPE_EQUAL, | |
40 | MATCH_TYPE_PREFIX, | |
41 | MATCH_TYPE_REGEX | |
42 | }; | |
43 | ||
44 | MatchType match_type = MATCH_TYPE_NONE; | |
9f95a23c | 45 | std::string value; |
7c673cae FG |
46 | |
47 | StringConstraint() {} | |
9f95a23c | 48 | StringConstraint(MatchType match_type, std::string value) |
c07f9fc5 FG |
49 | : match_type(match_type), value(value) { |
50 | } | |
7c673cae FG |
51 | }; |
52 | ||
9f95a23c | 53 | std::ostream& operator<<(std::ostream& out, const StringConstraint& c); |
7c673cae FG |
54 | |
55 | struct MonCapGrant { | |
56 | /* | |
f67539c2 | 57 | * A grant can come in one of five forms: |
7c673cae FG |
58 | * |
59 | * - a blanket allow ('allow rw', 'allow *') | |
60 | * - this will match against any service and the read/write/exec flags | |
61 | * in the mon code. semantics of what X means are somewhat ad hoc. | |
62 | * | |
63 | * - a service allow ('allow service mds rw') | |
64 | * - this will match against a specific service and the r/w/x flags. | |
65 | * | |
66 | * - a profile ('allow profile osd') | |
67 | * - this will match against specific monitor-enforced semantics of what | |
68 | * this type of user should need to do. examples include 'osd', 'mds', | |
69 | * 'bootstrap-osd'. | |
70 | * | |
71 | * - a command ('allow command foo', 'allow command bar with arg1=val1 arg2 prefix val2') | |
72 | * this includes the command name (the prefix string), and a set | |
73 | * of key/value pairs that constrain use of that command. if no pairs | |
74 | * are specified, any arguments are allowed; if a pair is specified, that | |
75 | * argument must be present and equal or match a prefix. | |
f67539c2 TL |
76 | * |
77 | * - an fs name ('allow fsname foo') | |
78 | * - this will restrict access to MDSMaps in the FSMap to the provided | |
79 | * fs name. | |
7c673cae FG |
80 | */ |
81 | std::string service; | |
82 | std::string profile; | |
83 | std::string command; | |
9f95a23c | 84 | std::map<std::string, StringConstraint> command_args; |
f67539c2 | 85 | std::string fs_name; |
7c673cae | 86 | |
11fdf7f2 TL |
87 | // restrict by network |
88 | std::string network; | |
89 | ||
90 | // these are filled in by parse_network(), called by MonCap::parse() | |
91 | entity_addr_t network_parsed; | |
92 | unsigned network_prefix = 0; | |
93 | bool network_valid = true; | |
94 | ||
95 | void parse_network(); | |
96 | ||
7c673cae FG |
97 | mon_rwxa_t allow; |
98 | ||
99 | // explicit grants that a profile grant expands to; populated as | |
100 | // needed by expand_profile() (via is_match()) and cached here. | |
9f95a23c | 101 | mutable std::list<MonCapGrant> profile_grants; |
7c673cae | 102 | |
92f5a8d4 | 103 | void expand_profile(const EntityName& name) const; |
7c673cae FG |
104 | |
105 | MonCapGrant() : allow(0) {} | |
106 | // cppcheck-suppress noExplicitConstructor | |
107 | MonCapGrant(mon_rwxa_t a) : allow(a) {} | |
9f95a23c TL |
108 | MonCapGrant(std::string s, mon_rwxa_t a) : service(std::move(s)), allow(a) {} |
109 | // cppcheck-suppress noExplicitConstructor | |
110 | MonCapGrant(std::string c) : command(std::move(c)) {} | |
111 | MonCapGrant(std::string c, std::string a, StringConstraint co) : command(std::move(c)) { | |
7c673cae FG |
112 | command_args[a] = co; |
113 | } | |
f67539c2 | 114 | MonCapGrant(mon_rwxa_t a, std::string fsname) : fs_name(fsname), allow(a) {} |
7c673cae FG |
115 | |
116 | /** | |
117 | * check if given request parameters match our constraints | |
118 | * | |
119 | * @param cct context | |
120 | * @param name entity name | |
121 | * @param service service (if any) | |
122 | * @param command command (if any) | |
123 | * @param command_args command args (if any) | |
124 | * @return bits we allow | |
125 | */ | |
126 | mon_rwxa_t get_allowed(CephContext *cct, | |
7c673cae FG |
127 | EntityName name, |
128 | const std::string& service, | |
129 | const std::string& command, | |
9f95a23c | 130 | const std::map<std::string, std::string>& command_args) const; |
7c673cae FG |
131 | |
132 | bool is_allow_all() const { | |
133 | return | |
134 | allow == MON_CAP_ANY && | |
135 | service.length() == 0 && | |
136 | profile.length() == 0 && | |
f67539c2 TL |
137 | command.length() == 0 && |
138 | fs_name.empty(); | |
7c673cae FG |
139 | } |
140 | }; | |
141 | ||
9f95a23c | 142 | std::ostream& operator<<(std::ostream& out, const MonCapGrant& g); |
7c673cae FG |
143 | |
144 | struct MonCap { | |
9f95a23c | 145 | std::string text; |
7c673cae FG |
146 | std::vector<MonCapGrant> grants; |
147 | ||
148 | MonCap() {} | |
11fdf7f2 | 149 | explicit MonCap(const std::vector<MonCapGrant> &g) : grants(g) {} |
7c673cae | 150 | |
9f95a23c | 151 | std::string get_str() const { |
7c673cae FG |
152 | return text; |
153 | } | |
154 | ||
155 | bool is_allow_all() const; | |
156 | void set_allow_all(); | |
9f95a23c | 157 | bool parse(const std::string& str, std::ostream *err=NULL); |
7c673cae FG |
158 | |
159 | /** | |
160 | * check if we are capable of something | |
161 | * | |
162 | * This method actually checks a description of a particular operation against | |
163 | * what the capability has specified. | |
164 | * | |
7c673cae FG |
165 | * @param service service name |
166 | * @param command command id | |
167 | * @param command_args | |
168 | * @param op_may_read whether the operation may need to read | |
169 | * @param op_may_write whether the operation may need to write | |
170 | * @param op_may_exec whether the operation may exec | |
171 | * @return true if the operation is allowed, false otherwise | |
172 | */ | |
173 | bool is_capable(CephContext *cct, | |
7c673cae | 174 | EntityName name, |
9f95a23c TL |
175 | const std::string& service, |
176 | const std::string& command, | |
177 | const std::map<std::string, std::string>& command_args, | |
11fdf7f2 TL |
178 | bool op_may_read, bool op_may_write, bool op_may_exec, |
179 | const entity_addr_t& addr) const; | |
7c673cae | 180 | |
9f95a23c TL |
181 | void encode(ceph::buffer::list& bl) const; |
182 | void decode(ceph::buffer::list::const_iterator& bl); | |
183 | void dump(ceph::Formatter *f) const; | |
184 | static void generate_test_instances(std::list<MonCap*>& ls); | |
f67539c2 | 185 | |
20effc67 TL |
186 | std::vector<std::string> allowed_fs_names() const { |
187 | std::vector<std::string> ret; | |
f67539c2 TL |
188 | for (auto& g : grants) { |
189 | if (not g.fs_name.empty()) { | |
190 | ret.push_back(g.fs_name); | |
191 | } else { | |
192 | return {}; | |
193 | } | |
194 | } | |
195 | return ret; | |
196 | } | |
197 | ||
20effc67 | 198 | bool fs_name_capable(const EntityName& ename, std::string_view fs_name, |
f67539c2 TL |
199 | __u8 mask) { |
200 | for (auto& g : grants) { | |
201 | if (g.is_allow_all()) { | |
202 | return true; | |
203 | } | |
204 | ||
205 | if ((g.fs_name.empty() || g.fs_name == fs_name) && (mask & g.allow)) { | |
206 | return true; | |
207 | } | |
208 | ||
209 | g.expand_profile(ename); | |
210 | for (auto& pg : g.profile_grants) { | |
211 | if ((pg.service == "fs" || pg.service == "mds") && | |
212 | (pg.fs_name.empty() || pg.fs_name == fs_name) && | |
213 | (pg.allow & mask)) { | |
214 | return true; | |
215 | } | |
216 | } | |
217 | } | |
218 | ||
219 | return false; | |
220 | } | |
221 | ||
7c673cae FG |
222 | }; |
223 | WRITE_CLASS_ENCODER(MonCap) | |
224 | ||
9f95a23c | 225 | std::ostream& operator<<(std::ostream& out, const MonCap& cap); |
7c673cae FG |
226 | |
227 | #endif |