1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #ifndef CEPH_RGW_KEYSTONE_H
5 #define CEPH_RGW_KEYSTONE_H
9 #include <boost/optional.hpp>
10 #include <boost/utility/string_ref.hpp>
12 #include "rgw_common.h"
13 #include "rgw_http_client.h"
14 #include "common/Cond.h"
15 #include "global/global_init.h"
19 int rgw_open_cms_envelope(CephContext
*cct
,
20 const std::string
& src
,
21 std::string
& dst
); /* out */
22 int rgw_decode_b64_cms(CephContext
*cct
,
23 const string
& signed_b64
,
25 bool rgw_is_pki_token(const string
& token
);
26 void rgw_get_token_id(const string
& token
, string
& token_id
);
27 static inline std::string
rgw_get_token_id(const string
& token
)
30 rgw_get_token_id(token
, token_id
);
34 bool rgw_decode_pki_token(CephContext
*cct
,
41 enum class ApiVersion
{
50 virtual ~Config() = default;
53 virtual std::string
get_endpoint_url() const noexcept
= 0;
54 virtual ApiVersion
get_api_version() const noexcept
= 0;
56 virtual boost::string_ref
get_admin_token() const noexcept
= 0;
57 virtual boost::string_ref
get_admin_user() const noexcept
= 0;
58 virtual boost::string_ref
get_admin_password() const noexcept
= 0;
59 virtual boost::string_ref
get_admin_tenant() const noexcept
= 0;
60 virtual boost::string_ref
get_admin_project() const noexcept
= 0;
61 virtual boost::string_ref
get_admin_domain() const noexcept
= 0;
64 class CephCtxConfig
: public Config
{
66 CephCtxConfig() = default;
67 virtual ~CephCtxConfig() = default;
70 static CephCtxConfig
& get_instance() {
71 static CephCtxConfig instance
;
75 std::string
get_endpoint_url() const noexcept override
;
76 ApiVersion
get_api_version() const noexcept override
;
78 boost::string_ref
get_admin_token() const noexcept override
{
79 return g_ceph_context
->_conf
->rgw_keystone_admin_token
;
82 boost::string_ref
get_admin_user() const noexcept override
{
83 return g_ceph_context
->_conf
->rgw_keystone_admin_user
;
86 boost::string_ref
get_admin_password() const noexcept override
{
87 return g_ceph_context
->_conf
->rgw_keystone_admin_password
;
90 boost::string_ref
get_admin_tenant() const noexcept override
{
91 return g_ceph_context
->_conf
->rgw_keystone_admin_tenant
;
94 boost::string_ref
get_admin_project() const noexcept override
{
95 return g_ceph_context
->_conf
->rgw_keystone_admin_project
;
98 boost::string_ref
get_admin_domain() const noexcept override
{
99 return g_ceph_context
->_conf
->rgw_keystone_admin_domain
;
109 class RGWKeystoneHTTPTransceiver
: public RGWHTTPTransceiver
{
111 RGWKeystoneHTTPTransceiver(CephContext
* const cct
,
112 bufferlist
* const token_body_bl
)
113 : RGWHTTPTransceiver(cct
, token_body_bl
,
114 cct
->_conf
->rgw_keystone_verify_ssl
,
115 { "X-Subject-Token" }) {
118 const header_value_t
& get_subject_token() const {
120 return get_header_value("X-Subject-Token");
121 } catch (std::out_of_range
&) {
122 static header_value_t empty_val
;
128 typedef RGWKeystoneHTTPTransceiver RGWValidateKeystoneToken
;
129 typedef RGWKeystoneHTTPTransceiver RGWGetKeystoneAdminToken
;
130 typedef RGWKeystoneHTTPTransceiver RGWGetRevokedTokens
;
132 static int get_admin_token(CephContext
* const cct
,
133 TokenCache
& token_cache
,
134 const Config
& config
,
136 static int issue_admin_token_request(CephContext
* const cct
,
137 const Config
& config
,
138 TokenEnvelope
& token
);
139 static int get_keystone_barbican_token(CephContext
* const cct
,
144 class TokenEnvelope
{
150 void decode_json(JSONObj
*obj
);
157 void decode_json(JSONObj
*obj
);
162 Token() : expires(0) { }
166 void decode_json(JSONObj
*obj
);
173 void decode_json(JSONObj
*obj
);
182 void decode_json(JSONObj
*obj
);
190 void decode_v3(JSONObj
* obj
);
191 void decode_v2(JSONObj
* obj
);
194 /* We really need the default ctor because of the internals of TokenCache. */
195 TokenEnvelope() = default;
197 time_t get_expires() const { return token
.expires
; }
198 const std::string
& get_domain_id() const {return project
.domain
.id
;};
199 const std::string
& get_domain_name() const {return project
.domain
.name
;};
200 const std::string
& get_project_id() const {return project
.id
;};
201 const std::string
& get_project_name() const {return project
.name
;};
202 const std::string
& get_user_id() const {return user
.id
;};
203 const std::string
& get_user_name() const {return user
.name
;};
204 bool has_role(const string
& r
) const;
205 bool expired() const {
206 const uint64_t now
= ceph_clock_now().sec();
207 return now
>= static_cast<uint64_t>(get_expires());
209 int parse(CephContext
* cct
,
210 const std::string
& token_str
,
211 ceph::buffer::list
& bl
/* in */,
219 list
<string
>::iterator lru_iter
;
222 std::atomic
<bool> down_flag
= { false };
224 class RevokeThread
: public Thread
{
225 friend class TokenCache
;
226 typedef RGWPostHTTPData RGWGetRevokedTokens
;
228 CephContext
* const cct
;
229 TokenCache
* const cache
;
230 const rgw::keystone::Config
& config
;
235 RevokeThread(CephContext
* const cct
,
236 TokenCache
* const cache
,
237 const rgw::keystone::Config
& config
)
241 lock("rgw::keystone::TokenCache::RevokeThread") {
244 void *entry() override
;
249 const boost::intrusive_ptr
<CephContext
> cct
;
251 std::string admin_token_id
;
252 std::string barbican_token_id
;
253 std::map
<std::string
, token_entry
> tokens
;
254 std::list
<std::string
> tokens_lru
;
260 TokenCache(const rgw::keystone::Config
& config
)
261 : revocator(g_ceph_context
, this, config
),
263 lock("rgw::keystone::TokenCache"),
264 max(cct
->_conf
->rgw_keystone_token_cache_size
) {
265 /* revocation logic needs to be smarter, but meanwhile,
267 * see http://tracker.ceph.com/issues/9493
268 * http://tracker.ceph.com/issues/19499
270 if (cct
->_conf
->rgw_keystone_revocation_interval
> 0
271 && cct
->_conf
->rgw_keystone_token_cache_size
) {
272 /* The thread name has been kept for backward compliance. */
273 revocator
.create("rgw_swift_k_rev");
285 TokenCache(const TokenCache
&) = delete;
286 void operator=(const TokenCache
&) = delete;
288 template<class ConfigT
>
289 static TokenCache
& get_instance() {
290 static_assert(std::is_base_of
<rgw::keystone::Config
, ConfigT
>::value
,
291 "ConfigT must be a subclass of rgw::keystone::Config");
293 /* In C++11 this is thread safe. */
294 static TokenCache
instance(ConfigT::get_instance());
298 bool find(const std::string
& token_id
, TokenEnvelope
& token
);
299 boost::optional
<TokenEnvelope
> find(const std::string
& token_id
) {
300 TokenEnvelope token_envlp
;
301 if (find(token_id
, token_envlp
)) {
306 bool find_admin(TokenEnvelope
& token
);
307 bool find_barbican(TokenEnvelope
& token
);
308 void add(const std::string
& token_id
, const TokenEnvelope
& token
);
309 void add_admin(const TokenEnvelope
& token
);
310 void add_barbican(const TokenEnvelope
& token
);
311 void invalidate(const std::string
& token_id
);
312 bool going_down() const;
314 void add_locked(const std::string
& token_id
, const TokenEnvelope
& token
);
315 bool find_locked(const std::string
& token_id
, TokenEnvelope
& token
);
320 class AdminTokenRequest
{
322 virtual ~AdminTokenRequest() = default;
323 virtual void dump(Formatter
* f
) const = 0;
326 class AdminTokenRequestVer2
: public AdminTokenRequest
{
330 AdminTokenRequestVer2(const Config
& conf
)
333 void dump(Formatter
*f
) const override
;
336 class AdminTokenRequestVer3
: public AdminTokenRequest
{
340 AdminTokenRequestVer3(const Config
& conf
)
343 void dump(Formatter
*f
) const override
;
346 class BarbicanTokenRequestVer2
: public AdminTokenRequest
{
350 BarbicanTokenRequestVer2(CephContext
* const _cct
)
353 void dump(Formatter
*f
) const;
356 class BarbicanTokenRequestVer3
: public AdminTokenRequest
{
360 BarbicanTokenRequestVer3(CephContext
* const _cct
)
363 void dump(Formatter
*f
) const;
367 }; /* namespace keystone */
368 }; /* namespace rgw */