]>
git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_oidc_provider.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
8 #include "common/errno.h"
9 #include "common/Formatter.h"
10 #include "common/ceph_json.h"
11 #include "common/ceph_time.h"
12 #include "rgw_rados.h"
15 #include "include/types.h"
16 #include "rgw_string.h"
18 #include "rgw_common.h"
19 #include "rgw_tools.h"
20 #include "rgw_oidc_provider.h"
22 #include "services/svc_zone.h"
23 #include "services/svc_sys_obj.h"
25 #define dout_subsys ceph_subsys_rgw
27 const string
RGWOIDCProvider::oidc_url_oid_prefix
= "oidc_url.";
28 const string
RGWOIDCProvider::oidc_arn_prefix
= "arn:aws:iam::";
30 int RGWOIDCProvider::store_url(const string
& url
, bool exclusive
)
33 string oid
= tenant
+ get_url_oid_prefix() + url
;
39 auto obj_ctx
= svc
->sysobj
->init_obj_ctx();
40 return rgw_put_system_obj(obj_ctx
, svc
->zone
->get_zone_params().oidc_pool
, oid
,
41 bl
, exclusive
, NULL
, real_time(), NULL
);
44 int RGWOIDCProvider::get_tenant_url_from_arn(string
& tenant
, string
& url
)
46 auto provider_arn
= rgw::ARN::parse(arn
);
50 url
= provider_arn
->resource
;
51 tenant
= provider_arn
->account
;
52 auto pos
= url
.find("oidc-provider/");
53 if (pos
!= std::string::npos
) {
59 int RGWOIDCProvider::create(bool exclusive
)
63 if (! validate_input()) {
67 string idp_url
= url_remove_prefix(provider_url
);
69 /* check to see the name is not used */
70 ret
= read_url(idp_url
, tenant
);
71 if (exclusive
&& ret
== 0) {
72 ldout(cct
, 0) << "ERROR: url " << provider_url
<< " already in use"
75 } else if ( ret
< 0 && ret
!= -ENOENT
) {
76 ldout(cct
, 0) << "failed reading provider url " << provider_url
<< ": "
77 << cpp_strerror(-ret
) << dendl
;
82 arn
= oidc_arn_prefix
+ tenant
+ ":oidc-provider/" + idp_url
;
85 real_clock::time_point t
= real_clock::now();
88 real_clock::to_timeval(t
, tv
);
92 gmtime_r(&tv
.tv_sec
, &result
);
93 strftime(buf
,30,"%Y-%m-%dT%H:%M:%S", &result
);
94 sprintf(buf
+ strlen(buf
),".%dZ",(int)tv
.tv_usec
/1000);
95 creation_date
.assign(buf
, strlen(buf
));
99 auto& pool
= svc
->zone
->get_zone_params().oidc_pool
;
100 ret
= store_url(idp_url
, exclusive
);
102 ldout(cct
, 0) << "ERROR: storing role info in pool: " << pool
.name
<< ": "
103 << provider_url
<< ": " << cpp_strerror(-ret
) << dendl
;
110 int RGWOIDCProvider::delete_obj()
113 auto& pool
= svc
->zone
->get_zone_params().oidc_pool
;
116 auto ret
= get_tenant_url_from_arn(tenant
, url
);
118 ldout(cct
, 0) << "ERROR: failed to parse arn" << dendl
;
122 if (this->tenant
!= tenant
) {
123 ldout(cct
, 0) << "ERROR: tenant in arn doesn't match that of user " << this->tenant
<< ", "
124 << tenant
<< ": " << dendl
;
129 string oid
= tenant
+ get_url_oid_prefix() + url
;
130 ret
= rgw_delete_system_obj(svc
->sysobj
, pool
, oid
, NULL
);
132 ldout(cct
, 0) << "ERROR: deleting oidc url from pool: " << pool
.name
<< ": "
133 << provider_url
<< ": " << cpp_strerror(-ret
) << dendl
;
139 int RGWOIDCProvider::get()
142 auto ret
= get_tenant_url_from_arn(tenant
, url
);
144 ldout(cct
, 0) << "ERROR: failed to parse arn" << dendl
;
148 if (this->tenant
!= tenant
) {
149 ldout(cct
, 0) << "ERROR: tenant in arn doesn't match that of user " << this->tenant
<< ", "
150 << tenant
<< ": " << dendl
;
154 ret
= read_url(url
, tenant
);
162 void RGWOIDCProvider::dump(Formatter
*f
) const
164 encode_json("OpenIDConnectProviderArn", arn
, f
);
167 void RGWOIDCProvider::dump_all(Formatter
*f
) const
169 f
->open_object_section("ClientIDList");
170 for (auto it
: client_ids
) {
171 encode_json("member", it
, f
);
174 encode_json("CreateDate", creation_date
, f
);
175 f
->open_object_section("ThumbprintList");
176 for (auto it
: thumbprints
) {
177 encode_json("member", it
, f
);
180 encode_json("Url", provider_url
, f
);
183 void RGWOIDCProvider::decode_json(JSONObj
*obj
)
185 JSONDecoder::decode_json("OpenIDConnectProviderArn", arn
, obj
);
188 int RGWOIDCProvider::read_url(const string
& url
, const string
& tenant
)
191 auto& pool
= svc
->zone
->get_zone_params().oidc_pool
;
192 string oid
= tenant
+ get_url_oid_prefix() + url
;
194 auto obj_ctx
= svc
->sysobj
->init_obj_ctx();
196 int ret
= rgw_get_system_obj(obj_ctx
, pool
, oid
, bl
, NULL
, NULL
, null_yield
);
203 auto iter
= bl
.cbegin();
205 } catch (buffer::error
& err
) {
206 ldout(cct
, 0) << "ERROR: failed to decode oidc provider info from pool: " << pool
.name
<<
207 ": " << url
<< dendl
;
214 bool RGWOIDCProvider::validate_input()
216 if (provider_url
.length() > MAX_OIDC_URL_LEN
) {
217 ldout(cct
, 0) << "ERROR: Invalid length of url " << dendl
;
220 if (client_ids
.size() > MAX_OIDC_NUM_CLIENT_IDS
) {
221 ldout(cct
, 0) << "ERROR: Invalid number of client ids " << dendl
;
225 for (auto& it
: client_ids
) {
226 if (it
.length() > MAX_OIDC_CLIENT_ID_LEN
) {
231 if (thumbprints
.size() > MAX_OIDC_NUM_THUMBPRINTS
) {
232 ldout(cct
, 0) << "ERROR: Invalid number of thumbprints " << thumbprints
.size() << dendl
;
236 for (auto& it
: thumbprints
) {
237 if (it
.length() > MAX_OIDC_THUMBPRINT_LEN
) {
245 int RGWOIDCProvider::get_providers(RGWRados
*store
,
246 const string
& tenant
,
247 vector
<RGWOIDCProvider
>& providers
)
249 auto ctl
= store
->pctl
;
251 auto pool
= store
->svc
.zone
->get_zone_params().oidc_pool
;
252 string prefix
= tenant
+ oidc_url_oid_prefix
;
254 //Get the filtered objects
257 RGWListRawObjsCtx ctx
;
260 int r
= store
->list_raw_objects(pool
, prefix
, 1000, ctx
, oids
, &is_truncated
);
262 ldout(ctl
->cct
, 0) << "ERROR: listing filtered objects failed: " << pool
.name
<< ": "
263 << prefix
<< ": " << cpp_strerror(-r
) << dendl
;
266 for (const auto& iter
: oids
) {
267 RGWOIDCProvider
provider(ctl
->cct
, store
->pctl
);
269 auto obj_ctx
= svc
->sysobj
->init_obj_ctx();
271 int ret
= rgw_get_system_obj(obj_ctx
, pool
, iter
, bl
, NULL
, NULL
, null_yield
);
278 auto iter
= bl
.cbegin();
279 decode(provider
, iter
);
280 } catch (buffer::error
& err
) {
281 ldout(ctl
->cct
, 0) << "ERROR: failed to decode oidc provider info from pool: " << pool
.name
<<
282 ": " << iter
<< dendl
;
286 providers
.push_back(std::move(provider
));
288 } while (is_truncated
);
293 const string
& RGWOIDCProvider::get_url_oid_prefix()
295 return oidc_url_oid_prefix
;