]>
Commit | Line | Data |
---|---|---|
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 | ||
5 | #ifndef CEPH_RGW_AUTH_KEYSTONE_H | |
6 | #define CEPH_RGW_AUTH_KEYSTONE_H | |
7 | ||
8 | #include <utility> | |
9 | #include <boost/optional.hpp> | |
31f18b77 | 10 | #include <boost/utility/string_view.hpp> |
7c673cae FG |
11 | |
12 | #include "rgw_auth.h" | |
13 | #include "rgw_rest_s3.h" | |
14 | #include "rgw_common.h" | |
15 | #include "rgw_keystone.h" | |
16 | ||
17 | namespace rgw { | |
18 | namespace auth { | |
19 | namespace keystone { | |
20 | ||
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. */ | |
24 | ||
25 | class TokenEngine : public rgw::auth::Engine { | |
26 | CephContext* const cct; | |
27 | ||
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; | |
32 | ||
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; | |
37 | ||
38 | /* Helper methods. */ | |
39 | bool is_applicable(const std::string& token) const noexcept; | |
7c673cae FG |
40 | |
41 | boost::optional<token_envelope_t> | |
11fdf7f2 | 42 | get_from_keystone(const DoutPrefixProvider* dpp, const std::string& token) const; |
7c673cae FG |
43 | |
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 | |
47 | ) const noexcept; | |
11fdf7f2 TL |
48 | result_t authenticate(const DoutPrefixProvider* dpp, |
49 | const std::string& token, | |
7c673cae FG |
50 | const req_state* s) const; |
51 | ||
52 | public: | |
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) | |
58 | : cct(cct), | |
59 | extractor(extractor), | |
60 | apl_factory(apl_factory), | |
61 | config(config), | |
62 | token_cache(token_cache) { | |
63 | } | |
64 | ||
65 | const char* get_name() const noexcept override { | |
66 | return "rgw::auth::keystone::TokenEngine"; | |
67 | } | |
68 | ||
11fdf7f2 TL |
69 | result_t authenticate(const DoutPrefixProvider* dpp, const req_state* const s) const override { |
70 | return authenticate(dpp, extractor->get_token(s), s); | |
7c673cae FG |
71 | } |
72 | }; /* class TokenEngine */ | |
73 | ||
9f95a23c TL |
74 | class SecretCache { |
75 | using token_envelope_t = rgw::keystone::TokenEnvelope; | |
76 | ||
77 | struct secret_entry { | |
78 | token_envelope_t token; | |
79 | std::string secret; | |
80 | utime_t expires; | |
81 | list<std::string>::iterator lru_iter; | |
82 | }; | |
83 | ||
84 | const boost::intrusive_ptr<CephContext> cct; | |
85 | ||
86 | std::map<std::string, secret_entry> secrets; | |
87 | std::list<std::string> secrets_lru; | |
88 | ||
89 | std::mutex lock; | |
90 | ||
91 | const size_t max; | |
92 | ||
93 | const utime_t s3_token_expiry_length; | |
94 | ||
95 | SecretCache() | |
96 | : cct(g_ceph_context), | |
97 | lock(), | |
98 | max(cct->_conf->rgw_keystone_token_cache_size), | |
99 | s3_token_expiry_length(300, 0) { | |
100 | } | |
101 | ||
102 | ~SecretCache() {} | |
103 | ||
104 | public: | |
105 | SecretCache(const SecretCache&) = delete; | |
106 | void operator=(const SecretCache&) = delete; | |
107 | ||
108 | static SecretCache& get_instance() { | |
109 | /* In C++11 this is thread safe. */ | |
110 | static SecretCache instance; | |
111 | return instance; | |
112 | } | |
113 | ||
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; | |
117 | std::string secret; | |
118 | if (find(token_id, token_envlp, secret)) { | |
119 | return boost::make_tuple(token_envlp, secret); | |
120 | } | |
121 | return boost::none; | |
122 | } | |
123 | void add(const std::string& token_id, const token_envelope_t& token, const std::string& secret); | |
124 | }; /* class SecretCache */ | |
7c673cae | 125 | |
31f18b77 | 126 | class EC2Engine : public rgw::auth::s3::AWSEngine { |
7c673cae FG |
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; | |
131 | ||
132 | const rgw::auth::RemoteApplier::Factory* const apl_factory; | |
133 | rgw::keystone::Config& config; | |
134 | rgw::keystone::TokenCache& token_cache; | |
9f95a23c | 135 | rgw::auth::keystone::SecretCache& secret_cache; |
7c673cae FG |
136 | |
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 | |
141 | ) const noexcept; | |
142 | std::pair<boost::optional<token_envelope_t>, int> | |
9f95a23c TL |
143 | get_from_keystone(const DoutPrefixProvider* dpp, |
144 | const boost::string_view& access_key_id, | |
7c673cae | 145 | const std::string& string_to_sign, |
31f18b77 | 146 | const boost::string_view& signature) const; |
9f95a23c TL |
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; | |
11fdf7f2 TL |
153 | result_t authenticate(const DoutPrefixProvider* dpp, |
154 | const boost::string_view& access_key_id, | |
31f18b77 | 155 | const boost::string_view& signature, |
11fdf7f2 | 156 | const boost::string_view& session_token, |
31f18b77 | 157 | const string_to_sign_t& string_to_sign, |
9f95a23c | 158 | const signature_factory_t& signature_factory, |
31f18b77 | 159 | const completer_factory_t& completer_factory, |
7c673cae | 160 | const req_state* s) const override; |
9f95a23c TL |
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; | |
7c673cae FG |
164 | public: |
165 | EC2Engine(CephContext* const cct, | |
31f18b77 | 166 | const rgw::auth::s3::AWSEngine::VersionAbstractor* const ver_abstractor, |
7c673cae FG |
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 | |
171 | * cached at all. */ | |
9f95a23c TL |
172 | rgw::keystone::TokenCache& token_cache, |
173 | rgw::auth::keystone::SecretCache& secret_cache) | |
31f18b77 | 174 | : AWSEngine(cct, *ver_abstractor), |
7c673cae FG |
175 | apl_factory(apl_factory), |
176 | config(config), | |
9f95a23c TL |
177 | token_cache(token_cache), |
178 | secret_cache(secret_cache) { | |
7c673cae FG |
179 | } |
180 | ||
31f18b77 | 181 | using AWSEngine::authenticate; |
7c673cae FG |
182 | |
183 | const char* get_name() const noexcept override { | |
184 | return "rgw::auth::keystone::EC2Engine"; | |
185 | } | |
186 | ||
187 | }; /* class EC2Engine */ | |
188 | ||
189 | }; /* namespace keystone */ | |
190 | }; /* namespace auth */ | |
191 | }; /* namespace rgw */ | |
192 | ||
193 | #endif /* CEPH_RGW_AUTH_KEYSTONE_H */ |