]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_keystone.h
bump version to 19.2.0-pve1
[ceph.git] / ceph / src / rgw / rgw_keystone.h
CommitLineData
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
19bool rgw_is_pki_token(const std::string& token);
20void rgw_get_token_id(const std::string& token, std::string& token_id);
21static 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
29namespace rgw {
30namespace keystone {
31
32enum class ApiVersion {
33 VER_2,
34 VER_3
35};
36
37
38class Config {
39protected:
40 Config() = default;
41 virtual ~Config() = default;
42
43public:
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
55class CephCtxConfig : public Config {
56protected:
57 CephCtxConfig() = default;
58 virtual ~CephCtxConfig() = default;
59
11fdf7f2
TL
60 const static std::string empty;
61
7c673cae
FG
62public:
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
93class TokenEnvelope;
94class TokenCache;
95
96class Service {
97public:
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 122 static int get_admin_token(const DoutPrefixProvider *dpp,
7c673cae
FG
123 TokenCache& token_cache,
124 const Config& config,
f51cf556
TL
125 optional_yield y,
126 std::string& token,
127 bool& token_cached);
20effc67 128 static int issue_admin_token_request(const DoutPrefixProvider *dpp,
7c673cae 129 const Config& config,
f51cf556 130 optional_yield y,
7c673cae 131 TokenEnvelope& token);
20effc67 132 static int get_keystone_barbican_token(const DoutPrefixProvider *dpp,
f51cf556 133 optional_yield y,
7c673cae
FG
134 std::string& token);
135};
136
137
138class TokenEnvelope {
139public:
140 class Domain {
141 public:
20effc67
TL
142 std::string id;
143 std::string name;
7c673cae
FG
144 void decode_json(JSONObj *obj);
145 };
146 class Project {
147 public:
148 Domain domain;
20effc67
TL
149 std::string id;
150 std::string name;
7c673cae
FG
151 void decode_json(JSONObj *obj);
152 };
153
154 class Token {
155 public:
156 Token() : expires(0) { }
20effc67 157 std::string id;
7c673cae
FG
158 time_t expires;
159 Project tenant_v2;
160 void decode_json(JSONObj *obj);
161 };
162
163 class Role {
164 public:
f51cf556
TL
165 Role() : is_admin(false), is_reader(false) { }
166 Role(const Role &r) {
167 id = r.id;
168 name = r.name;
169 is_admin = r.is_admin;
170 is_reader = r.is_reader;
171 }
20effc67
TL
172 std::string id;
173 std::string name;
f51cf556
TL
174 bool is_admin;
175 bool is_reader;
7c673cae
FG
176 void decode_json(JSONObj *obj);
177 };
178
179 class User {
180 public:
20effc67
TL
181 std::string id;
182 std::string name;
7c673cae 183 Domain domain;
20effc67 184 std::list<Role> roles_v2;
7c673cae
FG
185 void decode_json(JSONObj *obj);
186 };
187
188 Token token;
189 Project project;
190 User user;
20effc67 191 std::list<Role> roles;
7c673cae
FG
192
193 void decode_v3(JSONObj* obj);
194 void decode_v2(JSONObj* obj);
195
196public:
197 /* We really need the default ctor because of the internals of TokenCache. */
198 TokenEnvelope() = default;
199
1e59de90 200 void set_expires(time_t expires) { token.expires = expires; }
7c673cae
FG
201 time_t get_expires() const { return token.expires; }
202 const std::string& get_domain_id() const {return project.domain.id;};
203 const std::string& get_domain_name() const {return project.domain.name;};
204 const std::string& get_project_id() const {return project.id;};
205 const std::string& get_project_name() const {return project.name;};
206 const std::string& get_user_id() const {return user.id;};
207 const std::string& get_user_name() const {return user.name;};
20effc67 208 bool has_role(const std::string& r) const;
7c673cae
FG
209 bool expired() const {
210 const uint64_t now = ceph_clock_now().sec();
1e59de90 211 return std::cmp_greater_equal(now, get_expires());
7c673cae 212 }
f51cf556 213 int parse(const DoutPrefixProvider *dpp,
7c673cae
FG
214 const std::string& token_str,
215 ceph::buffer::list& bl /* in */,
216 ApiVersion version);
f51cf556
TL
217 void update_roles(const std::vector<std::string> & admin,
218 const std::vector<std::string> & reader);
7c673cae
FG
219};
220
221
222class TokenCache {
223 struct token_entry {
224 TokenEnvelope token;
20effc67 225 std::list<std::string>::iterator lru_iter;
7c673cae
FG
226 };
227
228 std::atomic<bool> down_flag = { false };
c07f9fc5 229 const boost::intrusive_ptr<CephContext> cct;
7c673cae
FG
230
231 std::string admin_token_id;
232 std::string barbican_token_id;
233 std::map<std::string, token_entry> tokens;
1e59de90 234 std::map<std::string, token_entry> service_tokens;
7c673cae 235 std::list<std::string> tokens_lru;
1e59de90 236 std::list<std::string> service_tokens_lru;
7c673cae 237
9f95a23c 238 ceph::mutex lock = ceph::make_mutex("rgw::keystone::TokenCache");
7c673cae
FG
239
240 const size_t max;
241
11fdf7f2 242 explicit TokenCache(const rgw::keystone::Config& config)
9f95a23c 243 : cct(g_ceph_context),
7c673cae 244 max(cct->_conf->rgw_keystone_token_cache_size) {
7c673cae
FG
245 }
246
247 ~TokenCache() {
248 down_flag = true;
7c673cae
FG
249 }
250
251public:
252 TokenCache(const TokenCache&) = delete;
253 void operator=(const TokenCache&) = delete;
254
255 template<class ConfigT>
256 static TokenCache& get_instance() {
257 static_assert(std::is_base_of<rgw::keystone::Config, ConfigT>::value,
258 "ConfigT must be a subclass of rgw::keystone::Config");
259
260 /* In C++11 this is thread safe. */
261 static TokenCache instance(ConfigT::get_instance());
262 return instance;
263 }
264
265 bool find(const std::string& token_id, TokenEnvelope& token);
1e59de90 266 bool find_service(const std::string& token_id, TokenEnvelope& token);
7c673cae
FG
267 boost::optional<TokenEnvelope> find(const std::string& token_id) {
268 TokenEnvelope token_envlp;
269 if (find(token_id, token_envlp)) {
270 return token_envlp;
271 }
272 return boost::none;
273 }
1e59de90
TL
274 boost::optional<TokenEnvelope> find_service(const std::string& token_id) {
275 TokenEnvelope token_envlp;
276 if (find_service(token_id, token_envlp)) {
277 return token_envlp;
278 }
279 return boost::none;
280 }
7c673cae
FG
281 bool find_admin(TokenEnvelope& token);
282 bool find_barbican(TokenEnvelope& token);
283 void add(const std::string& token_id, const TokenEnvelope& token);
1e59de90 284 void add_service(const std::string& token_id, const TokenEnvelope& token);
7c673cae
FG
285 void add_admin(const TokenEnvelope& token);
286 void add_barbican(const TokenEnvelope& token);
20effc67 287 void invalidate(const DoutPrefixProvider *dpp, const std::string& token_id);
f51cf556 288 void invalidate_admin(const DoutPrefixProvider *dpp);
7c673cae
FG
289 bool going_down() const;
290private:
1e59de90
TL
291 void add_locked(const std::string& token_id, const TokenEnvelope& token,
292 std::map<std::string, token_entry>& tokens, std::list<std::string>& tokens_lru);
293 bool find_locked(const std::string& token_id, TokenEnvelope& token,
294 std::map<std::string, token_entry>& tokens, std::list<std::string>& tokens_lru);
7c673cae
FG
295};
296
297
298class AdminTokenRequest {
299public:
300 virtual ~AdminTokenRequest() = default;
301 virtual void dump(Formatter* f) const = 0;
302};
303
304class AdminTokenRequestVer2 : public AdminTokenRequest {
305 const Config& conf;
306
307public:
11fdf7f2 308 explicit AdminTokenRequestVer2(const Config& conf)
7c673cae
FG
309 : conf(conf) {
310 }
311 void dump(Formatter *f) const override;
312};
313
314class AdminTokenRequestVer3 : public AdminTokenRequest {
315 const Config& conf;
316
317public:
11fdf7f2 318 explicit AdminTokenRequestVer3(const Config& conf)
7c673cae
FG
319 : conf(conf) {
320 }
321 void dump(Formatter *f) const override;
322};
323
324class BarbicanTokenRequestVer2 : public AdminTokenRequest {
325 CephContext *cct;
326
327public:
11fdf7f2 328 explicit BarbicanTokenRequestVer2(CephContext * const _cct)
7c673cae
FG
329 : cct(_cct) {
330 }
11fdf7f2 331 void dump(Formatter *f) const override;
7c673cae
FG
332};
333
334class BarbicanTokenRequestVer3 : public AdminTokenRequest {
335 CephContext *cct;
336
337public:
11fdf7f2 338 explicit BarbicanTokenRequestVer3(CephContext * const _cct)
7c673cae
FG
339 : cct(_cct) {
340 }
11fdf7f2 341 void dump(Formatter *f) const override;
7c673cae
FG
342};
343
344
345}; /* namespace keystone */
346}; /* namespace rgw */