diff --git a/scripts/application_recovery_resources.py b/scripts/application_recovery_resources.py index a28ac31..e7aec97 100644 --- a/scripts/application_recovery_resources.py +++ b/scripts/application_recovery_resources.py @@ -119,8 +119,16 @@ def policy(bucket, prefix, apps, owner): statements.append(statement(role + "Objects", principal, actions, bucket + "/" + prefix + "/*")) statements.append(statement(role + "List", principal, ["s3:ListBucket", "s3:ListBucketVersions"], bucket, {"StringLike": {"s3:prefix": [prefix + "/", prefix + "/*"]}})) - statements.append(statement(role + "Metadata", principal, - ["s3:GetBucketLocation", "s3:GetBucketVersioning", "s3:GetLifecycleConfiguration"], bucket)) + if prefix != "archives": + statements.append(statement(role + "Metadata", principal, + ["s3:GetBucketLocation", "s3:GetBucketVersioning", "s3:GetLifecycleConfiguration"], bucket)) + if prefix == "archives": + # Scaleway accepts at most ten statements per policy. These metadata + # rights are identical for all three callers; sharing their statement + # changes no effective permission or prefix restriction. + statements.append(statement("ArchiveMetadata", ["application_id:" + apps[r] + for r in ("reader", "custodian", "publisher")], + ["s3:GetBucketLocation", "s3:GetBucketVersioning", "s3:GetLifecycleConfiguration"], bucket)) return {"Version": "2023-04-17", "Id": "coulomb-independent-recovery", "Statement": statements} diff --git a/tests/test_application_recovery_resources.py b/tests/test_application_recovery_resources.py index a864a96..7a93a11 100644 --- a/tests/test_application_recovery_resources.py +++ b/tests/test_application_recovery_resources.py @@ -61,6 +61,14 @@ class ResourcesTests(unittest.TestCase): self.assertEqual(p["Statement"][0]["Principal"], {"SCW": "user_id:o"}) self.assertTrue(all(s["Effect"] == "Allow" for s in p["Statement"])) + def test_archive_policy_respects_native_ten_statement_limit(self): + p = m.policy("b", "archives", self.apps, "o") + self.assertLessEqual(len(p["Statement"]), 10) + shared = next(s for s in p["Statement"] if s["Sid"] == "ArchiveMetadata") + self.assertEqual(set(shared["Principal"]["SCW"]), + {"application_id:" + self.apps[r] for r in ("reader", "custodian", "publisher")}) + self.assertTrue(all(a.startswith("s3:Get") and "Object" not in a for a in shared["Action"])) + if __name__ == "__main__": unittest.main()