]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_rest_sts.h
import quincy beta 17.1.0
[ceph.git] / ceph / src / rgw / rgw_rest_sts.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 #pragma once
5
6 #include "rgw_auth.h"
7 #include "rgw_auth_filters.h"
8 #include "rgw_rest.h"
9 #include "rgw_sts.h"
10 #include "rgw_web_idp.h"
11 #include "jwt-cpp/jwt.h"
12 #include "rgw_oidc_provider.h"
13
14 namespace rgw::auth::sts {
15
16 class WebTokenEngine : public rgw::auth::Engine {
17 static constexpr std::string_view princTagsNamespace = "https://aws.amazon.com/tags";
18 CephContext* const cct;
19 rgw::sal::Store* store;
20
21 using result_t = rgw::auth::Engine::result_t;
22 using Pair = std::pair<std::string, std::string>;
23 using token_t = std::unordered_multimap<string, string>;
24 using principal_tags_t = std::set<Pair>;
25
26 const rgw::auth::TokenExtractor* const extractor;
27 const rgw::auth::WebIdentityApplier::Factory* const apl_factory;
28
29 bool is_applicable(const std::string& token) const noexcept;
30
31 bool is_client_id_valid(std::vector<std::string>& client_ids, const std::string& client_id) const;
32
33 bool is_cert_valid(const std::vector<std::string>& thumbprints, const std::string& cert) const;
34
35 std::unique_ptr<rgw::sal::RGWOIDCProvider> get_provider(const DoutPrefixProvider *dpp, const std::string& role_arn, const std::string& iss) const;
36
37 std::string get_role_tenant(const std::string& role_arn) const;
38
39 std::string get_role_name(const string& role_arn) const;
40
41 std::string get_cert_url(const std::string& iss, const DoutPrefixProvider *dpp,optional_yield y) const;
42
43 std::tuple<boost::optional<WebTokenEngine::token_t>, boost::optional<WebTokenEngine::principal_tags_t>>
44 get_from_jwt(const DoutPrefixProvider* dpp, const std::string& token, const req_state* const s, optional_yield y) const;
45
46 void validate_signature (const DoutPrefixProvider* dpp, const jwt::decoded_jwt& decoded, const std::string& algorithm, const std::string& iss, const std::vector<std::string>& thumbprints, optional_yield y) const;
47
48 result_t authenticate(const DoutPrefixProvider* dpp,
49 const std::string& token,
50 const req_state* s, optional_yield y) const;
51
52 template <typename T>
53 void recurse_and_insert(const string& key, const jwt::claim& c, T& t) const;
54 WebTokenEngine::token_t get_token_claims(const jwt::decoded_jwt& decoded) const;
55
56 public:
57 WebTokenEngine(CephContext* const cct,
58 rgw::sal::Store* store,
59 const rgw::auth::TokenExtractor* const extractor,
60 const rgw::auth::WebIdentityApplier::Factory* const apl_factory)
61 : cct(cct),
62 store(store),
63 extractor(extractor),
64 apl_factory(apl_factory) {
65 }
66
67 const char* get_name() const noexcept override {
68 return "rgw::auth::sts::WebTokenEngine";
69 }
70
71 result_t authenticate(const DoutPrefixProvider* dpp, const req_state* const s, optional_yield y) const override {
72 return authenticate(dpp, extractor->get_token(s), s, y);
73 }
74 }; /* class WebTokenEngine */
75
76 class DefaultStrategy : public rgw::auth::Strategy,
77 public rgw::auth::TokenExtractor,
78 public rgw::auth::WebIdentityApplier::Factory {
79 rgw::sal::Store* store;
80 ImplicitTenants& implicit_tenant_context;
81
82 /* The engine. */
83 const WebTokenEngine web_token_engine;
84
85 using aplptr_t = rgw::auth::IdentityApplier::aplptr_t;
86
87 /* The method implements TokenExtractor for Web Token in req_state. */
88 std::string get_token(const req_state* const s) const override {
89 return s->info.args.get("WebIdentityToken");
90 }
91
92 aplptr_t create_apl_web_identity( CephContext* cct,
93 const req_state* s,
94 const std::string& role_session,
95 const std::string& role_tenant,
96 const std::unordered_multimap<std::string, std::string>& token,
97 boost::optional<std::multimap<std::string, std::string>> role_tags,
98 boost::optional<std::set<std::pair<std::string, std::string>>> principal_tags) const override {
99 auto apl = rgw::auth::add_sysreq(cct, store, s,
100 rgw::auth::WebIdentityApplier(cct, store, role_session, role_tenant, token, role_tags, principal_tags));
101 return aplptr_t(new decltype(apl)(std::move(apl)));
102 }
103
104 public:
105 DefaultStrategy(CephContext* const cct,
106 ImplicitTenants& implicit_tenant_context,
107 rgw::sal::Store* store)
108 : store(store),
109 implicit_tenant_context(implicit_tenant_context),
110 web_token_engine(cct, store,
111 static_cast<rgw::auth::TokenExtractor*>(this),
112 static_cast<rgw::auth::WebIdentityApplier::Factory*>(this)) {
113 /* When the constructor's body is being executed, all member engines
114 * should be initialized. Thus, we can safely add them. */
115 using Control = rgw::auth::Strategy::Control;
116 add_engine(Control::SUFFICIENT, web_token_engine);
117 }
118
119 const char* get_name() const noexcept override {
120 return "rgw::auth::sts::DefaultStrategy";
121 }
122 };
123
124 } // namespace rgw::auth::sts
125
126 class RGWREST_STS : public RGWRESTOp {
127 protected:
128 STS::STSService sts;
129 public:
130 RGWREST_STS() = default;
131 int verify_permission(optional_yield y) override;
132 void send_response() override;
133 };
134
135 class RGWSTSAssumeRoleWithWebIdentity : public RGWREST_STS {
136 protected:
137 std::string duration;
138 std::string providerId;
139 std::string policy;
140 std::string roleArn;
141 std::string roleSessionName;
142 std::string sub;
143 std::string aud;
144 std::string iss;
145 public:
146 RGWSTSAssumeRoleWithWebIdentity() = default;
147 void execute(optional_yield y) override;
148 int get_params();
149 const char* name() const override { return "assume_role_web_identity"; }
150 RGWOpType get_type() override { return RGW_STS_ASSUME_ROLE_WEB_IDENTITY; }
151 };
152
153 class RGWSTSAssumeRole : public RGWREST_STS {
154 protected:
155 std::string duration;
156 std::string externalId;
157 std::string policy;
158 std::string roleArn;
159 std::string roleSessionName;
160 std::string serialNumber;
161 std::string tokenCode;
162 public:
163 RGWSTSAssumeRole() = default;
164 void execute(optional_yield y) override;
165 int get_params();
166 const char* name() const override { return "assume_role"; }
167 RGWOpType get_type() override { return RGW_STS_ASSUME_ROLE; }
168 };
169
170 class RGWSTSGetSessionToken : public RGWREST_STS {
171 protected:
172 std::string duration;
173 std::string serialNumber;
174 std::string tokenCode;
175 public:
176 RGWSTSGetSessionToken() = default;
177 void execute(optional_yield y) override;
178 int verify_permission(optional_yield y) override;
179 int get_params();
180 const char* name() const override { return "get_session_token"; }
181 RGWOpType get_type() override { return RGW_STS_GET_SESSION_TOKEN; }
182 };
183
184 class RGW_Auth_STS {
185 public:
186 static int authorize(const DoutPrefixProvider *dpp,
187 rgw::sal::Store* store,
188 const rgw::auth::StrategyRegistry& auth_registry,
189 struct req_state *s, optional_yield y);
190 };
191
192 class RGWHandler_REST_STS : public RGWHandler_REST {
193 const rgw::auth::StrategyRegistry& auth_registry;
194 const std::string& post_body;
195 RGWOp *op_post() override;
196 void rgw_sts_parse_input();
197 public:
198
199 static int init_from_header(struct req_state *s, int default_formatter, bool configurable_format);
200
201 RGWHandler_REST_STS(const rgw::auth::StrategyRegistry& auth_registry, const std::string& post_body="")
202 : RGWHandler_REST(),
203 auth_registry(auth_registry),
204 post_body(post_body) {}
205 ~RGWHandler_REST_STS() override = default;
206
207 int init(rgw::sal::Store* store,
208 struct req_state *s,
209 rgw::io::BasicClient *cio) override;
210 int authorize(const DoutPrefixProvider* dpp, optional_yield y) override;
211 int postauth_init(optional_yield y) override { return 0; }
212 };
213
214 class RGWRESTMgr_STS : public RGWRESTMgr {
215 public:
216 RGWRESTMgr_STS() = default;
217 ~RGWRESTMgr_STS() override = default;
218
219 RGWRESTMgr *get_resource_mgr(struct req_state* const s,
220 const std::string& uri,
221 std::string* const out_uri) override {
222 return this;
223 }
224
225 RGWHandler_REST* get_handler(rgw::sal::Store* store,
226 struct req_state*,
227 const rgw::auth::StrategyRegistry&,
228 const std::string&) override;
229 };