]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw/iam: Policy takes optional tenant name
authorCasey Bodley <cbodley@redhat.com>
Thu, 22 Feb 2024 18:16:00 +0000 (13:16 -0500)
committerCasey Bodley <cbodley@redhat.com>
Wed, 10 Apr 2024 17:09:16 +0000 (13:09 -0400)
the iam policy parser takes a tenant string to reject Resource ARNs that
specify resources in other tenants, and prevent wildcards from applying
to other tenants

this is problematic for account users, because cross-account access requires
an identity policy that covers another account's resource. it's the
cross-policy evaluation rules that prevent that from granting access to
things it shouldn't. so for account users, pass a null tenant string to
allow all resource arns

for resource policies, this restriction is unnecessary in the first
place, because the resource policy can only match itself as the resource

Signed-off-by: Casey Bodley <cbodley@redhat.com>
13 files changed:
src/rgw/rgw_admin.cc
src/rgw/rgw_auth.cc
src/rgw/rgw_iam_managed_policy.cc
src/rgw/rgw_iam_policy.cc
src/rgw/rgw_iam_policy.h
src/rgw/rgw_op.cc
src/rgw/rgw_polparser.cc
src/rgw/rgw_rest_iam_group.cc
src/rgw/rgw_rest_pubsub.cc
src/rgw/rgw_rest_role.cc
src/rgw/rgw_rest_sts.cc
src/rgw/rgw_rest_user_policy.cc
src/test/rgw/test_rgw_iam_policy.cc

