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"
18 int rgw_open_cms_envelope(CephContext
*cct
,
19 const std::string
& src
,
20 std::string
& dst
); /* out */
21 int rgw_decode_b64_cms(CephContext
*cct
,
22 const string
& signed_b64
,
24 bool rgw_is_pki_token(const string
& token
);
25 void rgw_get_token_id(const string
& token
, string
& token_id
);
26 static inline std::string
rgw_get_token_id(const string
& token
)
29 rgw_get_token_id(token
, token_id
);
33 bool rgw_decode_pki_token(CephContext
*cct
,
40 enum class ApiVersion
{
49 virtual ~Config() = default;
52 virtual std::string
get_endpoint_url() const noexcept
= 0;
53 virtual ApiVersion
get_api_version() const noexcept
= 0;
55 virtual boost::string_ref
get_admin_token() const noexcept
= 0;
56 virtual boost::string_ref
get_admin_user() const noexcept
= 0;
57 virtual boost::string_ref
get_admin_password() const noexcept
= 0;
58 virtual boost::string_ref
get_admin_tenant() const noexcept
= 0;
59 virtual boost::string_ref
get_admin_project() const noexcept
= 0;
60 virtual boost::string_ref
get_admin_domain() const noexcept
= 0;
63 class CephCtxConfig
: public Config
{
65 CephCtxConfig() = default;
66 virtual ~CephCtxConfig() = default;
69 static CephCtxConfig
& get_instance() {
70 static CephCtxConfig instance
;
74 std::string
get_endpoint_url() const noexcept override
;
75 ApiVersion
get_api_version() const noexcept override
;
77 boost::string_ref
get_admin_token() const noexcept override
{
78 return g_ceph_context
->_conf
->rgw_keystone_admin_token
;
81 boost::string_ref
get_admin_user() const noexcept override
{
82 return g_ceph_context
->_conf
->rgw_keystone_admin_user
;
85 boost::string_ref
get_admin_password() const noexcept override
{
86 return g_ceph_context
->_conf
->rgw_keystone_admin_password
;
89 boost::string_ref
get_admin_tenant() const noexcept override
{
90 return g_ceph_context
->_conf
->rgw_keystone_admin_tenant
;
93 boost::string_ref
get_admin_project() const noexcept override
{
94 return g_ceph_context
->_conf
->rgw_keystone_admin_project
;
97 boost::string_ref
get_admin_domain() const noexcept override
{
98 return g_ceph_context
->_conf
->rgw_keystone_admin_domain
;
108 class RGWKeystoneHTTPTransceiver
: public RGWHTTPTransceiver
{
110 RGWKeystoneHTTPTransceiver(CephContext
* const cct
,
111 bufferlist
* const token_body_bl
)
112 : RGWHTTPTransceiver(cct
, token_body_bl
,
113 cct
->_conf
->rgw_keystone_verify_ssl
,
114 { "X-Subject-Token" }) {
117 const header_value_t
& get_subject_token() const {
119 return get_header_value("X-Subject-Token");
120 } catch (std::out_of_range
&) {
121 static header_value_t empty_val
;
127 typedef RGWKeystoneHTTPTransceiver RGWValidateKeystoneToken
;
128 typedef RGWKeystoneHTTPTransceiver RGWGetKeystoneAdminToken
;
129 typedef RGWKeystoneHTTPTransceiver RGWGetRevokedTokens
;
131 static int get_admin_token(CephContext
* const cct
,
132 TokenCache
& token_cache
,
133 const Config
& config
,
135 static int issue_admin_token_request(CephContext
* const cct
,
136 const Config
& config
,
137 TokenEnvelope
& token
);
138 static int get_keystone_barbican_token(CephContext
* const cct
,
143 class TokenEnvelope
{
149 void decode_json(JSONObj
*obj
);
156 void decode_json(JSONObj
*obj
);
161 Token() : expires(0) { }
165 void decode_json(JSONObj
*obj
);
172 void decode_json(JSONObj
*obj
);
181 void decode_json(JSONObj
*obj
);
189 void decode_v3(JSONObj
* obj
);
190 void decode_v2(JSONObj
* obj
);
193 /* We really need the default ctor because of the internals of TokenCache. */
194 TokenEnvelope() = default;
196 time_t get_expires() const { return token
.expires
; }
197 const std::string
& get_domain_id() const {return project
.domain
.id
;};
198 const std::string
& get_domain_name() const {return project
.domain
.name
;};
199 const std::string
& get_project_id() const {return project
.id
;};
200 const std::string
& get_project_name() const {return project
.name
;};
201 const std::string
& get_user_id() const {return user
.id
;};
202 const std::string
& get_user_name() const {return user
.name
;};
203 bool has_role(const string
& r
) const;
204 bool expired() const {
205 const uint64_t now
= ceph_clock_now().sec();
206 return now
>= static_cast<uint64_t>(get_expires());
208 int parse(CephContext
* cct
,
209 const std::string
& token_str
,
210 ceph::buffer::list
& bl
/* in */,
218 list
<string
>::iterator lru_iter
;
221 std::atomic
<bool> down_flag
= { false };
223 class RevokeThread
: public Thread
{
224 friend class TokenCache
;
225 typedef RGWPostHTTPData RGWGetRevokedTokens
;
227 CephContext
* const cct
;
228 TokenCache
* const cache
;
229 const rgw::keystone::Config
& config
;
234 RevokeThread(CephContext
* const cct
,
235 TokenCache
* const cache
,
236 const rgw::keystone::Config
& config
)
240 lock("rgw::keystone::TokenCache::RevokeThread") {
242 void *entry() override
;
247 CephContext
* const cct
;
249 std::string admin_token_id
;
250 std::string barbican_token_id
;
251 std::map
<std::string
, token_entry
> tokens
;
252 std::list
<std::string
> tokens_lru
;
258 TokenCache(const rgw::keystone::Config
& config
)
259 : revocator(g_ceph_context
, this, config
),
261 lock("rgw::keystone::TokenCache"),
262 max(cct
->_conf
->rgw_keystone_token_cache_size
) {
263 /* revocation logic needs to be smarter, but meanwhile,
265 * see http://tracker.ceph.com/issues/9493
266 * http://tracker.ceph.com/issues/19499
268 if (cct
->_conf
->rgw_keystone_revocation_interval
> 0
269 && cct
->_conf
->rgw_keystone_token_cache_size
) {
270 /* The thread name has been kept for backward compliance. */
271 revocator
.create("rgw_swift_k_rev");
283 TokenCache(const TokenCache
&) = delete;
284 void operator=(const TokenCache
&) = delete;
286 template<class ConfigT
>
287 static TokenCache
& get_instance() {
288 static_assert(std::is_base_of
<rgw::keystone::Config
, ConfigT
>::value
,
289 "ConfigT must be a subclass of rgw::keystone::Config");
291 /* In C++11 this is thread safe. */
292 static TokenCache
instance(ConfigT::get_instance());
296 bool find(const std::string
& token_id
, TokenEnvelope
& token
);
297 boost::optional
<TokenEnvelope
> find(const std::string
& token_id
) {
298 TokenEnvelope token_envlp
;
299 if (find(token_id
, token_envlp
)) {
304 bool find_admin(TokenEnvelope
& token
);
305 bool find_barbican(TokenEnvelope
& token
);
306 void add(const std::string
& token_id
, const TokenEnvelope
& token
);
307 void add_admin(const TokenEnvelope
& token
);
308 void add_barbican(const TokenEnvelope
& token
);
309 void invalidate(const std::string
& token_id
);
310 bool going_down() const;
312 void add_locked(const std::string
& token_id
, const TokenEnvelope
& token
);
313 bool find_locked(const std::string
& token_id
, TokenEnvelope
& token
);
318 class AdminTokenRequest
{
320 virtual ~AdminTokenRequest() = default;
321 virtual void dump(Formatter
* f
) const = 0;
324 class AdminTokenRequestVer2
: public AdminTokenRequest
{
328 AdminTokenRequestVer2(const Config
& conf
)
331 void dump(Formatter
*f
) const override
;
334 class AdminTokenRequestVer3
: public AdminTokenRequest
{
338 AdminTokenRequestVer3(const Config
& conf
)
341 void dump(Formatter
*f
) const override
;
344 class BarbicanTokenRequestVer2
: public AdminTokenRequest
{
348 BarbicanTokenRequestVer2(CephContext
* const _cct
)
351 void dump(Formatter
*f
) const;
354 class BarbicanTokenRequestVer3
: public AdminTokenRequest
{
358 BarbicanTokenRequestVer3(CephContext
* const _cct
)
361 void dump(Formatter
*f
) const;
365 }; /* namespace keystone */
366 }; /* namespace rgw */