]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_auth_keystone.h
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rgw / rgw_auth_keystone.h
CommitLineData
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 3
1e59de90 4#pragma once
7c673cae 5
f67539c2 6#include <string_view>
7c673cae
FG
7#include <utility>
8#include <boost/optional.hpp>
9
10#include "rgw_auth.h"
11#include "rgw_rest_s3.h"
12#include "rgw_common.h"
13#include "rgw_keystone.h"
14
15namespace rgw {
16namespace auth {
17namespace keystone {
18
19/* Dedicated namespace for Keystone-related auth engines. We need it because
20 * Keystone offers three different authentication mechanisms (token, EC2 and
21 * regular user/pass). RadosGW actually does support the first two. */
22
23class TokenEngine : public rgw::auth::Engine {
24 CephContext* const cct;
25
26 using acl_strategy_t = rgw::auth::RemoteApplier::acl_strategy_t;
27 using auth_info_t = rgw::auth::RemoteApplier::AuthInfo;
28 using result_t = rgw::auth::Engine::result_t;
29 using token_envelope_t = rgw::keystone::TokenEnvelope;
30
1e59de90
TL
31 const rgw::auth::TokenExtractor* const auth_token_extractor;
32 const rgw::auth::TokenExtractor* const service_token_extractor;
7c673cae
FG
33 const rgw::auth::RemoteApplier::Factory* const apl_factory;
34 rgw::keystone::Config& config;
35 rgw::keystone::TokenCache& token_cache;
36
37 /* Helper methods. */
38 bool is_applicable(const std::string& token) const noexcept;
7c673cae
FG
39
40 boost::optional<token_envelope_t>
1e59de90 41 get_from_keystone(const DoutPrefixProvider* dpp, const std::string& token, bool allow_expired) const;
7c673cae
FG
42
43 acl_strategy_t get_acl_strategy(const token_envelope_t& token) const;
44 auth_info_t get_creds_info(const token_envelope_t& token,
45 const std::vector<std::string>& admin_roles
46 ) const noexcept;
11fdf7f2
TL
47 result_t authenticate(const DoutPrefixProvider* dpp,
48 const std::string& token,
1e59de90 49 const std::string& service_token,
7c673cae
FG
50 const req_state* s) const;
51
52public:
53 TokenEngine(CephContext* const cct,
1e59de90
TL
54 const rgw::auth::TokenExtractor* const auth_token_extractor,
55 const rgw::auth::TokenExtractor* const service_token_extractor,
7c673cae
FG
56 const rgw::auth::RemoteApplier::Factory* const apl_factory,
57 rgw::keystone::Config& config,
58 rgw::keystone::TokenCache& token_cache)
59 : cct(cct),
1e59de90
TL
60 auth_token_extractor(auth_token_extractor),
61 service_token_extractor(service_token_extractor),
7c673cae
FG
62 apl_factory(apl_factory),
63 config(config),
64 token_cache(token_cache) {
65 }
66
67 const char* get_name() const noexcept override {
68 return "rgw::auth::keystone::TokenEngine";
69 }
70
f67539c2
TL
71 result_t authenticate(const DoutPrefixProvider* dpp, const req_state* const s,
72 optional_yield y) const override {
1e59de90 73 return authenticate(dpp, auth_token_extractor->get_token(s), service_token_extractor->get_token(s), s);
7c673cae
FG
74 }
75}; /* class TokenEngine */
76
9f95a23c
TL
77class SecretCache {
78 using token_envelope_t = rgw::keystone::TokenEnvelope;
79
80 struct secret_entry {
81 token_envelope_t token;
82 std::string secret;
83 utime_t expires;
20effc67 84 std::list<std::string>::iterator lru_iter;
9f95a23c
TL
85 };
86
87 const boost::intrusive_ptr<CephContext> cct;
88
89 std::map<std::string, secret_entry> secrets;
90 std::list<std::string> secrets_lru;
91
92 std::mutex lock;
93
94 const size_t max;
95
96 const utime_t s3_token_expiry_length;
97
98 SecretCache()
99 : cct(g_ceph_context),
100 lock(),
101 max(cct->_conf->rgw_keystone_token_cache_size),
102 s3_token_expiry_length(300, 0) {
103 }
104
105 ~SecretCache() {}
106
107public:
108 SecretCache(const SecretCache&) = delete;
109 void operator=(const SecretCache&) = delete;
110
111 static SecretCache& get_instance() {
112 /* In C++11 this is thread safe. */
113 static SecretCache instance;
114 return instance;
115 }
116
117 bool find(const std::string& token_id, token_envelope_t& token, std::string& secret);
118 boost::optional<boost::tuple<token_envelope_t, std::string>> find(const std::string& token_id) {
119 token_envelope_t token_envlp;
120 std::string secret;
121 if (find(token_id, token_envlp, secret)) {
122 return boost::make_tuple(token_envlp, secret);
123 }
124 return boost::none;
125 }
126 void add(const std::string& token_id, const token_envelope_t& token, const std::string& secret);
127}; /* class SecretCache */
7c673cae 128
31f18b77 129class EC2Engine : public rgw::auth::s3::AWSEngine {
7c673cae
FG
130 using acl_strategy_t = rgw::auth::RemoteApplier::acl_strategy_t;
131 using auth_info_t = rgw::auth::RemoteApplier::AuthInfo;
132 using result_t = rgw::auth::Engine::result_t;
133 using token_envelope_t = rgw::keystone::TokenEnvelope;
134
135 const rgw::auth::RemoteApplier::Factory* const apl_factory;
136 rgw::keystone::Config& config;
137 rgw::keystone::TokenCache& token_cache;
9f95a23c 138 rgw::auth::keystone::SecretCache& secret_cache;
7c673cae
FG
139
140 /* Helper methods. */
141 acl_strategy_t get_acl_strategy(const token_envelope_t& token) const;
142 auth_info_t get_creds_info(const token_envelope_t& token,
2a845540
TL
143 const std::vector<std::string>& admin_roles,
144 const std::string& access_key_id
7c673cae
FG
145 ) const noexcept;
146 std::pair<boost::optional<token_envelope_t>, int>
9f95a23c 147 get_from_keystone(const DoutPrefixProvider* dpp,
f67539c2 148 const std::string_view& access_key_id,
7c673cae 149 const std::string& string_to_sign,
f67539c2 150 const std::string_view& signature) const;
1e59de90
TL
151
152 struct access_token_result {
153 boost::optional<token_envelope_t> token;
154 boost::optional<std::string> secret_key;
155 int failure_reason = 0;
156 };
157 access_token_result
9f95a23c 158 get_access_token(const DoutPrefixProvider* dpp,
f67539c2 159 const std::string_view& access_key_id,
9f95a23c 160 const std::string& string_to_sign,
f67539c2 161 const std::string_view& signature,
9f95a23c 162 const signature_factory_t& signature_factory) const;
11fdf7f2 163 result_t authenticate(const DoutPrefixProvider* dpp,
f67539c2
TL
164 const std::string_view& access_key_id,
165 const std::string_view& signature,
166 const std::string_view& session_token,
31f18b77 167 const string_to_sign_t& string_to_sign,
9f95a23c 168 const signature_factory_t& signature_factory,
31f18b77 169 const completer_factory_t& completer_factory,
f67539c2
TL
170 const req_state* s,
171 optional_yield y) const override;
9f95a23c
TL
172 std::pair<boost::optional<std::string>, int> get_secret_from_keystone(const DoutPrefixProvider* dpp,
173 const std::string& user_id,
f67539c2 174 const std::string_view& access_key_id) const;
7c673cae
FG
175public:
176 EC2Engine(CephContext* const cct,
31f18b77 177 const rgw::auth::s3::AWSEngine::VersionAbstractor* const ver_abstractor,
7c673cae
FG
178 const rgw::auth::RemoteApplier::Factory* const apl_factory,
179 rgw::keystone::Config& config,
180 /* The token cache is used ONLY for the retrieving admin token.
181 * Due to the architecture of AWS Auth S3 credentials cannot be
182 * cached at all. */
9f95a23c
TL
183 rgw::keystone::TokenCache& token_cache,
184 rgw::auth::keystone::SecretCache& secret_cache)
31f18b77 185 : AWSEngine(cct, *ver_abstractor),
7c673cae
FG
186 apl_factory(apl_factory),
187 config(config),
9f95a23c
TL
188 token_cache(token_cache),
189 secret_cache(secret_cache) {
7c673cae
FG
190 }
191
31f18b77 192 using AWSEngine::authenticate;
7c673cae
FG
193
194 const char* get_name() const noexcept override {
195 return "rgw::auth::keystone::EC2Engine";
196 }
197
198}; /* class EC2Engine */
199
200}; /* namespace keystone */
201}; /* namespace auth */
202}; /* namespace rgw */