From 8a2f1cf50c61ea901678e0ca8431bfb82e7e710f Mon Sep 17 00:00:00 2001 From: Elizaveta Chichindaeva Date: Wed, 3 Nov 2021 15:48:31 +0300 Subject: [PATCH] [#64] Create container_session_token.robot test Signed-off-by: Elizaveta Chichindaeva --- robot/resources/lib/cli_helpers.py | 9 +++ robot/resources/lib/gates.py | 25 ++----- robot/resources/lib/neofs.py | 66 ++++++++++++++++--- .../integration/acl/test_eacl.robot | 25 +++++++ .../container/container_session_token.robot | 50 ++++++++++++++ robot/variables/common.py | 2 + venv/localtest/requirements.txt | 2 +- 7 files changed, 151 insertions(+), 28 deletions(-) create mode 100644 robot/testsuites/integration/acl/test_eacl.robot create mode 100644 robot/testsuites/integration/container/container_session_token.robot diff --git a/robot/resources/lib/cli_helpers.py b/robot/resources/lib/cli_helpers.py index 86dac3a..a18ee3d 100644 --- a/robot/resources/lib/cli_helpers.py +++ b/robot/resources/lib/cli_helpers.py @@ -6,6 +6,7 @@ and other CLIs. """ import subprocess +import pexpect from robot.api import logger @@ -27,3 +28,11 @@ def _cmd_run(cmd): except subprocess.CalledProcessError as exc: raise RuntimeError(f"Error:\nreturn code: {exc.returncode} " f"\nOutput: {exc.output}") from exc + +def _run_with_passwd(cmd): + p = pexpect.spawn(cmd) + p.expect(".*") + p.sendline('\r') + p.wait() + cmd = p.read() + return cmd.decode() diff --git a/robot/resources/lib/gates.py b/robot/resources/lib/gates.py index 85cbeaf..a607212 100644 --- a/robot/resources/lib/gates.py +++ b/robot/resources/lib/gates.py @@ -1,22 +1,18 @@ #!/usr/bin/python3.8 -from logging import raiseExceptions -import boto3 -import botocore import os -import pexpect import re -import requests import shutil import subprocess import uuid - -from robot.api.deco import keyword -from robot.api import logger -import robot.errors -from robot.libraries.BuiltIn import BuiltIn +import requests +import botocore +import boto3 from common import * +from robot.api.deco import keyword +from robot.api import logger +from cli_helpers import _run_with_passwd ROBOT_AUTO_KEYWORDS = False @@ -61,15 +57,6 @@ def init_s3_credentials(wallet): raise Exception(f"Error: \nreturn code: {e.returncode}. \nOutput: {e.stderr}") -def _run_with_passwd(cmd): - p = pexpect.spawn(cmd) - p.expect(".*") - p.sendline('\r') - p.wait() - cmd = p.read() - return cmd.decode() - - @keyword('Config S3 client') def config_s3_client(access_key_id, secret_access_key): try: diff --git a/robot/resources/lib/neofs.py b/robot/resources/lib/neofs.py index 1b7077b..7b7b27d 100644 --- a/robot/resources/lib/neofs.py +++ b/robot/resources/lib/neofs.py @@ -1,23 +1,22 @@ #!/usr/bin/python3.8 -import base58 import base64 import binascii from datetime import datetime -import docker import hashlib import json import os import re import random -import subprocess +import uuid +import docker +import base58 from neo3 import wallet +from common import * from robot.api.deco import keyword from robot.api import logger - -from common import * -from cli_helpers import _cmd_run +from cli_helpers import _run_with_passwd, _cmd_run ROBOT_AUTO_KEYWORDS = False @@ -137,7 +136,7 @@ def get_range(private_key: str, cid: str, oid: str, range_file: str, bearer: str @keyword('Create container') -def create_container(private_key: str, basic_acl:str, rule:str, user_headers: str=''): +def create_container(private_key: str, basic_acl:str, rule:str, user_headers: str='', session: str=''): if rule == "": logger.error("Cannot create container with empty placement rule") @@ -145,10 +144,12 @@ def create_container(private_key: str, basic_acl:str, rule:str, user_headers: st basic_acl = f"--basic-acl {basic_acl}" if user_headers: user_headers = f"--attributes {user_headers}" + if session: + session = f"--session {session}" createContainerCmd = ( f'{NEOFS_CLI_EXEC} --rpc-endpoint {NEOFS_ENDPOINT} --wif {private_key} ' - f'container create --policy "{rule}" {basic_acl} {user_headers} --await' + f'container create --policy "{rule}" {basic_acl} {user_headers} {session} --await' ) logger.info(f"Cmd: {createContainerCmd}") output = _cmd_run(createContainerCmd) @@ -970,6 +971,55 @@ def delete_storagegroup(private_key: str, cid: str, oid: str, bearer_token: str= raise Exception(f"no Tombstone ID was parsed from command output: \t{output}") return oid +@keyword('Generate Session Token') +def generate_session_token(owner: str, pub_key: str, cid: str = "", wildcard: bool = False) -> str: + + file_path = f"{os.getcwd()}/{ASSETS_DIR}/{str(uuid.uuid4())}" + + owner_64 = base64.b64encode(base58.b58decode(owner)).decode('utf-8') + cid_64 = base64.b64encode(cid.encode('utf-8')).decode('utf-8') + pub_key_64 = base64.b64encode(bytes.fromhex(pub_key)).decode('utf-8') + id_64 = base64.b64encode(uuid.uuid4().bytes).decode('utf-8') + + session_token = { + "body":{ + "id":f"{id_64}", + "ownerID":{ + "value":f"{owner_64}" + }, + "lifetime":{ + "exp":"100000000", + "nbf":"0", + "iat":"0" + }, + "sessionKey":f"{pub_key_64}", + "container":{ + "verb":"PUT", + "wildcard": wildcard, + **({ "containerID":{"value":f"{cid_64}"} } if not wildcard else {}) + } + } + } + + logger.info(f"Got this Session Token: {session_token}") + + with open(file_path, 'w', encoding='utf-8') as session_token_file: + json.dump(session_token, session_token_file, ensure_ascii=False, indent=4) + + return file_path + + +@keyword ('Sign Session Token') +def sign_session_token(session_token: str, wallet: str, to_file: str=''): + if to_file: + to_file = f'--to {to_file}' + cmd = ( + f'{NEOFS_CLI_EXEC} util sign session-token --from {session_token} ' + f'-w {wallet} {to_file}' + ) + logger.info(f"cmd: {cmd}") + _run_with_passwd(cmd) + def _get_file_hash(filename): blocksize = 65536 diff --git a/robot/testsuites/integration/acl/test_eacl.robot b/robot/testsuites/integration/acl/test_eacl.robot new file mode 100644 index 0000000..3576b90 --- /dev/null +++ b/robot/testsuites/integration/acl/test_eacl.robot @@ -0,0 +1,25 @@ +*** Settings *** +Variables ../../../variables/common.py +Library ../${RESOURCES}/neofs.py +Library ../${RESOURCES}/payment_neogo.py + +Resource common_steps_acl_basic.robot +Resource ../${RESOURCES}/payment_operations.robot +Resource ../${RESOURCES}/setup_teardown.robot +Resource robot/testsuites/integration/acl/common_steps_acl_extended.robot + + +*** Test cases *** +Basic ACL Operations for Private Container + [Documentation] Testcase to validate NeoFS operations with ACL for Private Container. + [Tags] ACL NeoFS NeoCLI + [Timeout] 20 min + + [Setup] Setup + + ${WALLET} ${ADDR} ${USER_KEY} = Prepare Wallet And Deposit + ${WALLET_OTH} ${ADDR_OTH} ${OTHER_KEY} = Prepare Wallet And Deposit + + ${CID} = Create Container Public ${USER_KEY} + ${S_OID_USER} = Put object ${USER_KEY} ./test.txt ${CID} ${EMPTY} ${EMPTY} + \ No newline at end of file diff --git a/robot/testsuites/integration/container/container_session_token.robot b/robot/testsuites/integration/container/container_session_token.robot new file mode 100644 index 0000000..75e7a77 --- /dev/null +++ b/robot/testsuites/integration/container/container_session_token.robot @@ -0,0 +1,50 @@ +*** Settings *** +Variables ../../../variables/common.py +Variables ../../../variables/acl.py + +Resource setup_teardown.robot +Resource payment_operations.robot + +Library Process +Library neofs.py +Library String +Library OperatingSystem + +*** Variables *** +${SIGNED_FILE} = ${ASSETS_DIR}/signed_token.json + +*** Test Cases *** + +Session Token for Container + [Documentation] Testcase to check container session token + [Tags] Container SessionToken + [Timeout] 5 min + + [Setup] Setup + + ${WALLET} ${OWNER} ${OWNER_KEY} = Prepare Wallet And Deposit + ${GEN_WALLET} ${GEN} ${GEN_KEY} = Init Wallet with Address ${ASSETS_DIR} + + ${UTIL} = Run Process ${NEOGO_EXECUTABLE} wallet dump-keys -w ${GEN_WALLET} shell=True + ${PUB_PART} = Get Line ${UTIL.stdout} 1 + + ${SESSION_TOKEN} = Generate Session Token ${OWNER} ${PUB_PART} wildcard=True + + Sign Session token ${SESSION_TOKEN} ${WALLET} ${SIGNED_FILE} + + ${CID} = Create Container ${GEN_KEY} ${PRIVATE_ACL} ${COMMON_PLACEMENT_RULE} ${EMPTY} ${SIGNED_FILE} + Wait Until Keyword Succeeds ${MORPH_BLOCK_TIME} ${CONTAINER_WAIT_INTERVAL} + ... Container Existing ${OWNER_KEY} ${CID} + Run Keyword And Expect Error * + ... Container Existing ${GEN_KEY} ${CID} + +######################## +# Check container owner +######################## + + ${CONTAINER_INFO} = Run Process ${NEOFS_CLI_EXEC} container get --cid ${CID} --wif ${GEN_KEY} --rpc-endpoint ${NEOFS_ENDPOINT} shell=True + ${CID_OWNER_ID_LINE} = Get Line ${CONTAINER_INFO.stdout} 2 + @{CID_OWNER_ID} = Split String ${CID_OWNER_ID_LINE} + Should Be Equal As Strings ${OWNER} ${CID_OWNER_ID}[2] + + [Teardown] Teardown container_session_token diff --git a/robot/variables/common.py b/robot/variables/common.py index f3bdce7..c6c8193 100644 --- a/robot/variables/common.py +++ b/robot/variables/common.py @@ -66,3 +66,5 @@ NEOFS_NETMAP_DICT = {'s01': {'rpc': 's01.neofs.devenv:8080', 'UN-LOCODE': 'FI HEL'} } NEOFS_NETMAP = [i['rpc'] for i in NEOFS_NETMAP_DICT.values()] +NEOGO_EXECUTABLE = os.getenv('NEOGO_EXECUTABLE', 'neo-go') +NEOFS_CLI_EXEC = os.getenv('NEOFS_CLI_EXEC', 'neofs-cli') diff --git a/venv/localtest/requirements.txt b/venv/localtest/requirements.txt index 42a31a5..aa6865a 100644 --- a/venv/localtest/requirements.txt +++ b/venv/localtest/requirements.txt @@ -1,4 +1,4 @@ -robotframework==3.2.1 +robotframework==4.1.2 requests==2.25.1 pexpect==4.8.0 boto3==1.16.33