]>
Commit | Line | Data |
---|---|---|
92f5a8d4 TL |
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_MGRCAP_H | |
5 | #define CEPH_MGRCAP_H | |
6 | ||
9f95a23c | 7 | #include <iosfwd> |
92f5a8d4 | 8 | |
9f95a23c | 9 | #include "include/common_fwd.h" |
92f5a8d4 TL |
10 | #include "include/types.h" |
11 | #include "common/entity_name.h" | |
12 | ||
92f5a8d4 TL |
13 | static const __u8 MGR_CAP_R = (1 << 1); // read |
14 | static const __u8 MGR_CAP_W = (1 << 2); // write | |
15 | static const __u8 MGR_CAP_X = (1 << 3); // execute | |
16 | static const __u8 MGR_CAP_ANY = 0xff; // * | |
17 | ||
18 | struct mgr_rwxa_t { | |
19 | __u8 val = 0U; | |
20 | ||
21 | mgr_rwxa_t() {} | |
22 | explicit mgr_rwxa_t(__u8 v) : val(v) {} | |
23 | ||
24 | mgr_rwxa_t& operator=(__u8 v) { | |
25 | val = v; | |
26 | return *this; | |
27 | } | |
28 | operator __u8() const { | |
29 | return val; | |
30 | } | |
31 | }; | |
32 | ||
33 | std::ostream& operator<<(std::ostream& out, const mgr_rwxa_t& p); | |
34 | ||
35 | struct MgrCapGrantConstraint { | |
36 | enum MatchType { | |
37 | MATCH_TYPE_NONE, | |
38 | MATCH_TYPE_EQUAL, | |
39 | MATCH_TYPE_PREFIX, | |
40 | MATCH_TYPE_REGEX | |
41 | }; | |
42 | ||
43 | MatchType match_type = MATCH_TYPE_NONE; | |
44 | std::string value; | |
45 | ||
46 | MgrCapGrantConstraint() {} | |
47 | MgrCapGrantConstraint(MatchType match_type, std::string value) | |
48 | : match_type(match_type), value(value) { | |
49 | } | |
50 | }; | |
51 | ||
52 | std::ostream& operator<<(std::ostream& out, const MgrCapGrantConstraint& c); | |
53 | ||
54 | struct MgrCapGrant { | |
55 | /* | |
56 | * A grant can come in one of four forms: | |
57 | * | |
58 | * - a blanket allow ('allow rw', 'allow *') | |
59 | * - this will match against any service and the read/write/exec flags | |
60 | * in the mgr code. semantics of what X means are somewhat ad hoc. | |
61 | * | |
62 | * - a service allow ('allow service mds rw') | |
63 | * - this will match against a specific service and the r/w/x flags. | |
64 | * | |
65 | * - a module allow ('allow module rbd_support rw, allow module rbd_support with pool=rbd rw') | |
66 | * - this will match against a specific python add-on module and the r/w/x | |
67 | * flags. | |
68 | * | |
69 | * - a profile ('profile read-only, profile rbd pool=rbd') | |
70 | * - this will match against specific MGR-enforced semantics of what | |
71 | * this type of user should need to do. examples include 'read-write', | |
72 | * 'read-only', 'crash'. | |
73 | * | |
74 | * - a command ('allow command foo', 'allow command bar with arg1=val1 arg2 prefix val2') | |
75 | * this includes the command name (the prefix string) | |
76 | * | |
77 | * The command, module, and profile caps can also accept an optional | |
78 | * key/value map. If not provided, all command arguments and module | |
79 | * meta-arguments are allowed. If a key/value pair is specified, that | |
80 | * argument must be present and must match the provided constraint. | |
81 | */ | |
82 | typedef std::map<std::string, MgrCapGrantConstraint> Arguments; | |
83 | ||
84 | std::string service; | |
85 | std::string module; | |
86 | std::string profile; | |
87 | std::string command; | |
88 | Arguments arguments; | |
89 | ||
90 | // restrict by network | |
91 | std::string network; | |
92 | ||
93 | // these are filled in by parse_network(), called by MgrCap::parse() | |
94 | entity_addr_t network_parsed; | |
95 | unsigned network_prefix = 0; | |
96 | bool network_valid = true; | |
97 | ||
98 | void parse_network(); | |
99 | ||
100 | mgr_rwxa_t allow; | |
101 | ||
102 | // explicit grants that a profile grant expands to; populated as | |
103 | // needed by expand_profile() (via is_match()) and cached here. | |
104 | mutable std::list<MgrCapGrant> profile_grants; | |
105 | ||
106 | void expand_profile(std::ostream *err=nullptr) const; | |
107 | ||
108 | MgrCapGrant() : allow(0) {} | |
109 | MgrCapGrant(std::string&& service, | |
110 | std::string&& module, | |
111 | std::string&& profile, | |
112 | std::string&& command, | |
113 | Arguments&& arguments, | |
114 | mgr_rwxa_t allow) | |
115 | : service(std::move(service)), module(std::move(module)), | |
116 | profile(std::move(profile)), command(std::move(command)), | |
117 | arguments(std::move(arguments)), allow(allow) { | |
118 | } | |
119 | ||
120 | bool validate_arguments( | |
121 | const std::map<std::string, std::string>& arguments) const; | |
122 | ||
123 | /** | |
124 | * check if given request parameters match our constraints | |
125 | * | |
126 | * @param cct context | |
127 | * @param name entity name | |
128 | * @param service service (if any) | |
129 | * @param module module (if any) | |
130 | * @param command command (if any) | |
131 | * @param arguments profile/module/command args (if any) | |
132 | * @return bits we allow | |
133 | */ | |
134 | mgr_rwxa_t get_allowed( | |
135 | CephContext *cct, | |
136 | EntityName name, | |
137 | const std::string& service, | |
138 | const std::string& module, | |
139 | const std::string& command, | |
140 | const std::map<std::string, std::string>& arguments) const; | |
141 | ||
142 | bool is_allow_all() const { | |
143 | return (allow == MGR_CAP_ANY && | |
144 | service.empty() && | |
145 | module.empty() && | |
146 | profile.empty() && | |
147 | command.empty()); | |
148 | } | |
149 | }; | |
150 | ||
151 | std::ostream& operator<<(std::ostream& out, const MgrCapGrant& g); | |
152 | ||
153 | struct MgrCap { | |
154 | std::string text; | |
155 | std::vector<MgrCapGrant> grants; | |
156 | ||
157 | MgrCap() {} | |
158 | explicit MgrCap(const std::vector<MgrCapGrant> &g) : grants(g) {} | |
159 | ||
160 | std::string get_str() const { | |
161 | return text; | |
162 | } | |
163 | ||
164 | bool is_allow_all() const; | |
165 | void set_allow_all(); | |
166 | bool parse(const std::string& str, std::ostream *err=NULL); | |
167 | ||
168 | /** | |
169 | * check if we are capable of something | |
170 | * | |
171 | * This method actually checks a description of a particular operation against | |
172 | * what the capability has specified. | |
173 | * | |
174 | * @param service service name | |
175 | * @param module module name | |
176 | * @param command command id | |
177 | * @param arguments | |
178 | * @param op_may_read whether the operation may need to read | |
179 | * @param op_may_write whether the operation may need to write | |
180 | * @param op_may_exec whether the operation may exec | |
181 | * @return true if the operation is allowed, false otherwise | |
182 | */ | |
183 | bool is_capable(CephContext *cct, | |
184 | EntityName name, | |
185 | const std::string& service, | |
186 | const std::string& module, | |
187 | const std::string& command, | |
188 | const std::map<std::string, std::string>& arguments, | |
189 | bool op_may_read, bool op_may_write, bool op_may_exec, | |
190 | const entity_addr_t& addr) const; | |
191 | ||
192 | void encode(ceph::buffer::list& bl) const; | |
193 | void decode(ceph::buffer::list::const_iterator& bl); | |
194 | void dump(ceph::Formatter *f) const; | |
195 | static void generate_test_instances(std::list<MgrCap*>& ls); | |
196 | }; | |
197 | WRITE_CLASS_ENCODER(MgrCap) | |
198 | ||
199 | std::ostream& operator<<(std::ostream& out, const MgrCap& cap); | |
200 | ||
201 | #endif // CEPH_MGRCAP_H |