]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw/iam: add get_managed_policy() factory function
authorCasey Bodley <cbodley@redhat.com>
Thu, 1 Feb 2024 19:58:22 +0000 (14:58 -0500)
committerCasey Bodley <cbodley@redhat.com>
Fri, 12 Apr 2024 19:34:28 +0000 (15:34 -0400)
add definitions for the following managed policy ARNs:

* arn:aws:iam::aws:policy/IAMFullAccess
* arn:aws:iam::aws:policy/IAMReadOnlyAccess
* arn:aws:iam::aws:policy/AmazonSNSFullAccess
* arn:aws:iam::aws:policy/AmazonSNSReadOnlyAccess
* arn:aws:iam::aws:policy/AmazonS3FullAccess
* arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess

factory function get_managed_policy() returns a parsed Policy for the
requested ARN if available

Signed-off-by: Casey Bodley <cbodley@redhat.com>
(cherry picked from commit ccb6c38d8ea28d337430efc6e660b24896e75f17)

src/rgw/CMakeLists.txt
src/rgw/rgw_iam_managed_policy.cc [new file with mode: 0644]
src/rgw/rgw_iam_managed_policy.h [new file with mode: 0644]
src/test/rgw/test_rgw_iam_policy.cc

index 499fb61c0fe6a512b9b92a5f39003e25b737a88a..ca7bf2b104fc89643612559c50497138eeca13a7 100644 (file)
@@ -130,6 +130,7 @@ set(librgw_common_srcs
   rgw_crypt.cc
   rgw_crypt_sanitize.cc
   rgw_iam_policy.cc
+  rgw_iam_managed_policy.cc
   rgw_rest_user_policy.cc
   rgw_zone.cc
   rgw_sts.cc
diff --git a/src/rgw/rgw_iam_managed_policy.cc b/src/rgw/rgw_iam_managed_policy.cc
new file mode 100644 (file)
index 0000000..3034832
--- /dev/null
@@ -0,0 +1,177 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab ft=cpp
+
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright contributors to the Ceph project
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#include "rgw_iam_managed_policy.h"
+#include "rgw_iam_policy.h"
+
+namespace rgw::IAM {
+
+// Type: AWS managed policy
+// Creation time: February 06, 2015, 18:40 UTC
+// Edited time: June 21, 2019, 19:40 UTC
+// ARN: arn:aws:iam::aws:policy/IAMFullAccess
+// Policy version: v2 (default)
+static constexpr std::string_view IAMFullAccess = R"(
+{
+  "Version" : "2012-10-17",
+  "Statement" : [
+    {
+      "Effect" : "Allow",
+      "Action" : [
+        "iam:*",
+        "organizations:DescribeAccount",
+        "organizations:DescribeOrganization",
+        "organizations:DescribeOrganizationalUnit",
+        "organizations:DescribePolicy",
+        "organizations:ListChildren",
+        "organizations:ListParents",
+        "organizations:ListPoliciesForTarget",
+        "organizations:ListRoots",
+        "organizations:ListPolicies",
+        "organizations:ListTargetsForPolicy"
+      ],
+      "Resource" : "*"
+    }
+  ]
+})";
+
+// Type: AWS managed policy
+// Creation time: February 06, 2015, 18:40 UTC
+// Edited time: January 25, 2018, 19:11 UTC
+// ARN: arn:aws:iam::aws:policy/IAMReadOnlyAccess
+// Policy version: v4 (default)
+static constexpr std::string_view IAMReadOnlyAccess = R"(
+{
+  "Version" : "2012-10-17",
+  "Statement" : [
+    {
+      "Effect" : "Allow",
+      "Action" : [
+        "iam:GenerateCredentialReport",
+        "iam:GenerateServiceLastAccessedDetails",
+        "iam:Get*",
+        "iam:List*",
+        "iam:SimulateCustomPolicy",
+        "iam:SimulatePrincipalPolicy"
+      ],
+      "Resource" : "*"
+    }
+  ]
+})";
+
+// Type: AWS managed policy
+// Creation time: February 06, 2015, 18:41 UTC
+// Edited time: February 06, 2015, 18:41 UTC
+// ARN: arn:aws:iam::aws:policy/AmazonSNSFullAccess
+// Policy version: v1 (default)
+static constexpr std::string_view AmazonSNSFullAccess = R"(
+{
+  "Version" : "2012-10-17",
+  "Statement" : [
+    {
+      "Action" : [
+        "sns:*"
+      ],
+      "Effect" : "Allow",
+      "Resource" : "*"
+    }
+  ]
+})";
+
+// Type: AWS managed policy
+// Creation time: February 06, 2015, 18:41 UTC
+// Edited time: February 06, 2015, 18:41 UTC
+// ARN: arn:aws:iam::aws:policy/AmazonSNSReadOnlyAccess
+// Policy version: v1 (default)
+static constexpr std::string_view AmazonSNSReadOnlyAccess = R"(
+{
+  "Version" : "2012-10-17",
+  "Statement" : [
+    {
+      "Effect" : "Allow",
+      "Action" : [
+        "sns:GetTopicAttributes",
+        "sns:List*"
+      ],
+      "Resource" : "*"
+    }
+  ]
+})";
+
+// Type: AWS managed policy
+// Creation time: February 06, 2015, 18:40 UTC
+// Edited time: September 27, 2021, 20:16 UTC
+// ARN: arn:aws:iam::aws:policy/AmazonS3FullAccess
+// Policy version: v2 (default)
+static constexpr std::string_view AmazonS3FullAccess = R"(
+{
+  "Version" : "2012-10-17",
+  "Statement" : [
+    {
+      "Effect" : "Allow",
+      "Action" : [
+        "s3:*",
+        "s3-object-lambda:*"
+      ],
+      "Resource" : "*"
+    }
+  ]
+})";
+
+// Type: AWS managed policy
+// Creation time: February 06, 2015, 18:40 UTC
+// Edited time: August 10, 2023, 21:31 UTC
+// ARN: arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
+// Policy version: v3 (default)
+static constexpr std::string_view AmazonS3ReadOnlyAccess = R"(
+{
+  "Version" : "2012-10-17",
+  "Statement" : [
+    {
+      "Effect" : "Allow",
+      "Action" : [
+        "s3:Get*",
+        "s3:List*",
+        "s3:Describe*",
+        "s3-object-lambda:Get*",
+        "s3-object-lambda:List*"
+      ],
+      "Resource" : "*"
+    }
+  ]
+})";
+
+auto get_managed_policy(CephContext* cct, std::string_view arn)
+    -> std::optional<Policy>
+{
+  const std::string tenant; // empty tenant
+  constexpr bool reject = false; // reject_invalid_principals
+  if (arn == "arn:aws:iam::aws:policy/IAMFullAccess") {
+    return Policy{cct, tenant, std::string{IAMFullAccess}, reject};
+  } else if (arn == "arn:aws:iam::aws:policy/IAMReadOnlyAccess") {
+    return Policy{cct, tenant, std::string{IAMReadOnlyAccess}, reject};
+  } else if (arn == "arn:aws:iam::aws:policy/AmazonSNSFullAccess") {
+    return Policy{cct, tenant, std::string{AmazonSNSFullAccess}, reject};
+  } else if (arn == "arn:aws:iam::aws:policy/AmazonSNSReadOnlyAccess") {
+    return Policy{cct, tenant, std::string{AmazonSNSReadOnlyAccess}, reject};
+  } else if (arn == "arn:aws:iam::aws:policy/AmazonS3FullAccess") {
+    return Policy{cct, tenant, std::string{AmazonS3FullAccess}, reject};
+  } else if (arn == "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess") {
+    return Policy{cct, tenant, std::string{AmazonS3ReadOnlyAccess}, reject};
+  }
+  return {};
+}
+
+} // namespace rgw::IAM
diff --git a/src/rgw/rgw_iam_managed_policy.h b/src/rgw/rgw_iam_managed_policy.h
new file mode 100644 (file)
index 0000000..35a5cef
--- /dev/null
@@ -0,0 +1,30 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab ft=cpp
+
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright contributors to the Ceph project
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#pragma once
+
+#include <optional>
+#include <string_view>
+#include "common/ceph_context.h"
+
+namespace rgw::IAM {
+
+struct Policy;
+
+/// Return a managed policy by ARN.
+auto get_managed_policy(CephContext* cct, std::string_view arn)
+    -> std::optional<Policy>;
+
+} // namespace rgw::IAM
index 241263be749bd294f85548095ebfce7cf3d5a7a2..3ecbb782e5ce5feb1a589b3be2c40145d749bff0 100644 (file)
@@ -12,6 +12,8 @@
  *
  */
 
