]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_keystone.h
update source to Ceph Pacific 16.2.2
[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
FG
3
4#ifndef CEPH_RGW_KEYSTONE_H
5#define CEPH_RGW_KEYSTONE_H
6
7#include <type_traits>
f67539c2 8#include <string_view>
7c673cae
FG
9
10#include <boost/optional.hpp>
7c673cae
FG
11
12#include "rgw_common.h"
13#include "rgw_http_client.h"
9f95a23c 14#include "common/ceph_mutex.h"
c07f9fc5 15#include "global/global_init.h"
7c673cae
FG
16
17#include <atomic>
18
7c673cae
FG
19bool rgw_is_pki_token(const string& token);
20void rgw_get_token_id(const string& token, string& token_id);
21static inline std::string rgw_get_token_id(const string& token)
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,
11fdf7f2
TL
101 const string& method,
102 const 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
FG
121
122 static int get_admin_token(CephContext* const cct,
123 TokenCache& token_cache,
124 const Config& config,
125 std::string& token);
126 static int issue_admin_token_request(CephContext* const cct,
127 const Config& config,
128 TokenEnvelope& token);
129 static int get_keystone_barbican_token(CephContext * const cct,
130 std::string& token);
131};
132
133
134class TokenEnvelope {
135public:
136 class Domain {
137 public:
138 string id;
139 string name;
140 void decode_json(JSONObj *obj);
141 };
142 class Project {
143 public:
144 Domain domain;
145 string id;
146 string name;
147 void decode_json(JSONObj *obj);
148 };
149
150 class Token {
151 public:
152 Token() : expires(0) { }
153 string id;
154 time_t expires;
155 Project tenant_v2;
156 void decode_json(JSONObj *obj);
157 };
158
159 class Role {
160 public:
161 string id;
162 string name;
163 void decode_json(JSONObj *obj);
164 };
165
166 class User {
167 public:
168 string id;
169 string name;
170 Domain domain;
171 list<Role> roles_v2;
172 void decode_json(JSONObj *obj);
173 };
174
175 Token token;
176 Project project;
177 User user;
178 list<Role> roles;
179
180 void decode_v3(JSONObj* obj);
181 void decode_v2(JSONObj* obj);
182
183public:
184 /* We really need the default ctor because of the internals of TokenCache. */
185 TokenEnvelope() = default;
186
187 time_t get_expires() const { return token.expires; }
188 const std::string& get_domain_id() const {return project.domain.id;};
189 const std::string& get_domain_name() const {return project.domain.name;};
190 const std::string& get_project_id() const {return project.id;};
191 const std::string& get_project_name() const {return project.name;};
192 const std::string& get_user_id() const {return user.id;};
193 const std::string& get_user_name() const {return user.name;};
194 bool has_role(const string& r) const;
195 bool expired() const {
196 const uint64_t now = ceph_clock_now().sec();
197 return now >= static_cast<uint64_t>(get_expires());
198 }
199 int parse(CephContext* cct,
200 const std::string& token_str,
201 ceph::buffer::list& bl /* in */,
202 ApiVersion version);
203};
204
205
206class TokenCache {
207 struct token_entry {
208 TokenEnvelope token;
209 list<string>::iterator lru_iter;
210 };
211
212 std::atomic<bool> down_flag = { false };
c07f9fc5 213 const boost::intrusive_ptr<CephContext> cct;
7c673cae
FG
214
215 std::string admin_token_id;
216 std::string barbican_token_id;
217 std::map<std::string, token_entry> tokens;
218 std::list<std::string> tokens_lru;
219
9f95a23c 220 ceph::mutex lock = ceph::make_mutex("rgw::keystone::TokenCache");
7c673cae
FG
221
222 const size_t max;
223
11fdf7f2 224 explicit TokenCache(const rgw::keystone::Config& config)
9f95a23c 225 : cct(g_ceph_context),
7c673cae 226 max(cct->_conf->rgw_keystone_token_cache_size) {
7c673cae
FG
227 }
228
229 ~TokenCache() {
230 down_flag = true;
7c673cae
FG
231 }
232
233public:
234 TokenCache(const TokenCache&) = delete;
235 void operator=(const TokenCache&) = delete;
236
237 template<class ConfigT>
238 static TokenCache& get_instance() {
239 static_assert(std::is_base_of<rgw::keystone::Config, ConfigT>::value,
240 "ConfigT must be a subclass of rgw::keystone::Config");
241
242 /* In C++11 this is thread safe. */
243 static TokenCache instance(ConfigT::get_instance());
244 return instance;
245 }
246
247 bool find(const std::string& token_id, TokenEnvelope& token);
248 boost::optional<TokenEnvelope> find(const std::string& token_id) {
249 TokenEnvelope token_envlp;
250 if (find(token_id, token_envlp)) {
251 return token_envlp;
252 }
253 return boost::none;
254 }
255 bool find_admin(TokenEnvelope& token);
256 bool find_barbican(TokenEnvelope& token);
257 void add(const std::string& token_id, const TokenEnvelope& token);
258 void add_admin(const TokenEnvelope& token);
259 void add_barbican(const TokenEnvelope& token);
260 void invalidate(const std::string& token_id);
261 bool going_down() const;
262private:
263 void add_locked(const std::string& token_id, const TokenEnvelope& token);
264 bool find_locked(const std::string& token_id, TokenEnvelope& token);
265
266};
267
268
269class AdminTokenRequest {
270public:
271 virtual ~AdminTokenRequest() = default;
272 virtual void dump(Formatter* f) const = 0;
273};
274
275class AdminTokenRequestVer2 : public AdminTokenRequest {
276 const Config& conf;
277
278public:
11fdf7f2 279 explicit AdminTokenRequestVer2(const Config& conf)
7c673cae
FG
280 : conf(conf) {
281 }
282 void dump(Formatter *f) const override;
283};
284
285class AdminTokenRequestVer3 : public AdminTokenRequest {
286 const Config& conf;
287
288public:
11fdf7f2 289 explicit AdminTokenRequestVer3(const Config& conf)
7c673cae
FG
290 : conf(conf) {
291 }
292 void dump(Formatter *f) const override;
293};
294
295class BarbicanTokenRequestVer2 : public AdminTokenRequest {
296 CephContext *cct;
297
298public:
11fdf7f2 299 explicit BarbicanTokenRequestVer2(CephContext * const _cct)
7c673cae
FG
300 : cct(_cct) {
301 }
11fdf7f2 302 void dump(Formatter *f) const override;
7c673cae
FG
303};
304
305class BarbicanTokenRequestVer3 : public AdminTokenRequest {
306 CephContext *cct;
307
308public:
11fdf7f2 309 explicit BarbicanTokenRequestVer3(CephContext * const _cct)
7c673cae
FG
310 : cct(_cct) {
311 }
11fdf7f2 312 void dump(Formatter *f) const override;
7c673cae
FG
313};
314
315
316}; /* namespace keystone */
317}; /* namespace rgw */
318
319#endif