Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add checks for lifetime, expire_at flags #621

Merged
merged 7 commits into from
Sep 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions pytest_tests/steps/session_token.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ def create_session_token(
wallet_path: str,
wallet_password: str,
rpc_endpoint: str,
lifetime: Optional[int] = None,
expire_at: Optional[int] = None
) -> str:
"""
Create session token for an object.
Expand All @@ -256,6 +258,8 @@ def create_session_token(
wallet=wallet_path,
wallet_password=wallet_password,
out=session_token,
lifetime=lifetime,
expire_at=expire_at
)
return session_token

Expand Down
10 changes: 7 additions & 3 deletions pytest_tests/testsuites/acl/storage_group/test_storagegroup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
import allure
import pytest
from cluster_test_base import ClusterTestBase
from common import ASSETS_DIR, TEST_FILES_DIR, FREE_STORAGE, WALLET_PASS
from common import ASSETS_DIR, FREE_STORAGE, TEST_FILES_DIR, WALLET_PASS
from epoch import get_epoch
from file_helper import generate_file
from grpc_responses import OBJECT_ACCESS_DENIED, OBJECT_NOT_FOUND
from neofs_testlib.utils.wallet import init_wallet
Expand Down Expand Up @@ -233,7 +234,8 @@ def test_storagegroup_bearer_allow(self, object_size, max_object_size):
)

@allure.title("Test to check Storage Group lifetime")
def test_storagegroup_lifetime(self, object_size):
@pytest.mark.parametrize("expiration_flag", ["lifetime", "expire_at"])
def test_storagegroup_lifetime(self, object_size, expiration_flag, cluster):
cid = create_container(
self.main_wallet, shell=self.shell, endpoint=self.cluster.default_rpc_endpoint
)
Expand All @@ -242,13 +244,15 @@ def test_storagegroup_lifetime(self, object_size):
self.main_wallet, file_path, cid, shell=self.shell, cluster=self.cluster
)
objects = [oid]
current_epoch = get_epoch(self.shell, cluster)
storage_group = put_storagegroup(
self.shell,
self.cluster.default_rpc_endpoint,
self.main_wallet,
cid,
objects,
lifetime=1,
lifetime=1 if expiration_flag == "lifetime" else None,
expire_at=current_epoch + 1 if expiration_flag == "expire_at" else None,
)
with allure.step("Tick two epochs"):
for _ in range(2):
Expand Down
81 changes: 81 additions & 0 deletions pytest_tests/testsuites/acl/test_bearer.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import os
import uuid

import allure
import pytest
from cluster_test_base import ClusterTestBase
from common import ASSETS_DIR, TEST_FILES_DIR, WALLET_PASS
from epoch import get_epoch
from neofs_testlib.utils.wallet import get_last_address_from_wallet
from python_keywords.acl import (
EACLAccess,
EACLOperation,
EACLRole,
EACLRule,
create_bearer_token,
create_eacl,
form_bearertoken_file,
set_eacl,
sign_bearer,
wait_for_cache_expired,
)
from python_keywords.container_access import (
Expand Down Expand Up @@ -229,3 +237,76 @@ def test_bearer_token_compound_operations(self, wallets, eacl_container_with_obj
shell=self.shell,
cluster=self.cluster,
)

@pytest.mark.skip(reason="https://github.com/nspcc-dev/neofs-api/issues/273")
@pytest.mark.skip(reason="https://github.com/nspcc-dev/neofs-node/issues/2538")
@pytest.mark.nspcc_dev__neofs_api__issue_273
@pytest.mark.nspcc_dev__neofs_node__issue_2538
@pytest.mark.parametrize("expiration_flag", ["lifetime", "expire_at"])
def test_bearer_token_expiration(self, wallets, eacl_container_with_objects, expiration_flag):
current_epoch = get_epoch(self.shell, self.cluster)
self.tick_epochs(1)
cid, objects_oids, file_path = eacl_container_with_objects
user_wallet = wallets.get_wallet()

with allure.step("Create and sign bearer token via cli"):
eacl = [
EACLRule(access=EACLAccess.ALLOW, role=EACLRole.USER, operation=op)
for op in EACLOperation
]

path_to_bearer = os.path.join(
os.getcwd(), ASSETS_DIR, TEST_FILES_DIR, f"bearer_token_{str(uuid.uuid4())}"
)

create_bearer_token(
self.shell,
issued_at=1,
not_valid_before=1,
owner=get_last_address_from_wallet(user_wallet.wallet_path, WALLET_PASS),
out=path_to_bearer,
rpc_endpoint=self.cluster.default_rpc_endpoint,
eacl=create_eacl(cid, eacl, shell=self.shell),
lifetime=1 if expiration_flag == "lifetime" else None,
expire_at=current_epoch + 2 if expiration_flag == "expire_at" else None,
)

sign_bearer(
shell=self.shell,
wallet_path=user_wallet.wallet_path,
eacl_rules_file_from=path_to_bearer,
eacl_rules_file_to=path_to_bearer,
json=True,
)

self.tick_epochs(1)

with allure.step(
f"Check {EACLRole.USER.value} with token has access to all operations with container"
):
check_full_access_to_container(
user_wallet.wallet_path,
cid,
objects_oids.pop(),
file_path,
bearer=path_to_bearer,
wallet_config=user_wallet.config_path,
shell=self.shell,
cluster=self.cluster,
)

self.tick_epochs(1)

with allure.step(
f"Check {EACLRole.USER.value} has no access to all operations with container"
):
check_no_access_to_container(
user_wallet.wallet_path,
cid,
objects_oids.pop(),
file_path,
bearer=path_to_bearer,
wallet_config=user_wallet.config_path,
shell=self.shell,
cluster=self.cluster,
)
21 changes: 15 additions & 6 deletions pytest_tests/testsuites/object/test_object_lifetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import allure
import pytest
from epoch import get_epoch, tick_epoch
from epoch import get_epoch
from file_helper import generate_file, get_file_hash
from grpc_responses import OBJECT_NOT_FOUND
from pytest import FixtureRequest
Expand All @@ -19,12 +19,15 @@
class TestObjectApiLifetime(ClusterTestBase):
@allure.title("Test object life time")
@pytest.mark.parametrize(
"object_size",
[pytest.lazy_fixture("simple_object_size"), pytest.lazy_fixture("complex_object_size")],
ids=["simple object", "complex object"],
"object_size,expiration_flag",
[
(pytest.lazy_fixture("simple_object_size"), "lifetime"),
(pytest.lazy_fixture("complex_object_size"), "expire_at"),
],
ids=["simple object, lifetime", "complex object, expire_at"],
)
def test_object_api_lifetime(
self, default_wallet: str, request: FixtureRequest, object_size: int
self, default_wallet: str, request: FixtureRequest, object_size: int, expiration_flag: str
):
"""
Test object deleted after expiration epoch.
Expand All @@ -41,7 +44,13 @@ def test_object_api_lifetime(
epoch = get_epoch(self.shell, self.cluster)

oid = put_object_to_random_node(
wallet, file_path, cid, self.shell, self.cluster, expire_at=epoch + 1
wallet,
file_path,
cid,
self.shell,
self.cluster,
expire_at=epoch + 1 if expiration_flag == "expire_at" else None,
lifetime=1 if expiration_flag == "lifetime" else None,
)
got_file = get_object_from_random_node(wallet, cid, oid, self.shell, self.cluster)
assert get_file_hash(got_file) == file_hash
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
import pytest
from cluster_test_base import ClusterTestBase
from common import WALLET_PASS
from epoch import get_epoch
from file_helper import generate_file
from grpc_responses import SESSION_NOT_FOUND
from grpc_responses import EXPIRED_SESSION_TOKEN, SESSION_NOT_FOUND
from neofs_testlib.utils.wallet import get_last_address_from_wallet
from python_keywords.container import create_container
from python_keywords.neofs_verbs import delete_object, put_object, put_object_to_random_node
Expand Down Expand Up @@ -144,3 +145,73 @@ def test_object_session_token(self, default_wallet, object_size):
endpoint=non_container_node.get_rpc_endpoint(),
session=session_token,
)

