import allure import pytest from frostfs_testlib.cli import FrostfsCli from frostfs_testlib.reporter import get_reporter from frostfs_testlib.resources.error_patterns import OBJECT_ACCESS_DENIED, RULE_ACCESS_DENIED_OBJECT from frostfs_testlib.steps.cli.object import delete_object, get_object, get_range, get_range_hash, head_object, put_object, search_object from frostfs_testlib.storage.dataclasses.ape import Operations from frostfs_testlib.storage.dataclasses.object_size import ObjectSize from frostfs_testlib.storage.dataclasses.wallet import WalletInfo from frostfs_testlib.testing.cluster_test_base import ClusterTestBase from frostfs_testlib.testing.test_control import expect_not_raises from frostfs_testlib.utils.file_utils import generate_file from ...helpers.container_request import APE_EVERYONE_ALLOW_ALL, ContainerRequest reporter = get_reporter() REP2 = ContainerRequest("REP 2", ape_rules=APE_EVERYONE_ALLOW_ALL, short_name="REP2_allow_all_ape") @pytest.mark.ape @pytest.mark.ape_local @pytest.mark.ape_object @pytest.mark.ape_deny class TestApeLocalOverrideDeny(ClusterTestBase): @allure.title("LocalOverride: Deny to GetObject in root tenant") @pytest.mark.parametrize("container_request", [REP2], indirect=True) def test_local_override_deny_to_get_object_root( self, default_wallet: WalletInfo, frostfs_cli_on_first_node: FrostfsCli, simple_object_size: ObjectSize, container: str, ): test_file = generate_file(simple_object_size.value) with reporter.step("Create local override on first node"): frostfs_cli_on_first_node.control.add_rule( endpoint=self.cluster.storage_nodes[0].get_control_endpoint(), target_type="container", target_name=container, chain_id="denyGetObject", rule=f"deny Object.Get /{container}/*", ) with reporter.step("Put object in container on the first node"): oid = put_object(default_wallet, test_file, container, self.shell, self.cluster.storage_nodes[0].get_rpc_endpoint()) with reporter.step("Check get object from container on the first node, expected access denied error"): with pytest.raises(RuntimeError, match=RULE_ACCESS_DENIED_OBJECT): get_object(default_wallet, container, oid, self.shell, self.cluster.storage_nodes[0].get_rpc_endpoint()) with reporter.step("Check get object from container on the second node, expected allow"): with expect_not_raises(): get_object(default_wallet, container, oid, self.shell, self.cluster.storage_nodes[1].get_rpc_endpoint()) with reporter.step("Delete a rule"): frostfs_cli_on_first_node.control.remove_rule( endpoint=self.cluster.storage_nodes[0].get_control_endpoint(), target_type="container", target_name=container, chain_id="denyGetObject", ) with reporter.step("Check get object in container on the first node, expected allow"): with expect_not_raises(): get_object(default_wallet, container, oid, self.shell, self.cluster.storage_nodes[0].get_rpc_endpoint()) @allure.title("LocalOverride: Deny to PutObject in root tenant") @pytest.mark.parametrize("container_request", [REP2], indirect=True) def test_local_override_deny_to_put_object_root( self, default_wallet: WalletInfo, frostfs_cli_on_first_node: FrostfsCli, simple_object_size: ObjectSize, container: str, ): test_file = generate_file(simple_object_size.value) with reporter.step("Create local override on first node"): frostfs_cli_on_first_node.control.add_rule( endpoint=self.cluster.storage_nodes[0].get_control_endpoint(), target_type="container", target_name=container, chain_id="denyPutObject", rule=f"deny Object.Put /{container}/*", ) with reporter.step("Check put object from container on the first node, expected access denied error"): with pytest.raises(RuntimeError, match=OBJECT_ACCESS_DENIED): put_object(default_wallet, test_file, container, self.shell, self.cluster.storage_nodes[0].get_rpc_endpoint()) with reporter.step("Check put object from container on the second node, expected allow"): with expect_not_raises(): put_object( default_wallet, test_file, container, self.shell, self.cluster.storage_nodes[1].get_rpc_endpoint(), copies_number=3 ) with reporter.step("Delete a rule"): frostfs_cli_on_first_node.control.remove_rule( endpoint=self.cluster.storage_nodes[0].get_control_endpoint(), target_type="container", target_name=container, chain_id="denyPutObject", ) with reporter.step("Check get object in container on the first node, expected allow"): with expect_not_raises(): put_object(default_wallet, test_file, container, self.shell, self.cluster.storage_nodes[0].get_rpc_endpoint()) @allure.title("LocalOverride: Deny to HeadObject in root tenant") @pytest.mark.parametrize("container_request", [REP2], indirect=True) def test_local_override_deny_to_head_object_root( self, default_wallet: WalletInfo, frostfs_cli_on_first_node: FrostfsCli, simple_object_size: ObjectSize, container: str, ): test_file = generate_file(simple_object_size.value) with reporter.step("Create local override on first node"): frostfs_cli_on_first_node.control.add_rule( endpoint=self.cluster.storage_nodes[0].get_control_endpoint(), target_type="container", target_name=container, chain_id="denyHeadObject", rule=f"deny Object.Head /{container}/*", ) with reporter.step("Put object in container on the first node"): oid = put_object(default_wallet, test_file, container, self.shell, self.cluster.storage_nodes[0].get_rpc_endpoint()) with reporter.step("Check head object from container on the first node, expected access denied error"): with pytest.raises(RuntimeError, match=RULE_ACCESS_DENIED_OBJECT): head_object(default_wallet, container, oid, self.shell, self.cluster.storage_nodes[0].get_rpc_endpoint()) with reporter.step("Check head object from container on the second node, expected allow"): with expect_not_raises(): head_object(default_wallet, container, oid, self.shell, self.cluster.storage_nodes[1].get_rpc_endpoint()) with reporter.step("Delete a rule"): frostfs_cli_on_first_node.control.remove_rule( endpoint=self.cluster.storage_nodes[0].get_control_endpoint(), target_type="container", target_name=container, chain_id="denyHeadObject", ) with reporter.step("Check head object in container on the first node, expected allow"): with expect_not_raises(): head_object(default_wallet, container, oid, self.shell, self.cluster.storage_nodes[0].get_rpc_endpoint()) @allure.title("LocalOverride: Deny to SearchObject in root tenant") @pytest.mark.parametrize("container_request", [REP2], indirect=True) def test_local_override_deny_to_search_object_root( self, default_wallet: WalletInfo, frostfs_cli_on_first_node: FrostfsCli, container: str, ): with reporter.step("Create local override on first node"): frostfs_cli_on_first_node.control.add_rule( endpoint=self.cluster.storage_nodes[0].get_control_endpoint(), target_type="container", target_name=container, chain_id="denySearchObject", rule=f"deny Object.Search /{container}/*", ) with reporter.step("Check search object from container on the first node, expected access denied error"): with pytest.raises(RuntimeError, match=RULE_ACCESS_DENIED_OBJECT.format(operation=Operations.SEARCH_OBJECT)): search_object(default_wallet, container, self.shell, self.cluster.storage_nodes[0].get_rpc_endpoint()) with reporter.step("Check search object from container on the second node, expected allow"): with expect_not_raises(): search_object(default_wallet, container, self.shell, self.cluster.storage_nodes[1].get_rpc_endpoint()) with reporter.step("Delete a rule"): frostfs_cli_on_first_node.control.remove_rule( endpoint=self.cluster.storage_nodes[0].get_control_endpoint(), target_type="container", target_name=container, chain_id="denySearchObject", ) with reporter.step("Check search object in container on the first node, expected allow"): with expect_not_raises(): search_object(default_wallet, container, self.shell, self.cluster.storage_nodes[0].get_rpc_endpoint()) @allure.title("LocalOverride: Deny to RangeObject in root tenant") @pytest.mark.parametrize("container_request", [REP2], indirect=True) def test_local_override_deny_to_range_object_root( self, default_wallet: WalletInfo, frostfs_cli_on_first_node: FrostfsCli, simple_object_size: ObjectSize, container: str, ): test_file = generate_file(simple_object_size.value) with reporter.step("Create local override on first node"): frostfs_cli_on_first_node.control.add_rule( endpoint=self.cluster.storage_nodes[0].get_control_endpoint(), target_type="container", target_name=container, chain_id="denyRangeObject", rule=f"deny Object.Range /{container}/*", ) with reporter.step("Put object in container on the first node"): oid = put_object(default_wallet, test_file, container, self.shell, self.cluster.storage_nodes[0].get_rpc_endpoint()) with reporter.step("Check range object from container on the first node, expected access denied error"): with pytest.raises(RuntimeError, match=RULE_ACCESS_DENIED_OBJECT.format(operation=Operations.RANGE_OBJECT)): get_range(default_wallet, container, oid, "0:10", self.shell, self.cluster.storage_nodes[0].get_rpc_endpoint()) with reporter.step("Check get range object from container on the second node, expected allow"): with expect_not_raises(): get_range(default_wallet, container, oid, "0:10", self.shell, self.cluster.storage_nodes[1].get_rpc_endpoint()) with reporter.step("Delete a rule"): frostfs_cli_on_first_node.control.remove_rule( endpoint=self.cluster.storage_nodes[0].get_control_endpoint(), target_type="container", target_name=container, chain_id="denyRangeObject", ) with reporter.step("Check get range object in container on the first node, expected allow"): with expect_not_raises(): get_range(default_wallet, container, oid, "0:10", self.shell, self.cluster.storage_nodes[0].get_rpc_endpoint()) @allure.title("LocalOverride: Deny to HashObject in root tenant") @pytest.mark.parametrize("container_request", [REP2], indirect=True) def test_local_override_deny_to_hash_object_root( self, default_wallet: WalletInfo, frostfs_cli_on_first_node: FrostfsCli, simple_object_size: ObjectSize, container: str, ): test_file = generate_file(simple_object_size.value) with reporter.step("Create local override on first node"): frostfs_cli_on_first_node.control.add_rule( endpoint=self.cluster.storage_nodes[0].get_control_endpoint(), target_type="container", target_name=container, chain_id="denyHashObject", rule=f"deny Object.Hash /{container}/*", ) with reporter.step("Put object in container on the first node"): oid = put_object(default_wallet, test_file, container, self.shell, self.cluster.storage_nodes[0].get_rpc_endpoint()) with reporter.step("Check get range hash object from container on the first node, expected access denied error"): with pytest.raises(RuntimeError, match=RULE_ACCESS_DENIED_OBJECT.format(operation=Operations.HASH_OBJECT)): get_range_hash(default_wallet, container, oid, "0:10", self.shell, self.cluster.storage_nodes[0].get_rpc_endpoint()) with reporter.step("Check get range hash object from container on the second node, expected allow"): with expect_not_raises(): get_range_hash(default_wallet, container, oid, "0:10", self.shell, self.cluster.storage_nodes[1].get_rpc_endpoint()) with reporter.step("Delete a rule"): frostfs_cli_on_first_node.control.remove_rule( endpoint=self.cluster.storage_nodes[0].get_control_endpoint(), target_type="container", target_name=container, chain_id="denyHashObject", ) with reporter.step("Check get range hash object in container on the first node, expected allow"): with expect_not_raises(): get_range_hash(default_wallet, container, oid, "0:10", self.shell, self.cluster.storage_nodes[0].get_rpc_endpoint()) @allure.title("LocalOverride: Deny to DeleteObject in root tenant") @pytest.mark.parametrize("container_request", [REP2], indirect=True) def test_local_override_deny_to_delete_object_root( self, default_wallet: WalletInfo, frostfs_cli_on_first_node: FrostfsCli, simple_object_size: ObjectSize, container: str, ): test_file = generate_file(simple_object_size.value) with reporter.step("Create local override on first node"): frostfs_cli_on_first_node.control.add_rule( endpoint=self.cluster.storage_nodes[0].get_control_endpoint(), target_type="container", target_name=container, chain_id="denyDeleteObject", rule=f"deny Object.Delete /{container}/*", ) with reporter.step("Put objects in container on the first node"): oid_1 = put_object(default_wallet, test_file, container, self.shell, self.cluster.storage_nodes[0].get_rpc_endpoint()) oid_2 = put_object(default_wallet, test_file, container, self.shell, self.cluster.storage_nodes[0].get_rpc_endpoint()) with reporter.step("Search object in container on the first node"): search_object_in_container_1 = search_object( default_wallet, container, self.shell, self.cluster.storage_nodes[0].get_rpc_endpoint() ) assert oid_1 in search_object_in_container_1, f"Object {oid_1} was not found" assert oid_2 in search_object_in_container_1, f"Object {oid_2} was not found" with reporter.step("Search object from container on the second node"): search_object_in_container_2 = search_object( default_wallet, container, self.shell, self.cluster.storage_nodes[1].get_rpc_endpoint() ) assert oid_1 in search_object_in_container_2, f"Object {oid_1} was not found" assert oid_2 in search_object_in_container_2, f"Object {oid_2} was not found" with reporter.step("Check delete object from container on the first node, expected access denied error"): with pytest.raises(RuntimeError, match=RULE_ACCESS_DENIED_OBJECT): delete_object(default_wallet, container, oid_1, self.shell, self.cluster.storage_nodes[0].get_rpc_endpoint()) with reporter.step("Check delete object from container on the second node, expected allow"): with expect_not_raises(): delete_object(default_wallet, container, oid_2, self.shell, self.cluster.storage_nodes[1].get_rpc_endpoint()) with reporter.step("Delete a rule"): frostfs_cli_on_first_node.control.remove_rule( endpoint=self.cluster.storage_nodes[0].get_control_endpoint(), target_type="container", target_name=container, chain_id="denyDeleteObject", ) with reporter.step("Check delete object in container on the first node, expected allow"): with expect_not_raises(): delete_object(default_wallet, container, oid_1, self.shell, self.cluster.storage_nodes[0].get_rpc_endpoint())