1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
5 #ifndef CEPH_RGW_AUTH_KEYSTONE_H
6 #define CEPH_RGW_AUTH_KEYSTONE_H
9 #include <boost/optional.hpp>
10 #include <boost/utility/string_view.hpp>
13 #include "rgw_rest_s3.h"
14 #include "rgw_common.h"
15 #include "rgw_keystone.h"
21 /* Dedicated namespace for Keystone-related auth engines. We need it because
22 * Keystone offers three different authentication mechanisms (token, EC2 and
23 * regular user/pass). RadosGW actually does support the first two. */
25 class TokenEngine
: public rgw::auth::Engine
{
26 CephContext
* const cct
;
28 using acl_strategy_t
= rgw::auth::RemoteApplier::acl_strategy_t
;
29 using auth_info_t
= rgw::auth::RemoteApplier::AuthInfo
;
30 using result_t
= rgw::auth::Engine::result_t
;
31 using token_envelope_t
= rgw::keystone::TokenEnvelope
;
33 const rgw::auth::TokenExtractor
* const extractor
;
34 const rgw::auth::RemoteApplier::Factory
* const apl_factory
;
35 rgw::keystone::Config
& config
;
36 rgw::keystone::TokenCache
& token_cache
;
39 bool is_applicable(const std::string
& token
) const noexcept
;
41 boost::optional
<token_envelope_t
>
42 get_from_keystone(const DoutPrefixProvider
* dpp
, const std::string
& token
) const;
44 acl_strategy_t
get_acl_strategy(const token_envelope_t
& token
) const;
45 auth_info_t
get_creds_info(const token_envelope_t
& token
,
46 const std::vector
<std::string
>& admin_roles
48 result_t
authenticate(const DoutPrefixProvider
* dpp
,
49 const std::string
& token
,
50 const req_state
* s
) const;
53 TokenEngine(CephContext
* const cct
,
54 const rgw::auth::TokenExtractor
* const extractor
,
55 const rgw::auth::RemoteApplier::Factory
* const apl_factory
,
56 rgw::keystone::Config
& config
,
57 rgw::keystone::TokenCache
& token_cache
)
60 apl_factory(apl_factory
),
62 token_cache(token_cache
) {
65 const char* get_name() const noexcept override
{
66 return "rgw::auth::keystone::TokenEngine";
69 result_t
authenticate(const DoutPrefixProvider
* dpp
, const req_state
* const s
) const override
{
70 return authenticate(dpp
, extractor
->get_token(s
), s
);
72 }; /* class TokenEngine */
75 using token_envelope_t
= rgw::keystone::TokenEnvelope
;
78 token_envelope_t token
;
81 list
<std::string
>::iterator lru_iter
;
84 const boost::intrusive_ptr
<CephContext
> cct
;
86 std::map
<std::string
, secret_entry
> secrets
;
87 std::list
<std::string
> secrets_lru
;
93 const utime_t s3_token_expiry_length
;
96 : cct(g_ceph_context
),
98 max(cct
->_conf
->rgw_keystone_token_cache_size
),
99 s3_token_expiry_length(300, 0) {
105 SecretCache(const SecretCache
&) = delete;
106 void operator=(const SecretCache
&) = delete;
108 static SecretCache
& get_instance() {
109 /* In C++11 this is thread safe. */
110 static SecretCache instance
;
114 bool find(const std::string
& token_id
, token_envelope_t
& token
, std::string
& secret
);
115 boost::optional
<boost::tuple
<token_envelope_t
, std::string
>> find(const std::string
& token_id
) {
116 token_envelope_t token_envlp
;
118 if (find(token_id
, token_envlp
, secret
)) {
119 return boost::make_tuple(token_envlp
, secret
);
123 void add(const std::string
& token_id
, const token_envelope_t
& token
, const std::string
& secret
);
124 }; /* class SecretCache */
126 class EC2Engine
: public rgw::auth::s3::AWSEngine
{
127 using acl_strategy_t
= rgw::auth::RemoteApplier::acl_strategy_t
;
128 using auth_info_t
= rgw::auth::RemoteApplier::AuthInfo
;
129 using result_t
= rgw::auth::Engine::result_t
;
130 using token_envelope_t
= rgw::keystone::TokenEnvelope
;
132 const rgw::auth::RemoteApplier::Factory
* const apl_factory
;
133 rgw::keystone::Config
& config
;
134 rgw::keystone::TokenCache
& token_cache
;
135 rgw::auth::keystone::SecretCache
& secret_cache
;
137 /* Helper methods. */
138 acl_strategy_t
get_acl_strategy(const token_envelope_t
& token
) const;
139 auth_info_t
get_creds_info(const token_envelope_t
& token
,
140 const std::vector
<std::string
>& admin_roles
142 std::pair
<boost::optional
<token_envelope_t
>, int>
143 get_from_keystone(const DoutPrefixProvider
* dpp
,
144 const boost::string_view
& access_key_id
,
145 const std::string
& string_to_sign
,
146 const boost::string_view
& signature
) const;
147 std::pair
<boost::optional
<token_envelope_t
>, int>
148 get_access_token(const DoutPrefixProvider
* dpp
,
149 const boost::string_view
& access_key_id
,
150 const std::string
& string_to_sign
,
151 const boost::string_view
& signature
,
152 const signature_factory_t
& signature_factory
) const;
153 result_t
authenticate(const DoutPrefixProvider
* dpp
,
154 const boost::string_view
& access_key_id
,
155 const boost::string_view
& signature
,
156 const boost::string_view
& session_token
,
157 const string_to_sign_t
& string_to_sign
,
158 const signature_factory_t
& signature_factory
,
159 const completer_factory_t
& completer_factory
,
160 const req_state
* s
) const override
;
161 std::pair
<boost::optional
<std::string
>, int> get_secret_from_keystone(const DoutPrefixProvider
* dpp
,
162 const std::string
& user_id
,
163 const boost::string_view
& access_key_id
) const;
165 EC2Engine(CephContext
* const cct
,
166 const rgw::auth::s3::AWSEngine::VersionAbstractor
* const ver_abstractor
,
167 const rgw::auth::RemoteApplier::Factory
* const apl_factory
,
168 rgw::keystone::Config
& config
,
169 /* The token cache is used ONLY for the retrieving admin token.
170 * Due to the architecture of AWS Auth S3 credentials cannot be
172 rgw::keystone::TokenCache
& token_cache
,
173 rgw::auth::keystone::SecretCache
& secret_cache
)
174 : AWSEngine(cct
, *ver_abstractor
),
175 apl_factory(apl_factory
),
177 token_cache(token_cache
),
178 secret_cache(secret_cache
) {
181 using AWSEngine::authenticate
;
183 const char* get_name() const noexcept override
{
184 return "rgw::auth::keystone::EC2Engine";
187 }; /* class EC2Engine */
189 }; /* namespace keystone */
190 }; /* namespace auth */
191 }; /* namespace rgw */
193 #endif /* CEPH_RGW_AUTH_KEYSTONE_H */