@allure.title("Verify session token expiration flags")
@pytest.mark.skip(reason="https://github.com/nspcc-dev/neofs-node/issues/2539")
@pytest.mark.nspcc_dev__neofs_node__issue_2539
@pytest.mark.parametrize("expiration_flag", ["lifetime", "expire_at"])
def test_session_token_expiration_flags(
self, default_wallet, simple_object_size, expiration_flag, cluster
):
rpc_endpoint = self.cluster.storage_nodes[0].get_rpc_endpoint()

with allure.step("Create Session Token with Lifetime param"):
current_epoch = get_epoch(self.shell, cluster)

session_token = create_session_token(
shell=self.shell,
owner=get_last_address_from_wallet(default_wallet, ""),
wallet_path=default_wallet,
wallet_password=WALLET_PASS,
rpc_endpoint=rpc_endpoint,
lifetime=1 if expiration_flag == "lifetime" else None,
expire_at=current_epoch + 1 if expiration_flag == "expire_at" else None,
)

with allure.step("Create Private Container"):
un_locode = self.cluster.storage_nodes[0].get_un_locode()
locode = "SPB" if un_locode == "RU LED" else un_locode.split()[1]
placement_policy = (
f"REP 1 IN LOC_{locode}_PLACE CBF 1 SELECT 1 FROM LOC_{locode} "
f'AS LOC_{locode}_PLACE FILTER "UN-LOCODE" '
f'EQ "{un_locode}" AS LOC_{locode}'
)
cid = create_container(
default_wallet,
shell=self.shell,
endpoint=self.cluster.default_rpc_endpoint,
rule=placement_policy,
)