+#include "rgw_iam_policy.h"
+
 #include <string>
 
 #include <boost/intrusive_ptr.hpp>
@@ -26,7 +28,7 @@
 #include "global/global_init.h"
 #include "rgw_auth.h"
 #include "rgw_auth_registry.h"
-#include "rgw_iam_policy.h"
+#include "rgw_iam_managed_policy.h"
 #include "rgw_op.h"
 #include "rgw_process_env.h"
 #include "rgw_sal_rados.h"
@@ -128,6 +130,8 @@ using rgw::IAM::snsAllValue;
 using rgw::IAM::organizationsAllValue;
 using rgw::IAM::allValue;
 
+using rgw::IAM::get_managed_policy;
+
 class FakeIdentity : public Identity {
   const Principal id;
 public:
@@ -762,6 +766,139 @@ TEST_F(PolicyTest, Eval7) {
            Effect::Pass);
 }
 
+
+class ManagedPolicyTest : public ::testing::Test {
+protected:
+  intrusive_ptr<CephContext> cct;
+public:
+  ManagedPolicyTest() : cct(new CephContext(CEPH_ENTITY_TYPE_CLIENT)) {}
+};
+
+TEST_F(ManagedPolicyTest, IAMFullAccess)
+{
+  auto p = get_managed_policy(cct.get(), "arn:aws:iam::aws:policy/IAMFullAccess");
+  ASSERT_TRUE(p);
+
+  Action_t act = iamAllValue | organizationsAllValue;
+  act[iamAll] = 1;
+  act[organizationsAll] = 1;
+  EXPECT_EQ(act, p->statements[0].action);
+}
+
+TEST_F(ManagedPolicyTest, IAMReadOnlyAccess)
+{
+  auto p = get_managed_policy(cct.get(), "arn:aws:iam::aws:policy/IAMReadOnlyAccess");
+  ASSERT_TRUE(p);
+
+  Action_t act;
+  act[iamGenerateCredentialReport] = 1;
+  act[iamGenerateServiceLastAccessedDetails] = 1;
+  act[iamGetUserPolicy] = 1;
+  act[iamGetRole] = 1;
+  act[iamGetRolePolicy] = 1;
+  act[iamGetOIDCProvider] = 1;
+  act[iamGetUser] = 1;
+  act[iamListUserPolicies] = 1;
+  act[iamListRoles] = 1;
+  act[iamListRolePolicies] = 1;
+  act[iamListOIDCProviders] = 1;
+  act[iamListRoleTags] = 1;
+  act[iamListUsers] = 1;
+  act[iamListAccessKeys] = 1;
+  act[iamSimulateCustomPolicy] = 1;
+  act[iamSimulatePrincipalPolicy] = 1;
+
+  EXPECT_EQ(act, p->statements[0].action);
+}
+
+TEST_F(ManagedPolicyTest, AmazonSNSFullAccess)
+{
+  auto p = get_managed_policy(cct.get(), "arn:aws:iam::aws:policy/AmazonSNSFullAccess");
+  ASSERT_TRUE(p);
+
+  Action_t act = snsAllValue;
+  act[snsAll] = 1;
+  EXPECT_EQ(act, p->statements[0].action);
+}
+
+TEST_F(ManagedPolicyTest, AmazonSNSReadOnlyAccess)
+{
+  auto p = get_managed_policy(cct.get(), "arn:aws:iam::aws:policy/AmazonSNSReadOnlyAccess");
+  ASSERT_TRUE(p);
+
+  Action_t act;
+  // sns:GetTopicAttributes
+  act[snsGetTopicAttributes] = 1;
+  // sns:List*
+  act[snsListTopics] = 1;
+
+  EXPECT_EQ(act, p->statements[0].action);
+}
+
+TEST_F(ManagedPolicyTest, AmazonS3FullAccess)
+{
+  auto p = get_managed_policy(cct.get(), "arn:aws:iam::aws:policy/AmazonS3FullAccess");
+  ASSERT_TRUE(p);
+
+  Action_t act = s3AllValue | s3objectlambdaAllValue;
+  act[s3All] = 1;
+  act[s3objectlambdaAll] = 1;
+  EXPECT_EQ(act, p->statements[0].action);
+}
+
+TEST_F(ManagedPolicyTest, AmazonS3ReadOnlyAccess)
+{
+  auto p = get_managed_policy(cct.get(), "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess");
+  ASSERT_TRUE(p);
+
+  Action_t act;
+  // s3:Get*
+  act[s3GetObject] = 1;
+  act[s3GetObjectVersion] = 1;
+  act[s3GetObjectAcl] = 1;
+  act[s3GetObjectVersionAcl] = 1;
+  act[s3GetObjectTorrent] = 1;
+  act[s3GetObjectVersionTorrent] = 1;
+  act[s3GetAccelerateConfiguration] = 1;
+  act[s3GetBucketAcl] = 1;
+  act[s3GetBucketOwnershipControls] = 1;
+  act[s3GetBucketCORS] = 1;
+  act[s3GetBucketVersioning] = 1;
+  act[s3GetBucketRequestPayment] = 1;
+  act[s3GetBucketLocation] = 1;
+  act[s3GetBucketPolicy] = 1;
+  act[s3GetBucketNotification] = 1;
+  act[s3GetBucketLogging] = 1;
+  act[s3GetBucketTagging] = 1;
+  act[s3GetBucketWebsite] = 1;
+  act[s3GetLifecycleConfiguration] = 1;
+  act[s3GetReplicationConfiguration] = 1;
+  act[s3GetObjectTagging] = 1;
+  act[s3GetObjectVersionTagging] = 1;
+  act[s3GetBucketObjectLockConfiguration] = 1;
+  act[s3GetObjectRetention] = 1;
+  act[s3GetObjectLegalHold] = 1;
+  act[s3GetBucketPolicyStatus] = 1;
+  act[s3GetPublicAccessBlock] = 1;
+  act[s3GetBucketPublicAccessBlock] = 1;
+  act[s3GetBucketEncryption] = 1;
+  // s3:List*
+  act[s3ListMultipartUploadParts] = 1;
+  act[s3ListBucket] = 1;
+  act[s3ListBucketVersions] = 1;
+  act[s3ListAllMyBuckets] = 1;
+  act[s3ListBucketMultipartUploads] = 1;
+  // s3:Describe*
+  act[s3DescribeJob] = 1;
+  // s3-object-lambda:Get*
+  act[s3objectlambdaGetObject] = 1;
+  // s3-object-lambda:List*
+  act[s3objectlambdaListBucket] = 1;
+  act[s3objectlambdaAll] = 1;
+
+  EXPECT_EQ(act, p->statements[0].action);
+}
+
 const string PolicyTest::arbitrary_tenant = "arbitrary_tenant";
 string PolicyTest::example1 = R"(
 {