From 5d85c65ff1af0c0a6c359ebed37daab09690d470 Mon Sep 17 00:00:00 2001 From: Pritha Srivastava Date: Sun, 2 May 2021 09:29:03 +0530 Subject: [PATCH] rgw/sts: code for runtime evaluation of Condition element of an IAM policy. Signed-off-by: Pritha Srivastava --- src/rgw/rgw_iam_policy.cc | 40 ++++++++++++++++++++++++++++++--------- src/rgw/rgw_iam_policy.h | 1 + 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/rgw/rgw_iam_policy.cc b/src/rgw/rgw_iam_policy.cc index 8fe9d3a64cc..41d49791fcb 100644 --- a/src/rgw/rgw_iam_policy.cc +++ b/src/rgw/rgw_iam_policy.cc @@ -565,6 +565,17 @@ bool ParseState::do_string(CephContext* cct, const char* s, size_t l) { << dendl; } else if (w->kind == TokenKind::cond_key) { auto& t = pp->policy.statements.back(); + if (l > 0 && *s == '$') { + if (l >= 2 && *(s+1) == '{') { + if (l > 0 && *(s+l-1) == '}') { + t.conditions.back().isruntime = true; + } else { + return false; + } + } else { + return false; + } + } t.conditions.back().vals.emplace_back(s, l); // Principals @@ -676,6 +687,7 @@ ostream& operator <<(ostream& m, const MaskedIP& ip) { } bool Condition::eval(const Environment& env) const { + std::vector runtime_vals; auto i = env.find(key); if (op == TokenID::Null) { return i == env.end() ? true : false; @@ -690,6 +702,16 @@ bool Condition::eval(const Environment& env) const { return ifexists; } } + + if (isruntime) { + string k = vals.back(); + k.erase(0,2); //erase $, { + k.erase(k.length() - 1, 1); //erase } + const auto& it = env.equal_range(k); + for (auto itr = it.first; itr != it.second; itr++) { + runtime_vals.emplace_back(itr->second); + } + } const auto& s = i->second; const auto& itr = env.equal_range(key); @@ -698,34 +720,34 @@ bool Condition::eval(const Environment& env) const { // String! case TokenID::ForAnyValueStringEquals: case TokenID::StringEquals: - return orrible(std::equal_to(), itr, vals); + return orrible(std::equal_to(), itr, isruntime? runtime_vals : vals); case TokenID::StringNotEquals: return orrible(std::not_fn(std::equal_to()), - itr, vals); + itr, isruntime? runtime_vals : vals); case TokenID::ForAnyValueStringEqualsIgnoreCase: case TokenID::StringEqualsIgnoreCase: - return orrible(ci_equal_to(), itr, vals); + return orrible(ci_equal_to(), itr, isruntime? runtime_vals : vals); case TokenID::StringNotEqualsIgnoreCase: - return orrible(std::not_fn(ci_equal_to()), itr, vals); + return orrible(std::not_fn(ci_equal_to()), itr, isruntime? runtime_vals : vals); case TokenID::ForAnyValueStringLike: case TokenID::StringLike: - return orrible(string_like(), itr, vals); + return orrible(string_like(), itr, isruntime? runtime_vals : vals); case TokenID::StringNotLike: - return orrible(std::not_fn(string_like()), itr, vals); + return orrible(std::not_fn(string_like()), itr, isruntime? runtime_vals : vals); case TokenID::ForAllValuesStringEquals: - return andible(std::equal_to(), itr, vals); + return andible(std::equal_to(), itr, isruntime? runtime_vals : vals); case TokenID::ForAllValuesStringLike: - return andible(string_like(), itr, vals); + return andible(string_like(), itr, isruntime? runtime_vals : vals); case TokenID::ForAllValuesStringEqualsIgnoreCase: - return andible(ci_equal_to(), itr, vals); + return andible(ci_equal_to(), itr, isruntime? runtime_vals : vals); // Numeric case TokenID::NumericEquals: diff --git a/src/rgw/rgw_iam_policy.h b/src/rgw/rgw_iam_policy.h index 4a0f8f3b30f..e5ab4c70922 100644 --- a/src/rgw/rgw_iam_policy.h +++ b/src/rgw/rgw_iam_policy.h @@ -283,6 +283,7 @@ struct Condition { // In future development, use symbol internment. std::string key; bool ifexists = false; + bool isruntime = false; //Is evaluated during run-time // Much to my annoyance there is no actual way to do this in a // typed way that is compatible with AWS. I know this because I've // seen examples where the same value is used as a string in one -- 2.39.5