+std::string
+WebTokenEngine::get_role_tenant(const string& role_arn) const
+{
+ string tenant;
+ auto r_arn = rgw::ARN::parse(role_arn);
+ if (r_arn) {
+ tenant = r_arn->account;
+ }
+ return tenant;
+}
+
+std::string
+WebTokenEngine::get_role_name(const string& role_arn) const
+{
+ string role_name;
+ auto r_arn = rgw::ARN::parse(role_arn);
+ if (r_arn) {
+ role_name = r_arn->resource;
+ }
+ if (!role_name.empty()) {
+ auto pos = role_name.find_last_of('/');
+ if(pos != string::npos) {
+ role_name = role_name.substr(pos + 1);
+ }
+ }
+ return role_name;
+}
+
+std::unique_ptr<rgw::sal::RGWOIDCProvider>
+WebTokenEngine::get_provider(const DoutPrefixProvider *dpp, const string& role_arn, const string& iss) const
+{
+ string tenant = get_role_tenant(role_arn);
+
+ string idp_url = iss;
+ auto pos = idp_url.find("http://");
+ if (pos == std::string::npos) {
+ pos = idp_url.find("https://");
+ if (pos != std::string::npos) {
+ idp_url.erase(pos, 8);
+ } else {
+ pos = idp_url.find("www.");
+ if (pos != std::string::npos) {
+ idp_url.erase(pos, 4);
+ }
+ }
+ } else {
+ idp_url.erase(pos, 7);
+ }
+ auto provider_arn = rgw::ARN(idp_url, "oidc-provider", tenant);
+ string p_arn = provider_arn.to_string();
+ std::unique_ptr<rgw::sal::RGWOIDCProvider> provider = store->get_oidc_provider();
+ provider->set_arn(p_arn);
+ provider->set_tenant(tenant);
+ auto ret = provider->get(dpp);
+ if (ret < 0) {
+ return nullptr;
+ }
+ return provider;
+}
+
+bool
+WebTokenEngine::is_client_id_valid(vector<string>& client_ids, const string& client_id) const
+{
+ for (auto it : client_ids) {
+ if (it == client_id) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+WebTokenEngine::is_cert_valid(const vector<string>& thumbprints, const string& cert) const
+{
+ //calculate thumbprint of cert
+ std::unique_ptr<BIO, decltype(&BIO_free_all)> certbio(BIO_new_mem_buf(cert.data(), cert.size()), BIO_free_all);
+ std::unique_ptr<BIO, decltype(&BIO_free_all)> keybio(BIO_new(BIO_s_mem()), BIO_free_all);
+ string pw="";
+ std::unique_ptr<X509, decltype(&X509_free)> x_509cert(PEM_read_bio_X509(certbio.get(), nullptr, nullptr, const_cast<char*>(pw.c_str())), X509_free);
+ const EVP_MD* fprint_type = EVP_sha1();
+ unsigned int fprint_size;
+ unsigned char fprint[EVP_MAX_MD_SIZE];
+
+ if (!X509_digest(x_509cert.get(), fprint_type, fprint, &fprint_size)) {
+ return false;
+ }
+ stringstream ss;
+ for (unsigned int i = 0; i < fprint_size; i++) {
+ ss << std::setfill('0') << std::setw(2) << std::hex << (0xFF & (unsigned int)fprint[i]);
+ }
+ std::string digest = ss.str();
+
+ for (auto& it : thumbprints) {
+ if (boost::iequals(it,digest)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+template <typename T>
+void
+WebTokenEngine::recurse_and_insert(const string& key, const jwt::claim& c, T& t) const
+{
+ string s_val;
+ jwt::claim::type c_type = c.get_type();
+ switch(c_type) {
+ case jwt::claim::type::null:
+ break;
+ case jwt::claim::type::boolean:
+ case jwt::claim::type::number:
+ case jwt::claim::type::int64:
+ {
+ s_val = c.to_json().serialize();
+ t.emplace(std::make_pair(key, s_val));
+ break;
+ }
+ case jwt::claim::type::string:
+ {
+ s_val = c.to_json().to_str();
+ t.emplace(std::make_pair(key, s_val));
+ break;
+ }
+ case jwt::claim::type::array:
+ {
+ const picojson::array& arr = c.as_array();
+ for (auto& a : arr) {
+ recurse_and_insert(key, jwt::claim(a), t);
+ }
+ break;
+ }
+ case jwt::claim::type::object:
+ {
+ const picojson::object& obj = c.as_object();
+ for (auto& m : obj) {
+ recurse_and_insert(m.first, jwt::claim(m.second), t);
+ }
+ break;
+ }
+ }
+ return;
+}
+
+//Extract all token claims so that they can be later used in the Condition element of Role's trust policy
+WebTokenEngine::token_t
+WebTokenEngine::get_token_claims(const jwt::decoded_jwt& decoded) const
+{
+ WebTokenEngine::token_t token;
+ const auto& claims = decoded.get_payload_claims();
+
+ for (auto& c : claims) {
+ if (c.first == string(princTagsNamespace)) {
+ continue;
+ }
+ recurse_and_insert(c.first, c.second, token);
+ }
+ return token;
+}
+
+//Offline validation of incoming Web Token which is a signed JWT (JSON Web Token)
+std::tuple<boost::optional<WebTokenEngine::token_t>, boost::optional<WebTokenEngine::principal_tags_t>>
+WebTokenEngine::get_from_jwt(const DoutPrefixProvider* dpp, const std::string& token, const req_state* const s,
+ optional_yield y) const