From fcbc684e44abc0b336682a8f1d3b2ed072a9a359 Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Mon, 5 Feb 2024 17:49:42 -0500 Subject: [PATCH] rgw/iam: refactor OIDC ops rearrange the RGWRESTOp subclasses so that the base RGWRestOIDCProvider can provide a simple verify_permission() that works the same for all derived ops Signed-off-by: Casey Bodley --- src/rgw/rgw_rest_oidc_provider.cc | 138 +++++++++++++----------------- src/rgw/rgw_rest_oidc_provider.h | 67 +++++++-------- 2 files changed, 92 insertions(+), 113 deletions(-) diff --git a/src/rgw/rgw_rest_oidc_provider.cc b/src/rgw/rgw_rest_oidc_provider.cc index c50b067d58dba..e47239a67512e 100644 --- a/src/rgw/rgw_rest_oidc_provider.cc +++ b/src/rgw/rgw_rest_oidc_provider.cc @@ -24,32 +24,16 @@ using namespace std; int RGWRestOIDCProvider::verify_permission(optional_yield y) { - if (s->auth.identity->is_anonymous()) { - return -EACCES; + if (verify_user_permission(this, s, resource, action)) { + return 0; } - provider_arn = s->info.args.get("OpenIDConnectProviderArn"); - if (provider_arn.empty()) { - ldpp_dout(this, 20) << "ERROR: Provider ARN is empty"<< dendl; - return -EINVAL; - } - - auto ret = check_caps(s->user->get_caps()); - if (ret == 0) { - return ret; - } - - uint64_t op = get_op(); - auto rgw_arn = rgw::ARN::parse(provider_arn, true); - if (rgw_arn) { - if (!verify_user_permission(this, s, *rgw_arn, op)) { - return -EACCES; - } - } else { - return -EACCES; - } + return RGWRESTOp::verify_permission(y); +} - return 0; +int RGWRestOIDCProvider::check_caps(const RGWUserCaps& caps) +{ + return caps.check_cap("roles", perm); } void RGWRestOIDCProvider::send_response() @@ -61,42 +45,19 @@ void RGWRestOIDCProvider::send_response() end_header(s, this); } -int RGWRestOIDCProviderRead::check_caps(const RGWUserCaps& caps) -{ - return caps.check_cap("oidc-provider", RGW_CAP_READ); -} -int RGWRestOIDCProviderWrite::check_caps(const RGWUserCaps& caps) +RGWCreateOIDCProvider::RGWCreateOIDCProvider() + : RGWRestOIDCProvider(rgw::IAM::iamCreateOIDCProvider, RGW_CAP_WRITE) { - return caps.check_cap("oidc-provider", RGW_CAP_WRITE); } -int RGWCreateOIDCProvider::verify_permission(optional_yield y) -{ - if (s->auth.identity->is_anonymous()) { - return -EACCES; - } - - auto ret = check_caps(s->user->get_caps()); - if (ret == 0) { - return ret; - } - - string idp_url = url_remove_prefix(provider_url); - if (!verify_user_permission(this, - s, - rgw::ARN(idp_url, - "oidc-provider", - s->user->get_tenant(), true), - get_op())) { - return -EACCES; - } - return 0; -} - -int RGWCreateOIDCProvider::get_params() +int RGWCreateOIDCProvider::init_processing(optional_yield y) { provider_url = s->info.args.get("Url"); + if (provider_url.empty()) { + s->err.message = "Missing required element Url"; + return -EINVAL; + } auto val_map = s->info.args.get_params(); for (auto& it : val_map) { @@ -108,21 +69,18 @@ int RGWCreateOIDCProvider::get_params() } } - if (provider_url.empty() || thumbprints.empty()) { - ldpp_dout(this, 20) << "ERROR: one of url or thumbprints is empty" << dendl; + if (thumbprints.empty()) { + s->err.message = "Missing required element ThumbprintList"; return -EINVAL; } + string idp_url = url_remove_prefix(provider_url); + resource = rgw::ARN(idp_url, "oidc-provider/", s->user->get_tenant(), true); return 0; } void RGWCreateOIDCProvider::execute(optional_yield y) { - op_ret = get_params(); - if (op_ret < 0) { - return; - } - std::unique_ptr provider = driver->get_oidc_provider(); provider->set_url(provider_url); provider->set_tenant(s->user->get_tenant()); @@ -140,7 +98,36 @@ void RGWCreateOIDCProvider::execute(optional_yield y) s->formatter->close_section(); s->formatter->close_section(); } +} + + +static int validate_provider_arn(const std::string& provider_arn, + rgw::ARN& resource, std::string& message) +{ + if (provider_arn.empty()) { + message = "Missing required element OpenIDConnectProviderArn"; + return -EINVAL; + } + + auto arn = rgw::ARN::parse(provider_arn, true); + if (!arn) { + message = "Invalid value for OpenIDConnectProviderArn"; + return -EINVAL; + } + resource = std::move(*arn); + return 0; +} + + +RGWDeleteOIDCProvider::RGWDeleteOIDCProvider() + : RGWRestOIDCProvider(rgw::IAM::iamDeleteOIDCProvider, RGW_CAP_WRITE) +{ +} +int RGWDeleteOIDCProvider::init_processing(optional_yield y) +{ + provider_arn = s->info.args.get("OpenIDConnectProviderArn"); + return validate_provider_arn(provider_arn, resource, s->err.message); } void RGWDeleteOIDCProvider::execute(optional_yield y) @@ -163,6 +150,17 @@ void RGWDeleteOIDCProvider::execute(optional_yield y) } } +RGWGetOIDCProvider::RGWGetOIDCProvider() + : RGWRestOIDCProvider(rgw::IAM::iamGetOIDCProvider, RGW_CAP_READ) +{ +} + +int RGWGetOIDCProvider::init_processing(optional_yield y) +{ + provider_arn = s->info.args.get("OpenIDConnectProviderArn"); + return validate_provider_arn(provider_arn, resource, s->err.message); +} + void RGWGetOIDCProvider::execute(optional_yield y) { std::unique_ptr provider = driver->get_oidc_provider(); @@ -186,24 +184,10 @@ void RGWGetOIDCProvider::execute(optional_yield y) } } -int RGWListOIDCProviders::verify_permission(optional_yield y) -{ - if (s->auth.identity->is_anonymous()) { - return -EACCES; - } - - if (int ret = check_caps(s->user->get_caps()); ret == 0) { - return ret; - } - if (!verify_user_permission(this, - s, - rgw::ARN(), - get_op())) { - return -EACCES; - } - - return 0; +RGWListOIDCProviders::RGWListOIDCProviders() + : RGWRestOIDCProvider(rgw::IAM::iamListOIDCProviders, RGW_CAP_READ) +{ } void RGWListOIDCProviders::execute(optional_yield y) diff --git a/src/rgw/rgw_rest_oidc_provider.h b/src/rgw/rgw_rest_oidc_provider.h index 33535c6b5123d..14f71af17eb15 100644 --- a/src/rgw/rgw_rest_oidc_provider.h +++ b/src/rgw/rgw_rest_oidc_provider.h @@ -7,65 +7,60 @@ #include "rgw_oidc_provider.h" class RGWRestOIDCProvider : public RGWRESTOp { + const uint64_t action; + const uint32_t perm; protected: - std::vector client_ids; - std::vector thumbprints; - std::string provider_url; //'iss' field in JWT - std::string provider_arn; -public: - int verify_permission(optional_yield y) override; - void send_response() override; - virtual uint64_t get_op() = 0; -}; + rgw::ARN resource; // must be initialized before verify_permission() -class RGWRestOIDCProviderRead : public RGWRestOIDCProvider { -public: - RGWRestOIDCProviderRead() = default; int check_caps(const RGWUserCaps& caps) override; -}; -class RGWRestOIDCProviderWrite : public RGWRestOIDCProvider { + RGWRestOIDCProvider(uint64_t action, uint32_t perm) + : action(action), perm(perm) {} public: - RGWRestOIDCProviderWrite() = default; - int check_caps(const RGWUserCaps& caps) override; + int verify_permission(optional_yield y) override; + void send_response() override; }; -class RGWCreateOIDCProvider : public RGWRestOIDCProviderWrite { -public: - RGWCreateOIDCProvider() = default; - int verify_permission(optional_yield y) override; +class RGWCreateOIDCProvider : public RGWRestOIDCProvider { + std::vector client_ids; + std::vector thumbprints; + std::string provider_url; //'iss' field in JWT + public: + RGWCreateOIDCProvider(); + + int init_processing(optional_yield y) override; void execute(optional_yield y) override; - int get_params(); const char* name() const override { return "create_oidc_provider"; } RGWOpType get_type() override { return RGW_OP_CREATE_OIDC_PROVIDER; } - uint64_t get_op() override { return rgw::IAM::iamCreateOIDCProvider; } }; -class RGWDeleteOIDCProvider : public RGWRestOIDCProviderWrite { -public: - RGWDeleteOIDCProvider() = default; +class RGWDeleteOIDCProvider : public RGWRestOIDCProvider { + std::string provider_arn; + public: + RGWDeleteOIDCProvider(); + + int init_processing(optional_yield y) override; void execute(optional_yield y) override; const char* name() const override { return "delete_oidc_provider"; } RGWOpType get_type() override { return RGW_OP_DELETE_OIDC_PROVIDER; } - uint64_t get_op() override { return rgw::IAM::iamDeleteOIDCProvider; } }; -class RGWGetOIDCProvider : public RGWRestOIDCProviderRead { -public: - RGWGetOIDCProvider() = default; +class RGWGetOIDCProvider : public RGWRestOIDCProvider { + std::string provider_arn; + public: + RGWGetOIDCProvider(); + + int init_processing(optional_yield y) override; void execute(optional_yield y) override; const char* name() const override { return "get_oidc_provider"; } RGWOpType get_type() override { return RGW_OP_GET_OIDC_PROVIDER; } - uint64_t get_op() override { return rgw::IAM::iamGetOIDCProvider; } }; -class RGWListOIDCProviders : public RGWRestOIDCProviderRead { -public: - RGWListOIDCProviders() = default; - int verify_permission(optional_yield y) override; +class RGWListOIDCProviders : public RGWRestOIDCProvider { + public: + RGWListOIDCProviders(); + void execute(optional_yield y) override; - int get_params(); const char* name() const override { return "list_oidc_providers"; } RGWOpType get_type() override { return RGW_OP_LIST_OIDC_PROVIDERS; } - uint64_t get_op() override { return rgw::IAM::iamListOIDCProviders; } }; -- 2.39.5