with allure.step("Verify object operations with created session token are allowed"):
file_path = generate_file(simple_object_size)
oid = put_object(
wallet=default_wallet,
path=file_path,
cid=cid,
shell=self.shell,
endpoint=rpc_endpoint,
session=session_token,
)
delete_object(
wallet=default_wallet,
cid=cid,
oid=oid,
shell=self.shell,
endpoint=rpc_endpoint,
session=session_token,
)

self.tick_epochs(2)

with allure.step("Verify object operations with created session token are not allowed"):
file_path = generate_file(simple_object_size)
with pytest.raises(RuntimeError, match=EXPIRED_SESSION_TOKEN):
oid = put_object(
wallet=default_wallet,
path=file_path,
cid=cid,
shell=self.shell,
endpoint=rpc_endpoint,
session=session_token,
)
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ mmh3==3.0.0
multidict==6.0.2
mypy==0.950
mypy-extensions==0.4.3
neofs-testlib==1.1.8
neofs-testlib==1.1.10
netaddr==0.8.0
packaging==21.3
paramiko==2.10.3
Expand Down
27 changes: 27 additions & 0 deletions robot/resources/lib/python_keywords/acl.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,3 +276,30 @@ def bearer_token_base64_from_file(
with open(bearer_path, "rb") as file:
signed = file.read()
return base64.b64encode(signed).decode("utf-8")


@allure.step("Create bearer token")
def create_bearer_token(
shell,
issued_at: int,
not_valid_before: int,
owner: str,
out: str,
rpc_endpoint: str,
json: Optional[bool] = False,
eacl: Optional[str] = None,
lifetime: Optional[int] = None,
expire_at: Optional[int] = None,
) -> str:
neofscli = NeofsCli(shell=shell, neofs_cli_exec_path=NEOFS_CLI_EXEC, config_file=WALLET_CONFIG)
neofscli.bearer.create(
issued_at=issued_at,
not_valid_before=not_valid_before,
owner=owner,
out=out,
rpc_endpoint=rpc_endpoint,
json=json,
eacl=eacl,
lifetime=lifetime,
expire_at=expire_at,
)
8 changes: 7 additions & 1 deletion robot/resources/lib/python_keywords/neofs_verbs.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ def put_object_to_random_node(
attributes: Optional[dict] = None,
xhdr: Optional[dict] = None,
wallet_config: Optional[str] = None,
lifetime: Optional[int] = None,
expire_at: Optional[int] = None,
no_progress: bool = True,
session: Optional[str] = None,
Expand All @@ -192,7 +193,8 @@ def put_object_to_random_node(
cluster: cluster under test
wallet_config: path to the wallet config
no_progress: do not show progress bar
expire_at: Last epoch in the life of the object
lifetime: Lock lifetime - relative to the current epoch.
expire_at: Last epoch in the life of the object - absolute value.
xhdr: Request X-Headers in form of Key=Value
session: path to a JSON-encoded container session token
Returns:
Expand All @@ -213,6 +215,7 @@ def put_object_to_random_node(
expire_at,
no_progress,
session,
lifetime
)


Expand All @@ -230,6 +233,7 @@ def put_object(
expire_at: Optional[int] = None,
no_progress: bool = True,
session: Optional[str] = None,
lifetime: Optional[int] = None,
):
"""
PUT of given file.
Expand All @@ -247,6 +251,7 @@ def put_object(
expire_at: Last epoch in the life of the object
xhdr: Request X-Headers in form of Key=Value
session: path to a JSON-encoded container session token
lifetime: Lock lifetime - relative to the current epoch.
Returns:
(str): ID of uploaded Object
"""
Expand All @@ -259,6 +264,7 @@ def put_object(
cid=cid,
attributes=attributes,
bearer=bearer,
lifetime=lifetime,
expire_at=expire_at,
no_progress=no_progress,
xhdr=xhdr,
Expand Down
3 changes: 3 additions & 0 deletions robot/resources/lib/python_keywords/storage_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def put_storagegroup(
bearer: Optional[str] = None,
wallet_config: str = WALLET_CONFIG,
lifetime: int = 10,
expire_at: Optional[int] = None,
) -> str:
"""
Wrapper for `neofs-cli storagegroup put`. Before the SG is created,
Expand All @@ -36,6 +37,7 @@ def put_storagegroup(
wallet: Path to wallet on whose behalf the SG is created.
cid: ID of Container to put SG to.
lifetime: Storage group lifetime in epochs.
expire_at: The last active epoch of the storage group.
objects: List of Object IDs to include into the SG.
bearer: Path to Bearer token file.
wallet_config: Path to neofs-cli config file.
Expand All @@ -47,6 +49,7 @@ def put_storagegroup(
wallet=wallet,
cid=cid,
lifetime=lifetime,
expire_at=expire_at,
members=objects,
bearer=bearer,
rpc_endpoint=endpoint,
Expand Down
Loading