]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
9f95a23c | 2 | // vim: ts=8 sw=2 smarttab ft=cpp |
7c673cae | 3 | |
1e59de90 | 4 | #pragma once |
7c673cae | 5 | |
1e59de90 | 6 | #include <atomic> |
f67539c2 | 7 | #include <string_view> |
1e59de90 TL |
8 | #include <type_traits> |
9 | #include <utility> | |
7c673cae FG |
10 | |
11 | #include <boost/optional.hpp> | |
7c673cae FG |
12 | |
13 | #include "rgw_common.h" | |
14 | #include "rgw_http_client.h" | |
9f95a23c | 15 | #include "common/ceph_mutex.h" |
c07f9fc5 | 16 | #include "global/global_init.h" |
7c673cae | 17 | |
7c673cae | 18 | |
20effc67 TL |
19 | bool rgw_is_pki_token(const std::string& token); |
20 | void rgw_get_token_id(const std::string& token, std::string& token_id); | |
21 | static inline std::string rgw_get_token_id(const std::string& token) | |
7c673cae FG |
22 | { |
23 | std::string token_id; | |
24 | rgw_get_token_id(token, token_id); | |
25 | ||
26 | return token_id; | |
27 | } | |
7c673cae FG |
28 | |
29 | namespace rgw { | |
30 | namespace keystone { | |
31 | ||
32 | enum class ApiVersion { | |
33 | VER_2, | |
34 | VER_3 | |
35 | }; | |
36 | ||
37 | ||
38 | class Config { | |
39 | protected: | |
40 | Config() = default; | |
41 | virtual ~Config() = default; | |
42 | ||
43 | public: | |
44 | virtual std::string get_endpoint_url() const noexcept = 0; | |
45 | virtual ApiVersion get_api_version() const noexcept = 0; | |
46 | ||
11fdf7f2 | 47 | virtual std::string get_admin_token() const noexcept = 0; |
f67539c2 | 48 | virtual std::string_view get_admin_user() const noexcept = 0; |
11fdf7f2 | 49 | virtual std::string get_admin_password() const noexcept = 0; |
f67539c2 TL |
50 | virtual std::string_view get_admin_tenant() const noexcept = 0; |
51 | virtual std::string_view get_admin_project() const noexcept = 0; | |
52 | virtual std::string_view get_admin_domain() const noexcept = 0; | |
7c673cae FG |
53 | }; |
54 | ||
55 | class CephCtxConfig : public Config { | |
56 | protected: | |
57 | CephCtxConfig() = default; | |
58 | virtual ~CephCtxConfig() = default; | |
59 | ||
11fdf7f2 TL |
60 | const static std::string empty; |
61 | ||
7c673cae FG |
62 | public: |
63 | static CephCtxConfig& get_instance() { | |
64 | static CephCtxConfig instance; | |
65 | return instance; | |
66 | } | |
67 | ||
68 | std::string get_endpoint_url() const noexcept override; | |
69 | ApiVersion get_api_version() const noexcept override; | |
70 | ||
11fdf7f2 | 71 | std::string get_admin_token() const noexcept override; |
7c673cae | 72 | |
f67539c2 | 73 | std::string_view get_admin_user() const noexcept override { |
7c673cae FG |
74 | return g_ceph_context->_conf->rgw_keystone_admin_user; |
75 | } | |
76 | ||
11fdf7f2 | 77 | std::string get_admin_password() const noexcept override; |
7c673cae | 78 | |
f67539c2 | 79 | std::string_view get_admin_tenant() const noexcept override { |
7c673cae FG |
80 | return g_ceph_context->_conf->rgw_keystone_admin_tenant; |
81 | } | |
82 | ||
f67539c2 | 83 | std::string_view get_admin_project() const noexcept override { |
7c673cae FG |
84 | return g_ceph_context->_conf->rgw_keystone_admin_project; |
85 | } | |
86 | ||
f67539c2 | 87 | std::string_view get_admin_domain() const noexcept override { |
7c673cae FG |
88 | return g_ceph_context->_conf->rgw_keystone_admin_domain; |
89 | } | |
90 | }; | |
91 | ||
92 | ||
93 | class TokenEnvelope; | |
94 | class TokenCache; | |
95 | ||
96 | class Service { | |
97 | public: | |
98 | class RGWKeystoneHTTPTransceiver : public RGWHTTPTransceiver { | |
99 | public: | |
100 | RGWKeystoneHTTPTransceiver(CephContext * const cct, | |
20effc67 TL |
101 | const std::string& method, |
102 | const std::string& url, | |
7c673cae | 103 | bufferlist * const token_body_bl) |
11fdf7f2 | 104 | : RGWHTTPTransceiver(cct, method, url, token_body_bl, |
7c673cae FG |
105 | cct->_conf->rgw_keystone_verify_ssl, |
106 | { "X-Subject-Token" }) { | |
107 | } | |
108 | ||
109 | const header_value_t& get_subject_token() const { | |
110 | try { | |
111 | return get_header_value("X-Subject-Token"); | |
112 | } catch (std::out_of_range&) { | |
113 | static header_value_t empty_val; | |
114 | return empty_val; | |
115 | } | |
116 | } | |
117 | }; | |
118 | ||
119 | typedef RGWKeystoneHTTPTransceiver RGWValidateKeystoneToken; | |
120 | typedef RGWKeystoneHTTPTransceiver RGWGetKeystoneAdminToken; | |
7c673cae | 121 | |
20effc67 TL |
122 | static int get_admin_token(const DoutPrefixProvider *dpp, |
123 | CephContext* const cct, | |
7c673cae FG |
124 | TokenCache& token_cache, |
125 | const Config& config, | |
126 | std::string& token); | |
20effc67 TL |
127 | static int issue_admin_token_request(const DoutPrefixProvider *dpp, |
128 | CephContext* const cct, | |
7c673cae FG |
129 | const Config& config, |
130 | TokenEnvelope& token); | |
20effc67 TL |
131 | static int get_keystone_barbican_token(const DoutPrefixProvider *dpp, |
132 | CephContext * const cct, | |
7c673cae FG |
133 | std::string& token); |
134 | }; | |
135 | ||
136 | ||
137 | class TokenEnvelope { | |
138 | public: | |
139 | class Domain { | |
140 | public: | |
20effc67 TL |
141 | std::string id; |
142 | std::string name; | |
7c673cae FG |
143 | void decode_json(JSONObj *obj); |
144 | }; | |
145 | class Project { | |
146 | public: | |
147 | Domain domain; | |
20effc67 TL |
148 | std::string id; |
149 | std::string name; | |
7c673cae FG |
150 | void decode_json(JSONObj *obj); |
151 | }; | |
152 | ||
153 | class Token { | |
154 | public: | |
155 | Token() : expires(0) { } | |
20effc67 | 156 | std::string id; |
7c673cae FG |
157 | time_t expires; |
158 | Project tenant_v2; | |
159 | void decode_json(JSONObj *obj); | |
160 | }; | |
161 | ||
162 | class Role { | |
163 | public: | |
20effc67 TL |
164 | std::string id; |
165 | std::string name; | |
7c673cae FG |
166 | void decode_json(JSONObj *obj); |
167 | }; | |
168 | ||
169 | class User { | |
170 | public: | |
20effc67 TL |
171 | std::string id; |
172 | std::string name; | |
7c673cae | 173 | Domain domain; |
20effc67 | 174 | std::list<Role> roles_v2; |
7c673cae FG |
175 | void decode_json(JSONObj *obj); |
176 | }; | |
177 | ||
178 | Token token; | |
179 | Project project; | |
180 | User user; | |
20effc67 | 181 | std::list<Role> roles; |
7c673cae FG |
182 | |
183 | void decode_v3(JSONObj* obj); | |
184 | void decode_v2(JSONObj* obj); | |
185 | ||
186 | public: | |
187 | /* We really need the default ctor because of the internals of TokenCache. */ | |
188 | TokenEnvelope() = default; | |
189 | ||
1e59de90 | 190 | void set_expires(time_t expires) { token.expires = expires; } |
7c673cae FG |
191 | time_t get_expires() const { return token.expires; } |
192 | const std::string& get_domain_id() const {return project.domain.id;}; | |
193 | const std::string& get_domain_name() const {return project.domain.name;}; | |
194 | const std::string& get_project_id() const {return project.id;}; | |
195 | const std::string& get_project_name() const {return project.name;}; | |
196 | const std::string& get_user_id() const {return user.id;}; | |
197 | const std::string& get_user_name() const {return user.name;}; | |
20effc67 | 198 | bool has_role(const std::string& r) const; |
7c673cae FG |
199 | bool expired() const { |
200 | const uint64_t now = ceph_clock_now().sec(); | |
1e59de90 | 201 | return std::cmp_greater_equal(now, get_expires()); |
7c673cae | 202 | } |
20effc67 | 203 | int parse(const DoutPrefixProvider *dpp, CephContext* cct, |
7c673cae FG |
204 | const std::string& token_str, |
205 | ceph::buffer::list& bl /* in */, | |
206 | ApiVersion version); | |
207 | }; | |
208 | ||
209 | ||
210 | class TokenCache { | |
211 | struct token_entry { | |
212 | TokenEnvelope token; | |
20effc67 | 213 | std::list<std::string>::iterator lru_iter; |
7c673cae FG |
214 | }; |
215 | ||
216 | std::atomic<bool> down_flag = { false }; | |
c07f9fc5 | 217 | const boost::intrusive_ptr<CephContext> cct; |
7c673cae FG |
218 | |
219 | std::string admin_token_id; | |
220 | std::string barbican_token_id; | |
221 | std::map<std::string, token_entry> tokens; | |
1e59de90 | 222 | std::map<std::string, token_entry> service_tokens; |
7c673cae | 223 | std::list<std::string> tokens_lru; |
1e59de90 | 224 | std::list<std::string> service_tokens_lru; |
7c673cae | 225 | |
9f95a23c | 226 | ceph::mutex lock = ceph::make_mutex("rgw::keystone::TokenCache"); |
7c673cae FG |
227 | |
228 | const size_t max; | |
229 | ||
11fdf7f2 | 230 | explicit TokenCache(const rgw::keystone::Config& config) |
9f95a23c | 231 | : cct(g_ceph_context), |
7c673cae | 232 | max(cct->_conf->rgw_keystone_token_cache_size) { |
7c673cae FG |
233 | } |
234 | ||
235 | ~TokenCache() { | |
236 | down_flag = true; | |
7c673cae FG |
237 | } |
238 | ||
239 | public: | |
240 | TokenCache(const TokenCache&) = delete; | |
241 | void operator=(const TokenCache&) = delete; | |
242 | ||
243 | template<class ConfigT> | |
244 | static TokenCache& get_instance() { | |
245 | static_assert(std::is_base_of<rgw::keystone::Config, ConfigT>::value, | |
246 | "ConfigT must be a subclass of rgw::keystone::Config"); | |
247 | ||
248 | /* In C++11 this is thread safe. */ | |
249 | static TokenCache instance(ConfigT::get_instance()); | |
250 | return instance; | |
251 | } | |
252 | ||
253 | bool find(const std::string& token_id, TokenEnvelope& token); | |
1e59de90 | 254 | bool find_service(const std::string& token_id, TokenEnvelope& token); |
7c673cae FG |
255 | boost::optional<TokenEnvelope> find(const std::string& token_id) { |
256 | TokenEnvelope token_envlp; | |
257 | if (find(token_id, token_envlp)) { | |
258 | return token_envlp; | |
259 | } | |
260 | return boost::none; | |
261 | } | |
1e59de90 TL |
262 | boost::optional<TokenEnvelope> find_service(const std::string& token_id) { |
263 | TokenEnvelope token_envlp; | |
264 | if (find_service(token_id, token_envlp)) { | |
265 | return token_envlp; | |
266 | } | |
267 | return boost::none; | |
268 | } | |
7c673cae FG |
269 | bool find_admin(TokenEnvelope& token); |
270 | bool find_barbican(TokenEnvelope& token); | |
271 | void add(const std::string& token_id, const TokenEnvelope& token); | |
1e59de90 | 272 | void add_service(const std::string& token_id, const TokenEnvelope& token); |
7c673cae FG |
273 | void add_admin(const TokenEnvelope& token); |
274 | void add_barbican(const TokenEnvelope& token); | |
20effc67 | 275 | void invalidate(const DoutPrefixProvider *dpp, const std::string& token_id); |
7c673cae FG |
276 | bool going_down() const; |
277 | private: | |
1e59de90 TL |
278 | void add_locked(const std::string& token_id, const TokenEnvelope& token, |
279 | std::map<std::string, token_entry>& tokens, std::list<std::string>& tokens_lru); | |
280 | bool find_locked(const std::string& token_id, TokenEnvelope& token, | |
281 | std::map<std::string, token_entry>& tokens, std::list<std::string>& tokens_lru); | |
7c673cae FG |
282 | }; |
283 | ||
284 | ||
285 | class AdminTokenRequest { | |
286 | public: | |
287 | virtual ~AdminTokenRequest() = default; | |
288 | virtual void dump(Formatter* f) const = 0; | |
289 | }; | |
290 | ||
291 | class AdminTokenRequestVer2 : public AdminTokenRequest { | |
292 | const Config& conf; | |
293 | ||
294 | public: | |
11fdf7f2 | 295 | explicit AdminTokenRequestVer2(const Config& conf) |
7c673cae FG |
296 | : conf(conf) { |
297 | } | |
298 | void dump(Formatter *f) const override; | |
299 | }; | |
300 | ||
301 | class AdminTokenRequestVer3 : public AdminTokenRequest { | |
302 | const Config& conf; | |
303 | ||
304 | public: | |
11fdf7f2 | 305 | explicit AdminTokenRequestVer3(const Config& conf) |
7c673cae FG |
306 | : conf(conf) { |
307 | } | |
308 | void dump(Formatter *f) const override; | |
309 | }; | |
310 | ||
311 | class BarbicanTokenRequestVer2 : public AdminTokenRequest { | |
312 | CephContext *cct; | |
313 | ||
314 | public: | |
11fdf7f2 | 315 | explicit BarbicanTokenRequestVer2(CephContext * const _cct) |
7c673cae FG |
316 | : cct(_cct) { |
317 | } | |
11fdf7f2 | 318 | void dump(Formatter *f) const override; |
7c673cae FG |
319 | }; |
320 | ||
321 | class BarbicanTokenRequestVer3 : public AdminTokenRequest { | |
322 | CephContext *cct; | |
323 | ||
324 | public: | |
11fdf7f2 | 325 | explicit BarbicanTokenRequestVer3(CephContext * const _cct) |
7c673cae FG |
326 | : cct(_cct) { |
327 | } | |
11fdf7f2 | 328 | void dump(Formatter *f) const override; |
7c673cae FG |
329 | }; |
330 | ||
331 | ||
332 | }; /* namespace keystone */ | |
333 | }; /* namespace rgw */ |