diff --git a/robot/resources/lib/python_keywords/cli_helpers.py b/robot/resources/lib/python_keywords/cli_helpers.py index 692db06..80cc17c 100644 --- a/robot/resources/lib/python_keywords/cli_helpers.py +++ b/robot/resources/lib/python_keywords/cli_helpers.py @@ -28,7 +28,8 @@ def _cmd_run(cmd, timeout=30): logger.info(f"Executing command: {cmd}") start_time = datetime.now() compl_proc = subprocess.run(cmd, check=True, universal_newlines=True, - stdout=subprocess.PIPE, stderr=subprocess.STDOUT, timeout=timeout, + stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + timeout=timeout, shell=True) output = compl_proc.stdout return_code = compl_proc.returncode @@ -40,6 +41,8 @@ def _cmd_run(cmd, timeout=30): except subprocess.CalledProcessError as exc: raise RuntimeError(f"Error:\nreturn code: {exc.returncode} " f"\nOutput: {exc.output}") from exc + except OSError as exc: + raise RuntimeError(f"Output: {exc.strerror}") from exc except Exception as exc: return_code, _ = subprocess.getstatusoutput(cmd) logger.info(f"Error:\nreturn code: {return_code}\nOutput: " diff --git a/robot/resources/lib/python_keywords/neofs_verbs.py b/robot/resources/lib/python_keywords/neofs_verbs.py index 587b8e6..1599e97 100644 --- a/robot/resources/lib/python_keywords/neofs_verbs.py +++ b/robot/resources/lib/python_keywords/neofs_verbs.py @@ -10,13 +10,12 @@ import random import re import uuid -from robot.api import logger -from robot.api.deco import keyword - -from common import NEOFS_ENDPOINT, ASSETS_DIR, NEOFS_NETMAP, WALLET_CONFIG import json_transformers from cli_helpers import _cmd_run +from common import ASSETS_DIR, NEOFS_ENDPOINT, NEOFS_NETMAP, WALLET_CONFIG from data_formatters import dict_to_attrs +from robot.api import logger +from robot.api.deco import keyword ROBOT_AUTO_KEYWORDS = False @@ -126,7 +125,7 @@ def put_object(wallet: str, path: str, cid: str, bearer: str = "", user_headers: @keyword('Delete object') def delete_object(wallet: str, cid: str, oid: str, bearer: str = "", wallet_config: str = WALLET_CONFIG, - options: str = ""): + options: str = ""): """ DELETE an Object. @@ -187,7 +186,7 @@ def get_range(wallet: str, cid: str, oid: str, file_path: str, bearer: str, rang @keyword('Search object') def search_object(wallet: str, cid: str, keys: str = "", bearer: str = "", filters: dict = {}, - expected_objects_list=[], wallet_config: str = WALLET_CONFIG): + expected_objects_list=[], wallet_config: str = WALLET_CONFIG, options: str = ""): """ SEARCH an Object. @@ -200,6 +199,7 @@ def search_object(wallet: str, cid: str, keys: str = "", bearer: str = "", filte filters (optional, dict): key=value pairs to filter Objects expected_objects_list (optional, list): a list of ObjectIDs to compare found Objects with wallet_config(optional, str): path to the wallet config + options(optional, str): any other options which `neofs-cli object search` might accept Returns: (list): list of found ObjectIDs """ @@ -207,12 +207,13 @@ def search_object(wallet: str, cid: str, keys: str = "", bearer: str = "", filte if filters: filters_result += "--filters " logger.info(filters) - filters_result += ','.join(map(lambda i: f"'{i} EQ {filters[i]}'", filters)) + filters_result += ','.join( + map(lambda i: f"'{i} EQ {filters[i]}'", filters)) cmd = ( f'{NEOFS_CLI_EXEC} --rpc-endpoint {NEOFS_ENDPOINT} --wallet {wallet} ' f'object search {keys} --cid {cid} {filters_result} --config {wallet_config} ' - f'{"--bearer " + bearer if bearer else ""}' + f'{"--bearer " + bearer if bearer else ""} {options}' ) output = _cmd_run(cmd) diff --git a/robot/resources/lib/python_keywords/tombstone.py b/robot/resources/lib/python_keywords/tombstone.py index 59b80ad..116267a 100644 --- a/robot/resources/lib/python_keywords/tombstone.py +++ b/robot/resources/lib/python_keywords/tombstone.py @@ -2,18 +2,20 @@ import json +import neofs_verbs from neo3 import wallet from robot.api.deco import keyword from robot.libraries.BuiltIn import BuiltIn -import neofs_verbs - ROBOT_AUTO_KEYWORDS = False @keyword('Verify Head Tombstone') -def verify_head_tombstone(wallet_path: str, cid: str, oid_ts: str, oid: str): - header = neofs_verbs.head_object(wallet_path, cid, oid_ts) +def verify_head_tombstone(wallet_path: str, cid: str, oid_ts: str, oid: str, + bearer: str = "", options: str = ""): + header = neofs_verbs.head_object(wallet_path, cid, oid_ts, + bearer_token=bearer, + options=options) header = header['header'] BuiltIn().should_be_equal(header["containerID"], cid, @@ -32,18 +34,18 @@ def verify_head_tombstone(wallet_path: str, cid: str, oid_ts: str, oid: str): msg="Header Type isn't Tombstone") BuiltIn().should_be_equal( - header["sessionToken"]["body"]["object"]["verb"], 'DELETE', - msg="Header Session Type isn't DELETE" - ) + header["sessionToken"]["body"]["object"]["verb"], 'DELETE', + msg="Header Session Type isn't DELETE" + ) BuiltIn().should_be_equal( - header["sessionToken"]["body"]["object"]["address"]["containerID"], - cid, - msg="Header Session ID is wrong" - ) + header["sessionToken"]["body"]["object"]["address"]["containerID"], + cid, + msg="Header Session ID is wrong" + ) BuiltIn().should_be_equal( - header["sessionToken"]["body"]["object"]["address"]["objectID"], - oid, - msg="Header Session OID is wrong" - ) + header["sessionToken"]["body"]["object"]["address"]["objectID"], + oid, + msg="Header Session OID is wrong" + ) diff --git a/robot/resources/lib/robot/verbs.robot b/robot/resources/lib/robot/verbs.robot index 0ae1b23..f79b0c4 100644 --- a/robot/resources/lib/robot/verbs.robot +++ b/robot/resources/lib/robot/verbs.robot @@ -14,7 +14,7 @@ ${CLEANUP_TIMEOUT} = 10s *** Keywords *** Run All Verbs Except Delete And Expect Success - [Arguments] ${WALLET} ${CID} ${COMPLEXITY} + [Arguments] ${WALLET} ${CID} ${COMPLEXITY} ${BEARER_TOKEN}=${EMPTY} ${REQUEST_HEADERS}=${EMPTY} ${OBJ_SIZE} = Run Keyword If """${COMPLEXITY}""" == """Simple""" ... Set Variable ${SIMPLE_OBJ_SIZE} @@ -24,7 +24,11 @@ Run All Verbs Except Delete And Expect Success ${FILE} ${FILE_HASH} = Generate file ${OBJ_SIZE} ${OID} = Put object ${WALLET} ${FILE} ${CID} + ... bearer=${BEARER_TOKEN} + ... options=${REQUEST_HEADERS} ${OBJ_PATH} = Get object ${WALLET} ${CID} ${OID} + ... bearer_token=${BEARER_TOKEN} + ... options=${REQUEST_HEADERS} ${DOWNLOADED_FILE_HASH} = ... Get file hash ${OBJ_PATH} Should Be Equal ${DOWNLOADED_FILE_HASH} ${FILE_HASH} @@ -32,29 +36,43 @@ Run All Verbs Except Delete And Expect Success # TODO: get rid of ${EMPTY} ${RANGE_FILE} ... ${DATA_RANGE} = - ... Get Range ${WALLET} ${CID} ${OID} ${EMPTY} ${EMPTY} 0:10 + ... Get Range ${WALLET} ${CID} ${OID} file_path=${EMPTY} + ... bearer=${BEARER_TOKEN} + ... range_cut=0:10 + ... options=${REQUEST_HEADERS} ${FILE_CONTENT} = Get Binary File ${FILE} Should Contain ${FILE_CONTENT} ${DATA_RANGE} # TODO: get rid of ${EMPTY} - ${RANGE_HASH} = Get Range Hash ${WALLET} ${CID} ${OID} ${EMPTY} 0:10 + ${RANGE_HASH} = Get Range Hash ${WALLET} ${CID} ${OID} + ... bearer_token=${BEARER_TOKEN} + ... range_cut=0:10 + ... options=${REQUEST_HEADERS} ${GR_HASH} = Get File Hash ${RANGE_FILE} Should Be Equal ${GR_HASH} ${RANGE_HASH} ${FOUND_OBJECTS} = Search object ${WALLET} ${CID} keys=${OID} + ... bearer=${BEARER_TOKEN} + ... options=${REQUEST_HEADERS} List Should Contain Value ... ${FOUND_OBJECTS} ... ${OID} &{RESPONSE} = Head object ${WALLET} ${CID} ${OID} + ... bearer_token=${BEARER_TOKEN} + ... options=${REQUEST_HEADERS} [Return] ${OID} Delete Object And Validate Tombstone - [Arguments] ${WALLET} ${CID} ${OID} + [Arguments] ${WALLET} ${CID} ${OID} ${BEARER_TOKEN}=${EMPTY} ${REQUEST_HEADERS}=${EMPTY} - ${TOMBSTONE_ID} = Delete object ${WALLET} ${CID} ${OID} + ${TOMBSTONE_ID} = Delete object ${WALLET} ${CID} ${OID} + ... bearer=${BEARER_TOKEN} + ... options=${REQUEST_HEADERS} Verify Head tombstone ${WALLET} ${CID} ${TOMBSTONE_ID} ${OID} + ... bearer=${BEARER_TOKEN} + ... options=${REQUEST_HEADERS} Tick Epoch # we assume that during this time objects must be deleted @@ -62,4 +80,41 @@ Delete Object And Validate Tombstone ${ERR} = Run Keyword And Expect Error * ... Get object ${WALLET} ${CID} ${OID} + ... bearer_token=${BEARER_TOKEN} + ... options=${REQUEST_HEADERS} Should Contain ${ERR} code = 2052 message = object already removed + +Run All Verbs And Expect Failure + [Arguments] ${ERROR} ${WALLET} ${CID} ${OID} + + ${FILE} ${_} = Generate file ${SIMPLE_OBJ_SIZE} + + ${ERR} = Run Keyword And Expect Error * + ... Put object ${WALLET} ${FILE} ${CID} + Should Contain ${ERR} ${ERROR} + + ${ERR} = Run Keyword And Expect Error * + ... Get object ${WALLET} ${CID} ${OID} + Should Contain ${ERR} ${ERROR} + + # TODO: get rid of ${EMPTY} + ${ERR} = Run Keyword And Expect Error * + ... Get Range ${WALLET} ${CID} ${OID} ${EMPTY} ${EMPTY} 0:10 + Should Contain ${ERR} ${ERROR} + + # TODO: get rid of ${EMPTY} + ${ERR} = Run Keyword And Expect Error * + ... Get Range Hash ${WALLET} ${CID} ${OID} ${EMPTY} 0:10 + Should Contain ${ERR} ${ERROR} + + ${ERR} = Run Keyword And Expect Error * + ... Search object ${WALLET} ${CID} keys=${OID} + Should Contain ${ERR} ${ERROR} + + ${ERR} = Run Keyword And Expect Error * + ... Head object ${WALLET} ${CID} ${OID} + Should Contain ${ERR} ${ERROR} + + ${ERR} = Run Keyword And Expect Error * + ... Delete object ${WALLET} ${CID} ${OID} + Should Contain ${ERR} ${ERROR} diff --git a/robot/testsuites/integration/acl/acl_bearer_request_filter_xheader_equal.robot b/robot/testsuites/integration/acl/acl_bearer_request_filter_xheader_equal.robot index 2575fff..dd872bf 100644 --- a/robot/testsuites/integration/acl/acl_bearer_request_filter_xheader_equal.robot +++ b/robot/testsuites/integration/acl/acl_bearer_request_filter_xheader_equal.robot @@ -10,29 +10,21 @@ Resource eacl_tables.robot Resource common_steps_acl_bearer.robot Resource payment_operations.robot Resource setup_teardown.robot +Resource verbs.robot *** Variables *** -&{USER_HEADER} = key1=1 key2=abc -&{USER_HEADER_DEL} = key1=del key2=del -${EACL_ERROR_MSG} = * +${EACL_ERROR_MSG} = code = 2048 message = access to object operation denied *** Test cases *** BearerToken Operations with Filter Requst Equal [Documentation] Testcase to validate NeoFS operations with BearerToken with Filter Requst Equal. [Tags] ACL BearerToken - [Timeout] 20 min + [Timeout] 5 min [Setup] Setup - ${WALLET} ${_} ${_} = Prepare Wallet And Deposit - - Log Check Bearer token with simple object - ${FILE_S} ${_} = Generate file ${SIMPLE_OBJ_SIZE} - Check eACL Deny and Allow All Bearer Filter Requst Equal ${WALLET} ${FILE_S} - - Log Check Bearer token with complex object - ${FILE_S} ${_} = Generate file ${COMPLEX_OBJ_SIZE} - Check eACL Deny and Allow All Bearer Filter Requst Equal ${WALLET} ${FILE_S} + Check eACL Deny and Allow All Bearer Filter Requst Equal Simple + Check eACL Deny and Allow All Bearer Filter Requst Equal Complex [Teardown] Teardown acl_bearer_request_filter_xheader_equal @@ -41,28 +33,31 @@ BearerToken Operations with Filter Requst Equal *** Keywords *** Check eACL Deny and Allow All Bearer Filter Requst Equal - [Arguments] ${WALLET} ${FILE_S} + [Arguments] ${COMPLEXITY} - ${CID} = Create Container ${WALLET} basic_acl=eacl-public-read-write - Prepare eACL Role rules ${CID} - ${S_OID_USER} = Put object ${WALLET} ${FILE_S} ${CID} user_headers=${USER_HEADER} - ${S_OID_USER_2} = Put object ${WALLET} ${FILE_S} ${CID} - ${D_OID_USER} = Put object ${WALLET} ${FILE_S} ${CID} user_headers=${USER_HEADER_DEL} - @{S_OBJ_H} = Create List ${S_OID_USER} + ${WALLET} + ... ${_} + ... ${_} = Prepare Wallet And Deposit + ${CID} = Create Container ${WALLET} basic_acl=eacl-public-read-write - Put object ${WALLET} ${FILE_S} ${CID} - Get object ${WALLET} ${CID} ${S_OID_USER} ${EMPTY} local_file_eacl - Search object ${WALLET} ${CID} ${EMPTY} ${EMPTY} ${USER_HEADER} ${S_OBJ_H} - Head object ${WALLET} ${CID} ${S_OID_USER} - Get Range ${WALLET} ${CID} ${S_OID_USER} s_get_range ${EMPTY} 0:256 - Delete object ${WALLET} ${CID} ${D_OID_USER} + ${OID} = Run All Verbs Except Delete And Expect Success + ... ${WALLET} ${CID} ${COMPLEXITY} - Set eACL ${WALLET} ${CID} ${EACL_DENY_ALL_USER} + Delete Object And Validate Tombstone + ... ${WALLET} ${CID} ${OID} + + # Generating empty file to test operations with it after EACL will be set; + # the size does not matter as we expect to get "operation is not allowed" error + ${FILE} + ... ${_} = Generate File 0 + ${OID} = Put object ${WALLET} ${FILE} ${CID} + + Set eACL ${WALLET} ${CID} ${EACL_DENY_ALL_USER} # The current ACL cache lifetime is 30 sec Sleep ${NEOFS_CONTRACT_CACHE_TIMEOUT} - ${filters}= Create Dictionary headerType=REQUEST matchType=STRING_EQUAL key=a value=256 + ${filters}= Create Dictionary headerType=REQUEST matchType=STRING_EQUAL key=a value=256 ${rule1}= Create Dictionary Operation=GET Access=ALLOW Role=USER Filters=${filters} ${rule2}= Create Dictionary Operation=HEAD Access=ALLOW Role=USER Filters=${filters} ${rule3}= Create Dictionary Operation=PUT Access=ALLOW Role=USER Filters=${filters} @@ -74,23 +69,13 @@ Check eACL Deny and Allow All Bearer Filter Requst Equal ${EACL_TOKEN} = Form BearerToken File ${WALLET} ${CID} ${eACL_gen} - Run Keyword And Expect Error ${EACL_ERROR_MSG} - ... Put object ${WALLET} ${FILE_S} ${CID} user_headers=${USER_HEADER} - Run Keyword And Expect Error ${EACL_ERROR_MSG} - ... Get object ${WALLET} ${CID} ${S_OID_USER} ${EMPTY} local_file_eacl - Run Keyword And Expect Error ${EACL_ERROR_MSG} - ... Search object ${WALLET} ${CID} ${EMPTY} ${EMPTY} ${USER_HEADER} ${S_OBJ_H} - Run Keyword And Expect Error ${EACL_ERROR_MSG} - ... Head object ${WALLET} ${CID} ${S_OID_USER} - Run Keyword And Expect Error ${EACL_ERROR_MSG} - ... Get Range ${WALLET} ${CID} ${S_OID_USER} s_get_range ${EMPTY} 0:256 - Run Keyword And Expect Error ${EACL_ERROR_MSG} - ... Delete object ${WALLET} ${CID} ${S_OID_USER} + Run All Verbs And Expect Failure + ... ${EACL_ERROR_MSG} ${WALLET} ${CID} ${OID} - Put object ${WALLET} ${FILE_S} ${CID} bearer=${EACL_TOKEN} user_headers=${USER_HEADER} options=--xhdr a=256 - Get object ${WALLET} ${CID} ${S_OID_USER} ${EACL_TOKEN} local_file_eacl ${EMPTY} --xhdr a=256 - Search object ${WALLET} ${CID} ${EMPTY} ${EACL_TOKEN} ${USER_HEADER} ${EMPTY} --xhdr a=256 - Head object ${WALLET} ${CID} ${S_OID_USER} bearer_token=${EACL_TOKEN} options=--xhdr a=256 - Get Range ${WALLET} ${CID} ${S_OID_USER} s_get_range ${EACL_TOKEN} 0:256 --xhdr a=256 - Get Range Hash ${WALLET} ${CID} ${S_OID_USER} ${EACL_TOKEN} 0:256 --xhdr a=256 - Delete object ${WALLET} ${CID} ${S_OID_USER} ${EACL_TOKEN} --xhdr a=256 + ${OID} = Run All Verbs Except Delete And Expect Success + ... ${WALLET} ${CID} ${COMPLEXITY} + ... ${EACL_TOKEN} --xhdr a=256 + + Delete Object And Validate Tombstone + ... ${WALLET} ${CID} ${OID} + ... ${EACL_TOKEN} --xhdr a=256