index 88ad789efd7faaf9ce069d85f258fa4fa68e1cac..374a67f314f96d6aef751810f7832c1e7d0ab9e5 100644 (file)
@@ -6822,7 +6822,7 @@ int main(int argc, const char **argv)
       }
       try {
         const rgw::IAM::Policy p(
-         g_ceph_context, tenant, assume_role_doc,
+         g_ceph_context, nullptr, assume_role_doc,
          g_ceph_context->_conf.get_val<bool>(
            "rgw_policy_reject_invalid_principals"));
       } catch (rgw::IAM::PolicyParseException& e) {
@@ -6881,7 +6881,7 @@ int main(int argc, const char **argv)
       }
 
       try {
-        const rgw::IAM::Policy p(g_ceph_context, tenant, assume_role_doc,
+        const rgw::IAM::Policy p(g_ceph_context, nullptr, assume_role_doc,
                                 g_ceph_context->_conf.get_val<bool>(
                                   "rgw_policy_reject_invalid_principals"));
       } catch (rgw::IAM::PolicyParseException& e) {
@@ -6976,7 +6976,7 @@ int main(int argc, const char **argv)
         perm_policy_doc = bl.to_str();
       }
       try {
-        const rgw::IAM::Policy p(g_ceph_context, tenant, perm_policy_doc,
+        const rgw::IAM::Policy p(g_ceph_context, nullptr, perm_policy_doc,
                                 g_ceph_context->_conf.get_val<bool>(
                                   "rgw_policy_reject_invalid_principals"));
       } catch (rgw::IAM::PolicyParseException& e) {
index b5227aecf47cd9cc7049ff63c0ea97dbd2dfbd47..8b8cce881ce79e80b9d83cc90a7d076a16d143ea 100644 (file)
@@ -1009,9 +1009,12 @@ void rgw::auth::RoleApplier::load_acct_info(const DoutPrefixProvider* dpp, RGWUs
 
 void rgw::auth::RoleApplier::modify_request_state(const DoutPrefixProvider *dpp, req_state* s) const
 {
+  // non-account identity policy is restricted to the current tenant
+  const std::string* policy_tenant = role.account_id.empty() ? &role.tenant : nullptr;
+
   for (const auto& policy : role.inline_policies) {
     try {
-      const rgw::IAM::Policy p(s->cct, role.tenant, policy, false);
+      const rgw::IAM::Policy p(s->cct, policy_tenant, policy, false);
       s->iam_identity_policies.push_back(std::move(p));
     } catch (rgw::IAM::PolicyParseException& e) {
       //Control shouldn't reach here as the policy has already been
@@ -1034,7 +1037,7 @@ void rgw::auth::RoleApplier::modify_request_state(const DoutPrefixProvider *dpp,
   if (!this->token_attrs.token_policy.empty()) {
     try {
       string policy = this->token_attrs.token_policy;
-      const rgw::IAM::Policy p(s->cct, role.tenant, policy, false);
+      const rgw::IAM::Policy p(s->cct, policy_tenant, policy, false);
       s->session_policies.push_back(std::move(p));
     } catch (rgw::IAM::PolicyParseException& e) {
       //Control shouldn't reach here as the policy has already been
index 6187d7737dbb648dd89c6e01f4a10a39fdd64c6b..4e7f48cfe5fdc2079607ad9cf6bad665949c3109 100644 (file)
@@ -156,7 +156,7 @@ static constexpr std::string_view AmazonS3ReadOnlyAccess = R"(
 auto get_managed_policy(CephContext* cct, std::string_view arn)
     -> std::optional<Policy>
 {
-  const std::string tenant; // empty tenant
+  const std::string* tenant = nullptr;
   constexpr bool reject = false; // reject_invalid_principals
   if (arn == "arn:aws:iam::aws:policy/IAMFullAccess") {
     return Policy{cct, tenant, std::string{IAMFullAccess}, reject};
index cc8243022c5c966a201f8194402a3a49d41d775f..bef4b587a666ecb99a5c6df5c8238ffa5d8f0a46 100644 (file)
@@ -264,7 +264,7 @@ struct PolicyParser : public BaseReaderHandler<UTF8<>, PolicyParser> {
   keyword_hash tokens;
   std::vector<ParseState> s;
   CephContext* cct;
-  const string& tenant;
+  const string* tenant = nullptr;
   Policy& policy;
   uint32_t v = 0;
 
@@ -372,7 +372,7 @@ struct PolicyParser : public BaseReaderHandler<UTF8<>, PolicyParser> {
     v = 0;
   }
 
-  PolicyParser(CephContext* cct, const string& tenant, Policy& policy,
+  PolicyParser(CephContext* cct, const string* tenant, Policy& policy,
               bool reject_invalid_principals)
     : cct(cct), tenant(tenant), policy(policy),
       reject_invalid_principals(reject_invalid_principals) {}
@@ -688,16 +688,16 @@ bool ParseState::do_string(CephContext* cct, const char* s, size_t l) {
       return false;
     }
     // You can't specify resources for someone ELSE'S account.
-    if (a->account.empty() || a->account == pp->tenant ||
-       a->account == "*") {
-      if (a->account.empty() || a->account == "*")
-       a->account = pp->tenant;
+    if (a->account.empty() || pp->tenant == nullptr ||
+       a->account == *pp->tenant || a->account == "*") {
+      if (pp->tenant && (a->account.empty() || a->account == "*"))
+       a->account = *pp->tenant;
       (w->id == TokenID::Resource ? t->resource : t->notresource)
        .emplace(std::move(*a));
     } else {
       annotate(fmt::format("Policy owned by tenant `{}` cannot grant access to "
                           "resource owned by tenant `{}`.",
-                          pp->tenant, a->account));
+                          *pp->tenant, a->account));
       return false;
     }
   } else if (w->kind == TokenKind::cond_key) {
@@ -1797,7 +1797,7 @@ ostream& operator <<(ostream& m, const Statement& s) {
   return m << " }";
 }
 
-Policy::Policy(CephContext* cct, const string& tenant,
+Policy::Policy(CephContext* cct, const string* tenant,
               std::string _text,
               bool reject_invalid_principals)
   : text(std::move(_text)) {
index 6fa2437bcb4c2685f382e0fd9b48df7ec9a6ac2e..262aeb69149726a51588f80f561431869fe54069 100644 (file)
@@ -590,7 +590,7 @@ struct Policy {
   // when executing operations that *set* a bucket policy, but should
   // be false when reading a stored bucket policy so as not to break
   // backwards configuration.
-  Policy(CephContext* cct, const std::string& tenant,
+  Policy(CephContext* cct, const std::string* tenant,
         std::string text,
         bool reject_invalid_principals);
 
index d08fee5aa46a15f3852800c6fe113d320193009e..15bdf13c2f87a823e358822cfe6b3f1a2a6af43d 100644 (file)
@@ -326,11 +326,13 @@ static int get_obj_policy_from_attr(const DoutPrefixProvider *dpp,
 
 static boost::optional<Policy>
 get_iam_policy_from_attr(CephContext* cct,
-                         const map<string, bufferlist>& attrs,
-                         const string& tenant)
+                         const map<string, bufferlist>& attrs)
 {
   if (auto i = attrs.find(RGW_ATTR_IAM_POLICY); i != attrs.end()) {
-    return Policy(cct, tenant, i->second.to_str(), false);
+    // resource policy is not restricted to the current tenant
+    const std::string* policy_tenant = nullptr;
+
+    return Policy(cct, policy_tenant, i->second.to_str(), false);
   } else {
     return none;
   }
@@ -354,7 +356,7 @@ get_public_access_conf_from_attr(const map<string, bufferlist>& attrs)
 }
 
 static void load_inline_policy(CephContext* cct, const bufferlist& bl,
-                               const string& tenant,
+                               const string* tenant,
                                std::vector<rgw::IAM::Policy>& policies)
 {
   map<string, string> policy_map;
@@ -365,7 +367,6 @@ static void load_inline_policy(CephContext* cct, const bufferlist& bl,
 }
 
 static void load_managed_policy(CephContext* cct, const bufferlist& bl,
-                                const string& tenant,
                                 std::vector<rgw::IAM::Policy>& policies)
 {
   rgw::IAM::ManagedPolicies policy_set;
@@ -380,7 +381,7 @@ static void load_managed_policy(CephContext* cct, const bufferlist& bl,
 static void load_iam_group_policies(const DoutPrefixProvider* dpp,
                                     optional_yield y,
                                     rgw::sal::Driver* driver,
-                                    const std::string& tenant,
+                                    const std::string* tenant,
                                     std::string_view group_id,
                                     std::vector<rgw::IAM::Policy>& policies)
 {
@@ -394,7 +395,7 @@ static void load_iam_group_policies(const DoutPrefixProvider* dpp,
       load_inline_policy(cct, bl->second, tenant, policies);
     }
     if (auto bl = attrs.find(RGW_ATTR_MANAGED_POLICY); bl != attrs.end()) {
-      load_managed_policy(cct, bl->second, tenant, policies);
+      load_managed_policy(cct, bl->second, policies);
     }
   }
 }
@@ -406,18 +407,22 @@ void load_iam_identity_policies(const DoutPrefixProvider* dpp,
                                 const rgw::sal::Attrs& attrs,
                                 std::vector<rgw::IAM::Policy>& policies)
 {
+  // non-account identity policy is restricted to the current tenant
+  const std::string* policy_tenant = info.account_id.empty()
+      ? &info.user_id.tenant : nullptr;
+
   // load user policies from user attrs
   CephContext* cct = dpp->get_cct();
   if (auto bl = attrs.find(RGW_ATTR_USER_POLICY); bl != attrs.end()) {
-    load_inline_policy(cct, bl->second, info.user_id.tenant, policies);
+    load_inline_policy(cct, bl->second, policy_tenant, policies);
   }
   if (auto bl = attrs.find(RGW_ATTR_MANAGED_POLICY); bl != attrs.end()) {
-    load_managed_policy(cct, bl->second, info.user_id.tenant, policies);
+    load_managed_policy(cct, bl->second, policies);
   }
 
   // load each group and its policies
   for (const auto& id : info.group_ids) {
-    load_iam_group_policies(dpp, y, driver, info.user_id.tenant, id, policies);
+    load_iam_group_policies(dpp, y, driver, policy_tenant, id, policies);
   }
 }
 
@@ -483,7 +488,7 @@ static int read_obj_policy(const DoutPrefixProvider *dpp,
     mpobj->set_in_extra_data(true);
     object = mpobj.get();
   }
-  policy = get_iam_policy_from_attr(s->cct, bucket_attrs, bucket->get_tenant());
+  policy = get_iam_policy_from_attr(s->cct, bucket_attrs);
 
   int ret = get_obj_policy_from_attr(dpp, s->cct, driver, s->bucket_owner,
                                     acl, storage_class, object, s->yield);
@@ -703,7 +708,7 @@ int rgw_build_bucket_policies(const DoutPrefixProvider *dpp, rgw::sal::Driver* d
   }
 
   try {
-    s->iam_policy = get_iam_policy_from_attr(s->cct, s->bucket_attrs, s->bucket_tenant);
+    s->iam_policy = get_iam_policy_from_attr(s->cct, s->bucket_attrs);
   } catch (const std::exception& e) {
     ldpp_dout(dpp, 0) << "Error reading IAM Policy: " << e.what() << dendl;
 
@@ -2075,7 +2080,7 @@ int RGWGetObj::handle_user_manifest(const char *prefix, optional_yield y)
       ldpp_dout(this, 0) << "failed to read bucket policy" << dendl;
       return r;
     }
-    _bucket_policy = get_iam_policy_from_attr(s->cct, bucket_attrs, auth_tenant);
+    _bucket_policy = get_iam_policy_from_attr(s->cct, bucket_attrs);
     bucket_policy = &_bucket_policy;
     pbucket = ubucket.get();
   } else {
@@ -2210,7 +2215,7 @@ int RGWGetObj::handle_slo_manifest(bufferlist& bl, optional_yield y)
           return r;
        }
        auto _bucket_policy = get_iam_policy_from_attr(
-         s->cct, tmp_bucket->get_attrs(), auth_tenant);
+         s->cct, tmp_bucket->get_attrs());
         bucket_policy = _bucket_policy.get_ptr();
        buckets[bucket_name].swap(tmp_bucket);
         policies[bucket_name] = make_pair(bucket_acl, _bucket_policy);
@@ -5757,7 +5762,7 @@ int RGWCopyObj::verify_permission(optional_yield y)
   if (op_ret < 0) {
     return op_ret;
   }
-  auto dest_iam_policy = get_iam_policy_from_attr(s->cct, s->bucket->get_attrs(), s->bucket->get_tenant());
+  auto dest_iam_policy = get_iam_policy_from_attr(s->cct, s->bucket->get_attrs());
   /* admin request overrides permission checks */
   if (! s->auth.identity->is_admin_of(dest_policy.get_owner().id)){
     if (dest_iam_policy != boost::none || ! s->iam_identity_policies.empty() || !s->session_policies.empty()) {
@@ -7600,7 +7605,7 @@ bool RGWBulkDelete::Deleter::verify_permission(RGWBucketInfo& binfo,
     return false;
   }
 
-  auto policy = get_iam_policy_from_attr(s->cct, battrs, binfo.bucket.tenant);
+  auto policy = get_iam_policy_from_attr(s->cct, battrs);
 
   bucket_owner = bacl.get_owner();
 
@@ -7940,7 +7945,7 @@ bool RGWBulkUploadOp::handle_file_verify_permission(RGWBucketInfo& binfo,
     return false;
   }
 
-  auto policy = get_iam_policy_from_attr(s->cct, battrs, binfo.bucket.tenant);
+  auto policy = get_iam_policy_from_attr(s->cct, battrs);
 
   bucket_owner = bacl.get_owner();
   if (policy || ! s->iam_identity_policies.empty() || !s->session_policies.empty()) {
@@ -8625,7 +8630,7 @@ void RGWPutBucketPolicy::execute(optional_yield y)
 
   try {
     const Policy p(
-      s->cct, s->bucket_tenant, data.to_str(),
+      s->cct, nullptr, data.to_str(),
       s->cct->_conf.get_val<bool>("rgw_policy_reject_invalid_principals"));
     rgw::sal::Attrs attrs(s->bucket_attrs);
     if (s->bucket_access_conf &&
index 1bc98cabc89c07472e9f2d690fd78e6018630b68..217972f27c95f00fd68d30ff40a66a87bf6e52cf 100644 (file)
@@ -6,6 +6,7 @@
 #include <exception>
 #include <fstream>
 #include <iostream>
+#include <optional>
 #include <string>
 #include <string_view>
 
@@ -19,7 +20,7 @@
 #include "rgw/rgw_iam_policy.h"
 
 // Returns true on success
-bool parse(CephContext* cct, const std::string& tenant,
+bool parse(CephContext* cct, const std::string* tenant,
            const std::string& fname, std::istream& in) noexcept
 {
   bufferlist bl;
@@ -56,7 +57,7 @@ void usage(std::string_view cmdname)
 int main(int argc, const char** argv)
 {
   std::string_view cmdname = argv[0];
-  std::string tenant;
+  std::optional<std::string> tenant;
 
   auto args = argv_to_vec(argc, argv);
   if (ceph_argparse_need_usage(args)) {
@@ -82,9 +83,10 @@ int main(int argc, const char** argv)
   }
 
   bool success = true;
+  const std::string* t = tenant ? &*tenant : nullptr;
 
   if (args.empty()) {
-    success = parse(cct.get(), tenant, "(stdin)", std::cin);
+    success = parse(cct.get(), t, "(stdin)", std::cin);
   } else {
     for (const auto& file : args) {
       std::ifstream in;
@@ -93,7 +95,7 @@ int main(int argc, const char** argv)
        std::cerr << "Can't read " << file << std::endl;
        success = false;
       }
-      if (!parse(cct.get(), tenant, file, in)) {
+      if (!parse(cct.get(), t, file, in)) {
        success = false;
       }
     }
index 9819cbb53a00da6248431727f7404226b57af92a..1880111395fe0d2cb3182ba877c85c87abb29beb 100644 (file)
@@ -1282,7 +1282,7 @@ void RGWPutGroupPolicy_IAM::execute(optional_yield y)
   try {
     // validate the document
     const rgw::IAM::Policy p(
-      s->cct, s->user->get_tenant(), policy_document,
+      s->cct, nullptr, policy_document,
       s->cct->_conf.get_val<bool>("rgw_policy_reject_invalid_principals"));
   } catch (rgw::IAM::PolicyParseException& e) {
     s->err.message = std::move(e.msg);
index 9f02c5e73a82038cbc95aa038e6a389c181b1380..e22034cd367ab64c050fbc78fe687d27622e8de4 100644 (file)
@@ -89,7 +89,7 @@ std::optional<rgw::IAM::Policy> get_policy_from_text(req_state* const s,
                                                      const std::string& policy_text) {
   try {
     return rgw::IAM::Policy(
-        s->cct, s->auth.identity->get_tenant(), policy_text,
+        s->cct, nullptr, policy_text,
         s->cct->_conf.get_val<bool>("rgw_policy_reject_invalid_principals"));
   } catch (rgw::IAM::PolicyParseException& e) {
     ldout(s->cct, 1) << "failed to parse policy: '" << policy_text
index 0ee0c0ae9e5708806cd4f69fee084b332ccf194d..1b8e83b20e2c76ba7e7a7e17b2c903c0298dd407 100644 (file)
@@ -193,7 +193,7 @@ int RGWCreateRole::init_processing(optional_yield y)
   }
   try {
     const rgw::IAM::Policy p(
-      s->cct, s->user->get_tenant(), trust_policy,
+      s->cct, nullptr, trust_policy,
       s->cct->_conf.get_val<bool>("rgw_policy_reject_invalid_principals"));
   }
   catch (rgw::IAM::PolicyParseException& e) {
@@ -564,9 +564,20 @@ int RGWPutRolePolicy::init_processing(optional_yield y)
     s->err.message = "Missing required element PolicyDocument";
     return -EINVAL;
   }
+
+  int r = load_role(this, y, driver, s->owner.id, account_id,
+                    s->user->get_tenant(), role_name, role, resource,
+                    s->err.message);
+  if (r < 0) {
+    return r;
+  }
+
   try {
+    // non-account identity policy is restricted to the current tenant
+    const rgw::sal::RGWRoleInfo& info = role->get_info();
+    const std::string* policy_tenant = account_id.empty() ? &info.tenant : nullptr;
     const rgw::IAM::Policy p(
-      s->cct, s->user->get_tenant(), perm_policy,
+      s->cct, policy_tenant, perm_policy,
       s->cct->_conf.get_val<bool>("rgw_policy_reject_invalid_principals"));
   }
   catch (rgw::IAM::PolicyParseException& e) {
@@ -574,10 +585,7 @@ int RGWPutRolePolicy::init_processing(optional_yield y)
     s->err.message = e.what();
     return -ERR_MALFORMED_DOC;
   }
-
-  return load_role(this, y, driver, s->owner.id, account_id,
-                   s->user->get_tenant(), role_name, role, resource,
-                   s->err.message);
+  return 0;
 }
 
 void RGWPutRolePolicy::execute(optional_yield y)
index 111ca7c1e87b7c2aa56c1253d57ca0a7847c1893..cbb1b7de1180d7214146c8665accf0b81d7e4ba4 100644 (file)
@@ -531,7 +531,10 @@ int RGWREST_STS::verify_permission(optional_yield y)
   //Parse the policy
   //TODO - This step should be part of Role Creation
   try {
-    const rgw::IAM::Policy p(s->cct, s->user->get_tenant(), policy, false);
+    // resource policy is not restricted to the current tenant
+    const std::string* policy_tenant = nullptr;
+
+    const rgw::IAM::Policy p(s->cct, policy_tenant, policy, false);
     if (!s->principal_tags.empty()) {
       auto res = p.eval(s->env, *s->auth.identity, rgw::IAM::stsTagSession, boost::none);
       if (res != rgw::IAM::Effect::Allow) {
@@ -649,7 +652,7 @@ int RGWSTSAssumeRoleWithWebIdentity::get_params()
   if (! policy.empty()) {
     try {
       const rgw::IAM::Policy p(
-       s->cct, s->user->get_tenant(), policy,
+       s->cct, nullptr, policy,
        s->cct->_conf.get_val<bool>("rgw_policy_reject_invalid_principals"));
     }
     catch (rgw::IAM::PolicyParseException& e) {
@@ -710,7 +713,7 @@ int RGWSTSAssumeRole::get_params()
   if (! policy.empty()) {
     try {
       const rgw::IAM::Policy p(
-       s->cct, s->user->get_tenant(), policy,
+       s->cct, nullptr, policy,
        s->cct->_conf.get_val<bool>("rgw_policy_reject_invalid_principals"));
     }
     catch (rgw::IAM::PolicyParseException& e) {
index ccc86aa72e1289bdbc50518bae0b50d59b2045d0..0081bd828b90fe523ca15c551f32f013457b0a75 100644 (file)
@@ -160,8 +160,12 @@ void RGWPutUserPolicy::execute(optional_yield y)
 {
   // validate the policy document
   try {
+    // non-account identity policy is restricted to the current tenant
+    const std::string* policy_tenant = account_id.empty() ?
+        &s->user->get_tenant() : nullptr;
+
     const rgw::IAM::Policy p(
-      s->cct, s->user->get_tenant(), policy,
+      s->cct, policy_tenant, policy,
       s->cct->_conf.get_val<bool>("rgw_policy_reject_invalid_principals"));
   } catch (const rgw::IAM::PolicyParseException& e) {
     ldpp_dout(this, 5) << "failed to parse policy: " << e.what() << dendl;
index d96e965d86029c9a7a744a3bfd502bf0c1b82564..71c2f871d301e671029b28b106fd192832d01cc1 100644 (file)
@@ -220,7 +220,7 @@ public:
 TEST_F(PolicyTest, Parse1) {
   boost::optional<Policy> p;
 
-  ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant, example1, true));
+  ASSERT_NO_THROW(p = Policy(cct.get(), &arbitrary_tenant, example1, true));
   ASSERT_TRUE(p);
 
   EXPECT_EQ(p->text, example1);
@@ -248,7 +248,7 @@ TEST_F(PolicyTest, Parse1) {
 }
 
 TEST_F(PolicyTest, Eval1) {
-  auto p  = Policy(cct.get(), arbitrary_tenant, example1, true);
+  auto p  = Policy(cct.get(), &arbitrary_tenant, example1, true);
   Environment e;
 
   ARN arn1(Partition::aws, Service::s3,
@@ -271,7 +271,7 @@ TEST_F(PolicyTest, Eval1) {
 TEST_F(PolicyTest, Parse2) {
   boost::optional<Policy> p;
 
-  ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant, example2, true));
+  ASSERT_NO_THROW(p = Policy(cct.get(), &arbitrary_tenant, example2, true));
   ASSERT_TRUE(p);
 
   EXPECT_EQ(p->text, example2);
@@ -312,7 +312,7 @@ TEST_F(PolicyTest, Parse2) {
 }
 
 TEST_F(PolicyTest, Eval2) {
-  auto p  = Policy(cct.get(), arbitrary_tenant, example2, true);
+  auto p  = Policy(cct.get(), &arbitrary_tenant, example2, true);
   Environment e;
 
   auto trueacct = FakeIdentity(
@@ -352,7 +352,7 @@ TEST_F(PolicyTest, Eval2) {
 TEST_F(PolicyTest, Parse3) {
   boost::optional<Policy> p;
 
-  ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant, example3, true));
+  ASSERT_NO_THROW(p = Policy(cct.get(), &arbitrary_tenant, example3, true));
   ASSERT_TRUE(p);
 
   EXPECT_EQ(p->text, example3);
@@ -466,7 +466,7 @@ TEST_F(PolicyTest, Parse3) {
 }
 
 TEST_F(PolicyTest, Eval3) {
-  auto p  = Policy(cct.get(), arbitrary_tenant, example3, true);
+  auto p  = Policy(cct.get(), &arbitrary_tenant, example3, true);
   Environment em;
   Environment tr = { { "aws:MultiFactorAuthPresent", "true" } };
   Environment fa = { { "aws:MultiFactorAuthPresent", "false" } };
@@ -577,7 +577,7 @@ TEST_F(PolicyTest, Eval3) {
 TEST_F(PolicyTest, Parse4) {
   boost::optional<Policy> p;
 
-  ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant, example4, true));
+  ASSERT_NO_THROW(p = Policy(cct.get(), &arbitrary_tenant, example4, true));
   ASSERT_TRUE(p);
 
   EXPECT_EQ(p->text, example4);
@@ -605,7 +605,7 @@ TEST_F(PolicyTest, Parse4) {
 }
 
 TEST_F(PolicyTest, Eval4) {
-  auto p  = Policy(cct.get(), arbitrary_tenant, example4, true);
+  auto p  = Policy(cct.get(), &arbitrary_tenant, example4, true);
   Environment e;
 
   ARN arn1(Partition::aws, Service::iam,
@@ -622,7 +622,7 @@ TEST_F(PolicyTest, Eval4) {
 TEST_F(PolicyTest, Parse5) {
   boost::optional<Policy> p;
 
-  ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant, example5, true));
+  ASSERT_NO_THROW(p = Policy(cct.get(), &arbitrary_tenant, example5, true));
   ASSERT_TRUE(p);
   EXPECT_EQ(p->text, example5);
   EXPECT_EQ(p->version, Version::v2012_10_17);
@@ -650,7 +650,7 @@ TEST_F(PolicyTest, Parse5) {
 }
 
 TEST_F(PolicyTest, Eval5) {
-  auto p  = Policy(cct.get(), arbitrary_tenant, example5, true);
+  auto p  = Policy(cct.get(), &arbitrary_tenant, example5, true);
   Environment e;
 
   ARN arn1(Partition::aws, Service::iam,
@@ -672,7 +672,7 @@ TEST_F(PolicyTest, Eval5) {
 TEST_F(PolicyTest, Parse6) {
   boost::optional<Policy> p;
 
-  ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant, example6, true));
+  ASSERT_NO_THROW(p = Policy(cct.get(), &arbitrary_tenant, example6, true));
   ASSERT_TRUE(p);
   EXPECT_EQ(p->text, example6);
   EXPECT_EQ(p->version, Version::v2012_10_17);
@@ -700,7 +700,7 @@ TEST_F(PolicyTest, Parse6) {
 }
 
 TEST_F(PolicyTest, Eval6) {
-  auto p  = Policy(cct.get(), arbitrary_tenant, example6, true);
+  auto p  = Policy(cct.get(), &arbitrary_tenant, example6, true);
   Environment e;
 
   ARN arn1(Partition::aws, Service::iam,
@@ -717,7 +717,7 @@ TEST_F(PolicyTest, Eval6) {
 TEST_F(PolicyTest, Parse7) {
   boost::optional<Policy> p;
 
-  ASSERT_NO_THROW(p = Policy(cct.get(), arbitrary_tenant, example7, true));
+  ASSERT_NO_THROW(p = Policy(cct.get(), &arbitrary_tenant, example7, true));
   ASSERT_TRUE(p);
 
   EXPECT_EQ(p->text, example7);
@@ -748,7 +748,7 @@ TEST_F(PolicyTest, Parse7) {
 }
 
 TEST_F(PolicyTest, Eval7) {
-  auto p  = Policy(cct.get(), arbitrary_tenant, example7, true);
+  auto p  = Policy(cct.get(), &arbitrary_tenant, example7, true);
   Environment e;
 
   auto subacct = FakeIdentity(
@@ -1137,7 +1137,7 @@ TEST_F(IPPolicyTest, ParseIPAddress) {
   boost::optional<Policy> p;
 
   ASSERT_NO_THROW(
-    p = Policy(cct.get(), arbitrary_tenant, ip_address_full_example, true));
+    p = Policy(cct.get(), &arbitrary_tenant, ip_address_full_example, true));
   ASSERT_TRUE(p);
 
   EXPECT_EQ(p->text, ip_address_full_example);
@@ -1194,11 +1194,11 @@ TEST_F(IPPolicyTest, ParseIPAddress) {
 
 TEST_F(IPPolicyTest, EvalIPAddress) {
   auto allowp =
-    Policy(cct.get(), arbitrary_tenant, ip_address_allow_example, true);
+    Policy(cct.get(), &arbitrary_tenant, ip_address_allow_example, true);
   auto denyp =
-    Policy(cct.get(), arbitrary_tenant, ip_address_deny_example, true);
+    Policy(cct.get(), &arbitrary_tenant, ip_address_deny_example, true);
   auto fullp =
-    Policy(cct.get(), arbitrary_tenant, ip_address_full_example, true);
+    Policy(cct.get(), &arbitrary_tenant, ip_address_full_example, true);
   Environment e;
   Environment allowedIP, blocklistedIP, allowedIPv6, blocklistedIPv6;
   allowedIP.emplace("aws:SourceIp","192.168.1.2");