]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_auth_keystone.h
import 15.2.0 Octopus source
[ceph.git] / ceph / src / rgw / rgw_auth_keystone.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
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>
10 #include <boost/utility/string_view.hpp>
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;
40
41 boost::optional<token_envelope_t>
42 get_from_keystone(const DoutPrefixProvider* dpp, const std::string& token) const;
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;
48 result_t authenticate(const DoutPrefixProvider* dpp,
49 const std::string& token,
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
69 result_t authenticate(const DoutPrefixProvider* dpp, const req_state* const s) const override {
70 return authenticate(dpp, extractor->get_token(s), s);
71 }
72 }; /* class TokenEngine */
73
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 */
125
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;
131
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;
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>
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;
164 public:
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
171 * cached at all. */
172 rgw::keystone::TokenCache& token_cache,
173 rgw::auth::keystone::SecretCache& secret_cache)
174 : AWSEngine(cct, *ver_abstractor),
175 apl_factory(apl_factory),
176 config(config),
177 token_cache(token_cache),
178 secret_cache(secret_cache) {
179 }
180
181 using AWSEngine::authenticate;
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 */