mirror of
https://github.com/ceph/ceph
synced 2025-01-31 23:44:10 +00:00
Merge pull request #53915 from pritha-srivastava/wip-rgw-sts-update-oidc-provider
rgw/iam: add AddClientIdToOIDCProvider/UpdateOidcProviderThumbprint Reviewed-by: Matt Benjamin <mbenjamin@redhat.com> Reviewed-by: Casey Bodley <cbodley@redhat.com>
This commit is contained in:
commit
3e26494df4
@ -45,7 +45,7 @@ Example::
|
||||
POST "<hostname>?Action=Action=CreateOpenIDConnectProvider
|
||||
&ThumbprintList.list.1=F7D7B3515DD0D319DD219A43A9EA727AD6065287
|
||||
&ClientIDList.list.1=app-profile-jsp
|
||||
&Url=http://localhost:8080/auth/realms/quickstart
|
||||
&Url=http://localhost:8080/auth/realms/quickstart"
|
||||
|
||||
|
||||
DeleteOpenIDConnectProvider
|
||||
@ -63,7 +63,7 @@ Request Parameters
|
||||
|
||||
Example::
|
||||
POST "<hostname>?Action=Action=DeleteOpenIDConnectProvider
|
||||
&OpenIDConnectProviderArn=arn:aws:iam:::oidc-provider/localhost:8080/auth/realms/quickstart
|
||||
&OpenIDConnectProviderArn=arn:aws:iam:::oidc-provider/localhost:8080/auth/realms/quickstart"
|
||||
|
||||
|
||||
GetOpenIDConnectProvider
|
||||
@ -81,7 +81,7 @@ Request Parameters
|
||||
|
||||
Example::
|
||||
POST "<hostname>?Action=Action=GetOpenIDConnectProvider
|
||||
&OpenIDConnectProviderArn=arn:aws:iam:::oidc-provider/localhost:8080/auth/realms/quickstart
|
||||
&OpenIDConnectProviderArn=arn:aws:iam:::oidc-provider/localhost:8080/auth/realms/quickstart"
|
||||
|
||||
ListOpenIDConnectProviders
|
||||
--------------------------
|
||||
@ -95,3 +95,50 @@ None
|
||||
|
||||
Example::
|
||||
POST "<hostname>?Action=Action=ListOpenIDConnectProviders
|
||||
|
||||
AddClientIDToOpenIDConnectProvider
|
||||
----------------------------------
|
||||
|
||||
Add a client id to the list of existing client ids registered while creating an OpenIDConnectProvider.
|
||||
|
||||
Request Parameters
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``OpenIDConnectProviderArn``
|
||||
|
||||
:Description: ARN of the IDP which is returned by the Create API.
|
||||
:Type: String
|
||||
|
||||
``ClientID``
|
||||
|
||||
:Description: Client Id to add to the existing OpenIDConnectProvider.
|
||||
:Type: String
|
||||
|
||||
Example::
|
||||
POST "<hostname>?Action=Action=AddClientIDToOpenIDConnectProvider
|
||||
&OpenIDConnectProviderArn=arn:aws:iam:::oidc-provider/localhost:8080/auth/realms/quickstart
|
||||
&ClientID=app-jee-jsp"
|
||||
|
||||
UpdateOpenIDConnectProviderThumbprint
|
||||
-------------------------------------
|
||||
|
||||
Update the existing thumbprint list of an OpenIDConnectProvider with the given list.
|
||||
This API removes the existing thumbprint list and replaces that with the input thumbprint list.
|
||||
|
||||
Request Parameters
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``OpenIDConnectProviderArn``
|
||||
|
||||
:Description: ARN of the IDP which is returned by the Create API.
|
||||
:Type: String
|
||||
|
||||
``ThumbprintList.member.N``
|
||||
|
||||
:Description: List of OpenID Connect IDP's server certificates' thumbprints. A maximum of 5 thumbprints are allowed.
|
||||
:Type: Array of Strings
|
||||
|
||||
Example::
|
||||
POST "<hostname>?Action=Action=UpdateOpenIDConnectProviderThumbprint
|
||||
&OpenIDConnectProviderArn=arn:aws:iam:::oidc-provider/localhost:8080/auth/realms/quickstart
|
||||
&&ThumbprintList.list.1=ABCDB3515DD0D319DD219A43A9EA727AD6061234"
|
@ -495,6 +495,8 @@ bool is_non_s3_op(RGWOpType op_type)
|
||||
case RGW_OP_DELETE_OIDC_PROVIDER:
|
||||
case RGW_OP_GET_OIDC_PROVIDER:
|
||||
case RGW_OP_LIST_OIDC_PROVIDERS:
|
||||
case RGW_OP_ADD_CLIENTID_TO_OIDC_PROVIDER:
|
||||
case RGW_OP_UPDATE_OIDC_PROVIDER_THUMBPRINT:
|
||||
case RGW_OP_PUBSUB_TOPIC_CREATE:
|
||||
case RGW_OP_PUBSUB_TOPICS_LIST:
|
||||
case RGW_OP_PUBSUB_TOPIC_GET:
|
||||
|
@ -160,6 +160,8 @@ static const actpair actpairs[] =
|
||||
{ "iam:DeleteOIDCProvider", iamDeleteOIDCProvider},
|
||||
{ "iam:GetOIDCProvider", iamGetOIDCProvider},
|
||||
{ "iam:ListOIDCProviders", iamListOIDCProviders},
|
||||
{ "iam:AddClientIdToOIDCProvider", iamAddClientIdToOIDCProvider},
|
||||
{ "iam:UpdateOIDCProviderThumbprint", iamUpdateOIDCProviderThumbprint},
|
||||
{ "iam:TagRole", iamTagRole},
|
||||
{ "iam:ListRoleTags", iamListRoleTags},
|
||||
{ "iam:UntagRole", iamUntagRole},
|
||||
@ -1550,6 +1552,12 @@ const char* action_bit_string(uint64_t action) {
|
||||
case iamListOIDCProviders:
|
||||
return "iam:ListOIDCProviders";
|
||||
|
||||
case iamAddClientIdToOIDCProvider:
|
||||
return "iam:AddClientIdToOIDCProvider";
|
||||
|
||||
case iamUpdateOIDCProviderThumbprint:
|
||||
return "iam:UpdateOIDCProviderThumbprint";
|
||||
|
||||
case iamTagRole:
|
||||
return "iam:TagRole";
|
||||
|
||||
|
@ -143,6 +143,8 @@ enum {
|
||||
iamDeleteOIDCProvider,
|
||||
iamGetOIDCProvider,
|
||||
iamListOIDCProviders,
|
||||
iamAddClientIdToOIDCProvider,
|
||||
iamUpdateOIDCProviderThumbprint,
|
||||
iamTagRole,
|
||||
iamListRoleTags,
|
||||
iamUntagRole,
|
||||
|
@ -161,5 +161,7 @@ enum RGWOpType {
|
||||
RGW_OP_DELETE_OIDC_PROVIDER,
|
||||
RGW_OP_GET_OIDC_PROVIDER,
|
||||
RGW_OP_LIST_OIDC_PROVIDERS,
|
||||
RGW_OP_ADD_CLIENTID_TO_OIDC_PROVIDER,
|
||||
RGW_OP_UPDATE_OIDC_PROVIDER_THUMBPRINT,
|
||||
};
|
||||
|
||||
|
@ -45,6 +45,8 @@ static const std::unordered_map<std::string_view, op_generator> op_generators =
|
||||
{"ListOpenIDConnectProviders", [](const bufferlist& bl_post_body) -> RGWOp* {return new RGWListOIDCProviders;}},
|
||||
{"GetOpenIDConnectProvider", [](const bufferlist& bl_post_body) -> RGWOp* {return new RGWGetOIDCProvider;}},
|
||||
{"DeleteOpenIDConnectProvider", [](const bufferlist& bl_post_body) -> RGWOp* {return new RGWDeleteOIDCProvider;}},
|
||||
{"AddClientIDToOpenIDConnectProvider", [](const bufferlist& bl_post_body) -> RGWOp* {return new RGWAddClientIdToOIDCProvider;}},
|
||||
{"UpdateOpenIDConnectProviderThumbprint", [](const bufferlist& bl_post_body) -> RGWOp* {return new RGWUpdateOIDCProviderThumbprint;}},
|
||||
{"TagRole", [](const bufferlist& bl_post_body) -> RGWOp* {return new RGWTagRole(bl_post_body);}},
|
||||
{"ListRoleTags", [](const bufferlist& bl_post_body) -> RGWOp* {return new RGWListRoleTags;}},
|
||||
{"UntagRole", [](const bufferlist& bl_post_body) -> RGWOp* {return new RGWUntagRole(bl_post_body);}},
|
||||
|
@ -333,3 +333,147 @@ void RGWListOIDCProviders::execute(optional_yield y)
|
||||
s->formatter->close_section();
|
||||
}
|
||||
}
|
||||
|
||||
RGWAddClientIdToOIDCProvider::RGWAddClientIdToOIDCProvider()
|
||||
: RGWRestOIDCProvider(rgw::IAM::iamAddClientIdToOIDCProvider, RGW_CAP_WRITE)
|
||||
{
|
||||
}
|
||||
|
||||
int RGWAddClientIdToOIDCProvider::init_processing(optional_yield y)
|
||||
{
|
||||
std::string_view account;
|
||||
if (const auto& acc = s->auth.identity->get_account(); acc) {
|
||||
account = acc->id;
|
||||
} else {
|
||||
account = s->user->get_tenant();
|
||||
}
|
||||
std::string provider_arn = s->info.args.get("OpenIDConnectProviderArn");
|
||||
auto ret = validate_provider_arn(provider_arn, account,
|
||||
resource, url, s->err.message);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
client_id = s->info.args.get("ClientID");
|
||||
|
||||
if (client_id.empty()) {
|
||||
s->err.message = "Missing required element ClientID";
|
||||
ldpp_dout(this, 20) << "ERROR: ClientID is empty" << dendl;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (client_id.size() > MAX_OIDC_CLIENT_ID_LEN) {
|
||||
s->err.message = "ClientID cannot exceed the maximum length of "
|
||||
+ std::to_string(MAX_OIDC_CLIENT_ID_LEN);
|
||||
ldpp_dout(this, 20) << "ERROR: ClientID length exceeded " << MAX_OIDC_CLIENT_ID_LEN << dendl;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RGWAddClientIdToOIDCProvider::execute(optional_yield y)
|
||||
{
|
||||
RGWOIDCProviderInfo info;
|
||||
op_ret = driver->load_oidc_provider(this, y, resource.account, url, info);
|
||||
|
||||
if (op_ret < 0) {
|
||||
if (op_ret != -ENOENT && op_ret != -EINVAL) {
|
||||
op_ret = ERR_INTERNAL_ERROR;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(std::find(info.client_ids.begin(), info.client_ids.end(), client_id) != info.client_ids.end()) {
|
||||
op_ret = -EEXIST;
|
||||
} else {
|
||||
|
||||
info.client_ids.emplace_back(client_id);
|
||||
|
||||
constexpr bool exclusive = false;
|
||||
op_ret = driver->store_oidc_provider(this, y, info, exclusive);
|
||||
}
|
||||
if (op_ret == 0 || op_ret == -EEXIST) {
|
||||
op_ret = 0;
|
||||
s->formatter->open_object_section("AddClientIDToOpenIDConnectProviderResponse");
|
||||
s->formatter->open_object_section("ResponseMetadata");
|
||||
s->formatter->dump_string("RequestId", s->trans_id);
|
||||
s->formatter->close_section();
|
||||
s->formatter->open_object_section("AddClientIDToOpenIDConnectProviderResponse");
|
||||
dump_oidc_provider(info, s->formatter);
|
||||
s->formatter->close_section();
|
||||
s->formatter->close_section();
|
||||
}
|
||||
}
|
||||
|
||||
RGWUpdateOIDCProviderThumbprint::RGWUpdateOIDCProviderThumbprint()
|
||||
: RGWRestOIDCProvider(rgw::IAM::iamUpdateOIDCProviderThumbprint, RGW_CAP_WRITE)
|
||||
{
|
||||
}
|
||||
|
||||
int RGWUpdateOIDCProviderThumbprint::init_processing(optional_yield y)
|
||||
{
|
||||
std::string_view account;
|
||||
if (const auto& acc = s->auth.identity->get_account(); acc) {
|
||||
account = acc->id;
|
||||
} else {
|
||||
account = s->user->get_tenant();
|
||||
}
|
||||
std::string provider_arn = s->info.args.get("OpenIDConnectProviderArn");
|
||||
auto ret = validate_provider_arn(provider_arn, account,
|
||||
resource, url, s->err.message);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto val_map = s->info.args.get_params();
|
||||
/* From AWS documentation here: https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateOpenIDConnectProviderThumbprint.html
|
||||
The list that you pass with this operation completely replaces the existing list of thumbprints. (The lists are not merged.) */
|
||||
for (auto& it : val_map) {
|
||||
if (it.first.find("ThumbprintList.member.") != string::npos) {
|
||||
if (it.second.size() > MAX_OIDC_THUMBPRINT_LEN) {
|
||||
s->err.message = "Thumbprint cannot exceed the maximum length of "
|
||||
+ std::to_string(MAX_OIDC_THUMBPRINT_LEN);
|
||||
ldpp_dout(this, 20) << "ERROR: Thumbprint exceeds maximum length of " << MAX_OIDC_THUMBPRINT_LEN << dendl;
|
||||
return -EINVAL;
|
||||
}
|
||||
thumbprints.emplace_back(it.second);
|
||||
}
|
||||
}
|
||||
|
||||
if (thumbprints.empty()) {
|
||||
s->err.message = "Missing required element ThumbprintList";
|
||||
ldpp_dout(this, 20) << "ERROR: Thumbprints list is empty" << dendl;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RGWUpdateOIDCProviderThumbprint::execute(optional_yield y)
|
||||
{
|
||||
RGWOIDCProviderInfo info;
|
||||
op_ret = driver->load_oidc_provider(this, y, resource.account, url, info);
|
||||
|
||||
if (op_ret < 0) {
|
||||
if (op_ret != -ENOENT && op_ret != -EINVAL) {
|
||||
op_ret = ERR_INTERNAL_ERROR;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
info.thumbprints = std::move(thumbprints);
|
||||
|
||||
constexpr bool exclusive = false;
|
||||
op_ret = driver->store_oidc_provider(this, y, info, exclusive);
|
||||
if (op_ret == 0) {
|
||||
s->formatter->open_object_section("AddClientIDToOpenIDConnectProviderResponse");
|
||||
s->formatter->open_object_section("ResponseMetadata");
|
||||
s->formatter->dump_string("RequestId", s->trans_id);
|
||||
s->formatter->close_section();
|
||||
s->formatter->open_object_section("AddClientIDToOpenIDConnectProviderResponse");
|
||||
dump_oidc_provider(info, s->formatter);
|
||||
s->formatter->close_section();
|
||||
s->formatter->close_section();
|
||||
}
|
||||
}
|
||||
|
@ -62,3 +62,27 @@ class RGWListOIDCProviders : public RGWRestOIDCProvider {
|
||||
const char* name() const override { return "list_oidc_providers"; }
|
||||
RGWOpType get_type() override { return RGW_OP_LIST_OIDC_PROVIDERS; }
|
||||
};
|
||||
|
||||
class RGWAddClientIdToOIDCProvider : public RGWRestOIDCProvider {
|
||||
std::string url;
|
||||
std::string client_id;
|
||||
public:
|
||||
RGWAddClientIdToOIDCProvider();
|
||||
|
||||
int init_processing(optional_yield y);
|
||||
void execute(optional_yield y) override;
|
||||
const char* name() const override { return "add_client_id_to_oidc_provider"; }
|
||||
RGWOpType get_type() override { return RGW_OP_ADD_CLIENTID_TO_OIDC_PROVIDER; }
|
||||
};
|
||||
|
||||
class RGWUpdateOIDCProviderThumbprint : public RGWRestOIDCProvider {
|
||||
std::string url;
|
||||
std::vector<std::string> thumbprints;
|
||||
public:
|
||||
RGWUpdateOIDCProviderThumbprint();
|
||||
|
||||
int init_processing(optional_yield y);
|
||||
void execute(optional_yield y) override;
|
||||
const char* name() const override { return "update_oidc_provider_thumbprint"; }
|
||||
RGWOpType get_type() override { return RGW_OP_UPDATE_OIDC_PROVIDER_THUMBPRINT; }
|
||||
};
|
||||
|
@ -384,7 +384,6 @@ WebTokenEngine::validate_signature(const DoutPrefixProvider* dpp, const jwt::dec
|
||||
found_valid_cert = true;
|
||||
break;
|
||||
}
|
||||
found_valid_cert = true;
|
||||
}
|
||||
if (! found_valid_cert) {
|
||||
ldpp_dout(dpp, 0) << "Cert doesn't match that with the thumbprints registered with oidc provider: " << cert.c_str() << dendl;
|
||||
|
@ -1854,7 +1854,7 @@ do_rgw_create_users()
|
||||
--access-key ABCDEFGHIJKLMNOPQRST \
|
||||
--secret abcdefghijklmnopqrstuvwxyzabcdefghijklmn \
|
||||
--display-name youruseridhere \
|
||||
--email s3@example.com --caps="roles=*;user-policy=*" -c $conf_fn > /dev/null
|
||||
--email s3@example.com --caps="roles=*;user-policy=*;oidc-provider=*" -c $conf_fn > /dev/null
|
||||
$CEPH_BIN/radosgw-admin user create \
|
||||
--uid 56789abcdef0123456789abcdef0123456789abcdef0123456789abcdef01234 \
|
||||
--access-key NOPQRSTUVWXYZABCDEFG \
|
||||
|
Loading…
Reference in New Issue
Block a user