diff options
author | qrort <qrort@yandex-team.com> | 2022-11-30 23:47:12 +0300 |
---|---|---|
committer | qrort <qrort@yandex-team.com> | 2022-11-30 23:47:12 +0300 |
commit | 22f8ae0e3f5d68b92aecccdf96c1d841a0334311 (patch) | |
tree | bffa27765faf54126ad44bcafa89fadecb7a73d7 /library/python/deprecated/ticket_parser2 | |
parent | 332b99e2173f0425444abb759eebcb2fafaa9209 (diff) | |
download | ydb-22f8ae0e3f5d68b92aecccdf96c1d841a0334311.tar.gz |
validate canons without yatest_common
Diffstat (limited to 'library/python/deprecated/ticket_parser2')
27 files changed, 2995 insertions, 0 deletions
diff --git a/library/python/deprecated/ticket_parser2/README.md b/library/python/deprecated/ticket_parser2/README.md new file mode 100644 index 0000000000..2672e55c9e --- /dev/null +++ b/library/python/deprecated/ticket_parser2/README.md @@ -0,0 +1,3 @@ +ticket_parser2 is deprecated: please use [tvmauth](https://a.yandex-team.ru/arc/trunk/arcadia/library/python/tvmauth) instead. + +https://clubs.at.yandex-team.ru/passport/3619 diff --git a/library/python/deprecated/ticket_parser2/examples/create_with_tvmapi/__init__.py b/library/python/deprecated/ticket_parser2/examples/create_with_tvmapi/__init__.py new file mode 100644 index 0000000000..f8809b2ed6 --- /dev/null +++ b/library/python/deprecated/ticket_parser2/examples/create_with_tvmapi/__init__.py @@ -0,0 +1,75 @@ +import ticket_parser2 as tp2 + + +def get_client_for_checking_all_tickets_and_fetching_service_tickets(): + c = tp2.TvmClient( + tp2.TvmApiClientSettings( + self_client_id=11, + enable_service_ticket_checking=True, + enable_user_ticket_checking=tp2.BlackboxEnv.Test, + self_secret="AAAAAAAAAAAAAAAAAAAAAA", + dsts={"bb": 224, "datasync": 2000060}, + ) + ) + + # c.check_service_ticket("some service ticket") + # c.check_user_ticket("some user ticket") + # c.get_service_ticket_for("bb") + # c.get_service_ticket_for(client_id=224) + + return c + + +def get_client_for_checking_all_tickets(): + c = tp2.TvmClient( + tp2.TvmApiClientSettings( + self_client_id=11, + enable_service_ticket_checking=True, + enable_user_ticket_checking=tp2.BlackboxEnv.Test, + ) + ) + + # c.check_service_ticket("some service ticket") + # c.check_user_ticket("some user ticket") + + return c + + +def get_client_for_fetching_service_tickets(): + c = tp2.TvmClient( + tp2.TvmApiClientSettings( + self_client_id=11, + self_secret="AAAAAAAAAAAAAAAAAAAAAA", + dsts={"bb": 224, "datasync": 2000060}, + ) + ) + + # c.get_service_ticket_for("bb") + # c.get_service_ticket_for(client_id=224) + + return c + + +def get_client_for_checking_service_tickets(): + c = tp2.TvmClient( + tp2.TvmApiClientSettings( + self_client_id=11, + enable_service_ticket_checking=True, + ) + ) + + # c.check_service_ticket("some service ticket") + + return c + + +def get_client_for_checking_user_tickets(): + c = tp2.TvmClient( + tp2.TvmApiClientSettings( + enable_user_ticket_checking=tp2.BlackboxEnv.Test, + ) + ) + + # c.check_user_ticket("some user ticket") + + return c diff --git a/library/python/deprecated/ticket_parser2/examples/create_with_tvmtool/__init__.py b/library/python/deprecated/ticket_parser2/examples/create_with_tvmtool/__init__.py new file mode 100644 index 0000000000..6011f8efd1 --- /dev/null +++ b/library/python/deprecated/ticket_parser2/examples/create_with_tvmtool/__init__.py @@ -0,0 +1,29 @@ +import ticket_parser2 as tp2 + + +# Possibility of using functions depends on config of tvmtool +# check_service_ticket +# check_user_ticket +# get_service_ticket_for + + +def get_client_for_dev(): + c = tp2.TvmClient( + tp2.TvmToolClientSettings( + self_alias="me", + auth_token="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + port=18080, + ) + ) + + return c + + +def get_client_in_qloud_or_yandexdeploy(): + c = tp2.TvmClient( + tp2.TvmToolClientSettings( + self_alias="me", + ) + ) + + return c diff --git a/library/python/deprecated/ticket_parser2/examples/service_using_tvm_client/__init__.py b/library/python/deprecated/ticket_parser2/examples/service_using_tvm_client/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/library/python/deprecated/ticket_parser2/examples/service_using_tvm_client/__init__.py diff --git a/library/python/deprecated/ticket_parser2/examples/service_using_tvm_client/serv.py b/library/python/deprecated/ticket_parser2/examples/service_using_tvm_client/serv.py new file mode 100644 index 0000000000..43c965ab9e --- /dev/null +++ b/library/python/deprecated/ticket_parser2/examples/service_using_tvm_client/serv.py @@ -0,0 +1,39 @@ +import requests +import ticket_parser2 as tp2 + + +class SomeService: + def __init__(self, **kwargs): + self._client = tp2.TvmClient( + tp2.TvmApiClientSettings( + self_client_id=11, + enable_service_ticket_checking=True, + enable_user_ticket_checking=tp2.BlackboxEnv.Test, + self_secret="AAAAAAAAAAAAAAAAAAAAAA", + dsts={"bb": 224, "datasync": 2000060}, + ) + ) + + self._allowed_consumers = kwargs['acl'] # array + + def stop(self): + self._client.stop() + + # Processing of request is here + def handle_request(self, **kwargs): + try: + st = self._client.check_service_ticket(kwargs['X-Ya-Service-Ticket']) + ut = self._client.check_user_ticket(kwargs['X-Ya-User-Ticket']) + + if st.src not in self._allowed_consumers: + raise Exception("Access denied (service)") + + if 'allow_to_get_secret_data' not in ut.scopes: + raise Exception("Access denied (user)") + + return requests.get( + 'my_backend_request', + headers={'X-Ya-Service-Ticket': self._client.get_service_ticket_for("datasync")}, + ).content + except tp2.TvmException: + raise Exception("Error") diff --git a/library/python/deprecated/ticket_parser2/mock/ticket_parser2_mock/__init__.py b/library/python/deprecated/ticket_parser2/mock/ticket_parser2_mock/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/library/python/deprecated/ticket_parser2/mock/ticket_parser2_mock/__init__.py diff --git a/library/python/deprecated/ticket_parser2/mock/ticket_parser2_mock/api/__init__.py b/library/python/deprecated/ticket_parser2/mock/ticket_parser2_mock/api/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/library/python/deprecated/ticket_parser2/mock/ticket_parser2_mock/api/__init__.py diff --git a/library/python/deprecated/ticket_parser2/mock/ticket_parser2_mock/api/v1/__init__.py b/library/python/deprecated/ticket_parser2/mock/ticket_parser2_mock/api/v1/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/library/python/deprecated/ticket_parser2/mock/ticket_parser2_mock/api/v1/__init__.py diff --git a/library/python/deprecated/ticket_parser2/mock/ticket_parser2_mock/api/v1/tvm_client.py b/library/python/deprecated/ticket_parser2/mock/ticket_parser2_mock/api/v1/tvm_client.py new file mode 100644 index 0000000000..7e05ca25d0 --- /dev/null +++ b/library/python/deprecated/ticket_parser2/mock/ticket_parser2_mock/api/v1/tvm_client.py @@ -0,0 +1,147 @@ +try: + import mock # noqa +except ImportError: + import unittest.mock # noqa + +try: + import ticket_parser2_py3.api.v1 as tp2 # noqa + import ticket_parser2_py3.api.v1.exceptions as tp2e # noqa + import ticket_parser2_py3.api.v1.unittest as tp2u # noqa +except ImportError: + import ticket_parser2.api.v1 as tp2 # noqa + import ticket_parser2.api.v1.exceptions as tp2e # noqa + import ticket_parser2.api.v1.unittest as tp2u # noqa + + +import warnings + + +warnings.warn( + message="This package is going to be removed. Please use 'ticket_parser2.mock' instead", + category=FutureWarning, + stacklevel=2, +) + + +__doc__ = """ +Use TvmClientPatcher to replace TvmClient with MockedTvmClient. +MockedTvmClient can check ServiceTickets and UserTickets from `tvmknife unittest` +Read more: https://wiki.yandex-team.ru/passport/tvm2/debug/#tvmknife +Examples are in docstring for TvmClientPatcher. +""" + + +PUBLIC_KEYS = tp2u.TVMKNIFE_PUBLIC_KEYS + + +class MockedTvmClient(object): + def __init__(self, status=tp2.TvmClientStatus.Ok, self_client_id=100500, bb_env=tp2.BlackboxEnv.Test): + self._status = status + self._serv_ctx = tp2.ServiceContext(self_client_id, None, PUBLIC_KEYS) + self._user_ctx = tp2.UserContext(bb_env, PUBLIC_KEYS) + self._stopped = False + + def __check(self): + if self._stopped: + raise tp2e.NonRetriableException("TvmClient is already stopped") + + def stop(self): + self._stopped = True + + @property + def status(self): + self.__check() + return self._status + + @staticmethod + def status_to_string(status): + return tp2.TvmClient.status_to_string(status) + + def get_service_ticket_for(self, alias=None, client_id=None): + """ + You can generate any ticket you want with `tvmknife unittest` and override this function with your ticket + https://wiki.yandex-team.ru/passport/tvm2/debug/ + """ + self.__check() + if alias is None and client_id is None: + raise tp2e.TvmException("One of args is required: 'alias' or 'client_id'") + return "Some service ticket" + + def check_service_ticket(self, ticket): + self.__check() + return self._serv_ctx.check(ticket) + + def check_user_ticket(self, ticket): + self.__check() + return self._user_ctx.check(ticket) + + +class TvmClientPatcher(object): + """ + Example: + with TvmClientPatcher(): + c = TvmClient() + assert TvmClientStatus.Ok == c.status + assert 123 == c.check_service_ticket(SRV_TICKET).src + assert 123 == c.check_user_ticket(USER_TICKET_TEST).default_uid + assert 'Some service ticket' == c.get_service_ticket_for("foo") + + Example: + with TvmClientPatcher(MockedTvmClient(self_client_id=100501)): + c = TvmClient() + assert TvmClientStatus.Ok == c.status + with pytest.raises(TicketParsingException): + c.check_service_ticket(SRV_TICKET) + assert 123 == c.check_user_ticket(TEST_TICKET).default_uid + assert 'Some service ticket' == c.get_service_ticket_for("foo") + + Example: + with TvmClientPatcher(MockedTvmClient()) as p: + p.get_mocked_tvm_client().check_service_ticket = mock.Mock( + side_effect=TicketParsingException("Unsupported version", Status.UnsupportedVersion, "2:err"), + ) + + c = TvmClient() + assert TvmClientStatus.Ok == c.status + with pytest.raises(TicketParsingException): + c.check_service_ticket(SRV_TICKET) + + Example: + m = MockedTvmClient() + m.get_service_ticket_for = mock.Mock(side_effect=[ + 'SERVICE_TICKET_FOR_MY_FIRST_CALL', + 'SERVICE_TICKET_FOR_MY_SECOND_CALL'], + ) + with TvmClientPatcher(m): + c = TvmClient() + assert TvmClientStatus.Ok == c.status + assert 'SERVICE_TICKET_FOR_MY_FIRST_CALL' == c.get_service_ticket_for() + assert 'SERVICE_TICKET_FOR_MY_SECOND_CALL' == c.get_service_ticket_for() + """ + + def __init__(self, mocked_tvm_client=None): + if mocked_tvm_client is None: + mocked_tvm_client = MockedTvmClient() + self._mocked_tvm_client = mocked_tvm_client + self._patch = mock.patch.object( + tp2.TvmClient, + '__new__', + mock.Mock(return_value=mocked_tvm_client), + ) + + def start(self): + self._patch.start() + return self + + def stop(self): + self._patch.stop() + + def __enter__(self): + self.start() + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.stop() + + def get_mocked_tvm_client(self): + return self._mocked_tvm_client diff --git a/library/python/deprecated/ticket_parser2/so/ticket_parser2_pymodule.exports b/library/python/deprecated/ticket_parser2/so/ticket_parser2_pymodule.exports new file mode 100644 index 0000000000..3cb2b5c85e --- /dev/null +++ b/library/python/deprecated/ticket_parser2/so/ticket_parser2_pymodule.exports @@ -0,0 +1 @@ +C initticket_parser2_pymodule diff --git a/library/python/deprecated/ticket_parser2/src/exception.h b/library/python/deprecated/ticket_parser2/src/exception.h new file mode 100644 index 0000000000..a31417300a --- /dev/null +++ b/library/python/deprecated/ticket_parser2/src/exception.h @@ -0,0 +1,80 @@ +#pragma once + +#include <library/cpp/tvmauth/exception.h> +#include <library/cpp/tvmauth/client/exception.h> + +#include <exception> +#include <ios> +#include <new> +#include <stdexcept> +#include <typeinfo> + +#include <Python.h> + +extern "C" DL_EXPORT(PyObject*) pyEmptyTvmKeysException; +extern "C" DL_EXPORT(PyObject*) pyMalformedTvmKeysException; +extern "C" DL_EXPORT(PyObject*) pyMalformedTvmSecretException; +extern "C" DL_EXPORT(PyObject*) pyNotAllowedException; +extern "C" DL_EXPORT(PyObject*) pyClientException; +extern "C" DL_EXPORT(PyObject*) pyBrokenTvmClientSettings; +extern "C" DL_EXPORT(PyObject*) pyInvalidCache; +extern "C" DL_EXPORT(PyObject*) pyRetriableException; +extern "C" DL_EXPORT(PyObject*) pyNonRetriableException; +extern "C" DL_EXPORT(PyObject*) pyPermissionDenied; +extern "C" DL_EXPORT(PyObject*) pyMissingServiceTicket; + +static void raise_py_error() { + // Catch a handful of different errors here and turn them into the + // equivalent Python errors. + try { + if (PyErr_Occurred()) + ; // let the latest Python exn pass through and ignore the current one + else + throw; + } catch (const NTvmAuth::TEmptyTvmKeysException& ex) { + PyErr_SetString(pyEmptyTvmKeysException, ex.what()); + } catch (const NTvmAuth::TMalformedTvmKeysException& ex) { + PyErr_SetString(pyMalformedTvmKeysException, ex.what()); + } catch (const NTvmAuth::TMalformedTvmSecretException& ex) { + PyErr_SetString(pyMalformedTvmSecretException, ex.what()); + } catch (const NTvmAuth::TNotAllowedException& ex) { + PyErr_SetString(pyNotAllowedException, ex.what()); + } catch (const NTvmAuth::TBrokenTvmClientSettings& ex) { + PyErr_SetString(pyBrokenTvmClientSettings, ex.what()); + } catch (const NTvmAuth::TPermissionDenied& ex) { + PyErr_SetString(pyPermissionDenied, ex.what()); + } catch (const NTvmAuth::TMissingServiceTicket& ex) { + PyErr_SetString(pyMissingServiceTicket, ex.what()); + } catch (const NTvmAuth::TNonRetriableException& ex) { + PyErr_SetString(pyNonRetriableException, ex.what()); + } catch (const NTvmAuth::TRetriableException& ex) { + PyErr_SetString(pyRetriableException, ex.what()); + } catch (const NTvmAuth::TClientException& ex) { + PyErr_SetString(pyClientException, ex.what()); + } catch (const std::bad_alloc& ex) { + PyErr_SetString(PyExc_MemoryError, ex.what()); + } catch (const std::bad_cast& ex) { + PyErr_SetString(PyExc_TypeError, ex.what()); + } catch (const std::domain_error& ex) { + PyErr_SetString(PyExc_ValueError, ex.what()); + } catch (const std::invalid_argument& ex) { + PyErr_SetString(PyExc_ValueError, ex.what()); + } catch (const std::ios_base::failure& ex) { + // Unfortunately, in standard C++ we have no way of distinguishing EOF + // from other errors here; be careful with the exception mask + PyErr_SetString(PyExc_IOError, ex.what()); + } catch (const std::out_of_range& ex) { + // Change out_of_range to IndexError + PyErr_SetString(PyExc_IndexError, ex.what()); + } catch (const std::overflow_error& ex) { + PyErr_SetString(PyExc_OverflowError, ex.what()); + } catch (const std::range_error& ex) { + PyErr_SetString(PyExc_ArithmeticError, ex.what()); + } catch (const std::underflow_error& ex) { + PyErr_SetString(PyExc_ArithmeticError, ex.what()); + } catch (const std::exception& ex) { + PyErr_SetString(PyExc_RuntimeError, ex.what()); + } catch (...) { + PyErr_SetString(PyExc_RuntimeError, "Unknown exception"); + } +} diff --git a/library/python/deprecated/ticket_parser2/src/logger.h b/library/python/deprecated/ticket_parser2/src/logger.h new file mode 100644 index 0000000000..9a89f30324 --- /dev/null +++ b/library/python/deprecated/ticket_parser2/src/logger.h @@ -0,0 +1,31 @@ +#pragma once + +#include <library/cpp/pybind/ptr.h> +#include <library/cpp/tvmauth/client/logger.h> + +extern "C" { + void cy_call_func(PyObject*, char*, int, const char*, size_t); +} + +namespace NTvmAuth { + class IPyLogger: public ILogger { + public: + NPyBind::TPyObjectPtr Obj_; + + IPyLogger(PyObject* obj) + : Obj_(obj) + { + } + + ~IPyLogger() { + } + + void Log(int lvl, const TString& msg) override { + if (!Obj_) { + return; + } + + cy_call_func(this->Obj_.Get(), (char*)"__log", lvl, msg.data(), msg.size()); + } + }; +} diff --git a/library/python/deprecated/ticket_parser2/src/ut/test_client.py b/library/python/deprecated/ticket_parser2/src/ut/test_client.py new file mode 100644 index 0000000000..34ff26bd0f --- /dev/null +++ b/library/python/deprecated/ticket_parser2/src/ut/test_client.py @@ -0,0 +1,710 @@ +#!/usr/bin/env python +from __future__ import print_function + +import logging +from multiprocessing import Process +import shutil +import socket +import sys +import time + +import mock +import pytest +from six import StringIO +from six.moves import ( + BaseHTTPServer, + socketserver as SocketServer, +) +import ticket_parser2 as tp2 +import ticket_parser2.low_level +from ticket_parser2.exceptions import ( + BrokenTvmClientSettings, + NonRetriableException, + RetriableException, + TicketParsingException, + TvmException, +) +import ticket_parser2.unittest as tp2u +from ticket_parser2.mock import ( + MockedTvmClient, + TvmClientPatcher, +) +import yatest.common as yc +from yatest.common import network + + +SRV_TICKET = ( + "3:serv:CBAQ__________9_IgYIexCUkQY:GioCM49Ob6_f80y6FY0XBVN4hLXuMlFeyMvIMiDuQnZkbkLpRp" + "QOuQo5YjWoBjM0Vf-XqOm8B7xtrvxSYHDD7Q4OatN2l-Iwg7i71lE3scUeD36x47st3nd0OThvtjrFx_D8mw_" + "c0GT5KcniZlqq1SjhLyAk1b_zJsx8viRAhCU" +) +PROD_TICKET = ( + "3:user:CAsQ__________9_Gg4KAgh7EHsg0oXYzAQoAA:N8PvrDNLh-5JywinxJntLeQGDEHBUxfzjuvB8-_B" + "EUv1x9CALU7do8irDlDYVeVVDr4AIpR087YPZVzWPAqmnBuRJS0tJXekmDDvrivLnbRrzY4IUXZ_fImB0fJhTy" + "VetKv6RD11bGqnAJeDpIukBwPTbJc_EMvKDt8V490CJFw" +) +TEST_TICKET = ( + "3:user:CA0Q__________9_Gg4KAgh7EHsg0oXYzAQoAQ:FSADps3wNGm92Vyb1E9IVq5M6ZygdGdt1vafWWEh" + "fDDeCLoVA-sJesxMl2pGW4OxJ8J1r_MfpG3ZoBk8rLVMHUFrPa6HheTbeXFAWl8quEniauXvKQe4VyrpA1SPgt" + "RoFqi5upSDIJzEAe1YRJjq1EClQ_slMt8R0kA_JjKUX54" +) +PROD_YATEAM_TICKET = ( + "3:user:CAwQ__________9_Gg4KAgh7EHsg0oXYzAQoAg:JBYQYr71TnozlBiJhGVyCKdAhlDtrEda1ofe4mCz" + "0OkxWi4J1EtB3CeYUkxSO4iTSAqJVq8bFdneyS7YCVOt4u69E-SClzRgZ6v7A36l4Z25XNovqC-0o1h-IwFTgy" + "CZfoPJVfkEOmAYXV4YINBca6L2lZ7ux6q0s5Q5_kUnkAk" +) +TEST_YATEAM_TICKET = ( + "3:user:CA4Q__________9_GhIKBAjAxAcQwMQHINKF2MwEKAM:CpRDQBbh5icA3NCuKuSZUIO0gNyWXej1XfI" + "nEiSvhs6wcrDHCeQbxzYOfeq2wM801DkaebSmnDBgoWjC7C9hMj4xpmOF_QhRfhFibXbm0O-7lbczO8zLL080m" + "s59rpaEU3SOKLJ-HaaXrjPCIGSTAIJRvWnck-QXJXPpqmPETr8" +) + +TVM_RESP = '{"19" : { "ticket" : "3:serv:CBAQ__________9_IgYIKhCUkQY:CX"}}'.encode('utf-8') + +log_stream = StringIO() +logger = logging.getLogger('TVM') +handler = logging.StreamHandler(stream=log_stream) +handler.setLevel(logging.DEBUG) +logger.addHandler(handler) + + +def get_log_stream_value(): + return log_stream.getvalue().lstrip('\x00') + + +def test_settings(): + with pytest.raises(BrokenTvmClientSettings): + tp2.TvmApiClientSettings(self_client_id=0) + + with pytest.raises(BrokenTvmClientSettings): + tp2.TvmApiClientSettings(enable_service_ticket_checking=True) + tp2.TvmApiClientSettings(enable_service_ticket_checking=True, self_client_id=123) + + tp2.TvmApiClientSettings(enable_user_ticket_checking=tp2.BlackboxEnv.Test) + + with pytest.raises(BrokenTvmClientSettings): + tp2.TvmApiClientSettings() + with pytest.raises(BrokenTvmClientSettings): + tp2.TvmApiClientSettings(self_secret='asd', dsts={'qwe': 1}) + with pytest.raises(BrokenTvmClientSettings): + tp2.TvmApiClientSettings(self_secret='', dsts={'qwe': 1}) + with pytest.raises(BrokenTvmClientSettings): + tp2.TvmApiClientSettings(self_secret='asd', dsts={}) + with pytest.raises(TvmException): + tp2.TvmApiClientSettings(self_secret='asd', dsts='kek', self_client_id=123) + tp2.TvmApiClientSettings(self_secret='asd', dsts={'qwe': 1}, self_client_id=123) + + s = tp2.TvmApiClientSettings(enable_user_ticket_checking=tp2.BlackboxEnv.Test) + s.set_disk_cache_dir('./') + + with pytest.raises(BrokenTvmClientSettings): + tp2.TvmClient('kek') + + +def test_full_client(): + path = yc.source_path() + '/library/cpp/tvmauth/client/ut/files/' + shutil.copyfile(path + 'public_keys', './public_keys') + shutil.copyfile(path + 'service_tickets', './service_tickets') + + c = None + log_stream.truncate(0) + try: + s = tp2.TvmApiClientSettings( + self_client_id=100500, + enable_service_ticket_checking=True, + enable_user_ticket_checking=tp2.BlackboxEnv.Test, + self_secret='qwerty', + dsts={'dest': 19}, + ) + s.set_disk_cache_dir('./') + + c = tp2.TvmClient(s) + time.sleep(1) + + exp = "File './service_tickets' was successfully read\n" + exp += "Got 1 service ticket(s) from disk\n" + exp += "Cache was updated with 1 service ticket(s): 2050-01-01T00:00:00.000000Z\n" + exp += "File './public_keys' was successfully read\n" + exp += "Cache was updated with public keys: 2050-01-01T00:00:00.000000Z\n" + exp += "File './retry_settings' does not exist\n" + exp += "Thread-worker started\n" + assert exp == get_log_stream_value() + + st = c.status + assert st == tp2.TvmClientStatus.Ok + assert tp2.TvmClient.status_to_string(st) == 'TvmClient cache is ok' + + # assert c.last_update_time_of_public_keys == datetime.strptime('2050-01-01 03:00:00', '%Y-%m-%d %H:%M:%S') + # assert c.last_update_time_of_service_tickets == datetime.strptime('2050-01-01 03:00:01', '%Y-%m-%d %H:%M:%S') + + assert '3:serv:CBAQ__________9_IgYIKhCUkQY:CX' == c.get_service_ticket_for('dest') + assert '3:serv:CBAQ__________9_IgYIKhCUkQY:CX' == c.get_service_ticket_for(alias='dest') + assert '3:serv:CBAQ__________9_IgYIKhCUkQY:CX' == c.get_service_ticket_for(client_id=19) + with pytest.raises(BrokenTvmClientSettings): + c.get_service_ticket_for('dest2') + with pytest.raises(BrokenTvmClientSettings): + c.get_service_ticket_for(client_id=20) + with pytest.raises(TvmException): + c.get_service_ticket_for() + + assert c.check_service_ticket(SRV_TICKET) + with pytest.raises(TicketParsingException): + c.check_service_ticket(PROD_TICKET) + with pytest.raises(TicketParsingException): + c.check_service_ticket(TEST_TICKET) + + assert c.check_user_ticket(TEST_TICKET) + with pytest.raises(TicketParsingException): + c.check_user_ticket(PROD_TICKET) + with pytest.raises(TicketParsingException): + c.check_user_ticket(SRV_TICKET) + + with pytest.raises(TicketParsingException): + assert c.check_user_ticket(TEST_TICKET, overrided_bb_env=tp2.BlackboxEnv.Prod) + c.check_user_ticket(PROD_TICKET, overrided_bb_env=tp2.BlackboxEnv.Prod) + + except Exception: + print(get_log_stream_value()) + raise + finally: + print('==test_full_client: 1') + if c is not None: + c.stop() + print('==test_full_client: 2') + + +def test_getting_client_without_aliases(): + path = yc.source_path() + '/library/cpp/tvmauth/client/ut/files/' + shutil.copyfile(path + 'public_keys', './public_keys') + shutil.copyfile(path + 'service_tickets', './service_tickets') + + c = None + log_stream.truncate(0) + try: + s = tp2.TvmApiClientSettings( + self_client_id=100500, + enable_service_ticket_checking=True, + enable_user_ticket_checking=tp2.BlackboxEnv.Test, + self_secret='qwerty', + dsts=[19], + ) + s.set_disk_cache_dir('./') + + c = tp2.TvmClient(s) + time.sleep(1) + + exp = "File './service_tickets' was successfully read\n" + exp += "Got 1 service ticket(s) from disk\n" + exp += "Cache was updated with 1 service ticket(s): 2050-01-01T00:00:00.000000Z\n" + exp += "File './public_keys' was successfully read\n" + exp += "Cache was updated with public keys: 2050-01-01T00:00:00.000000Z\n" + exp += "File './retry_settings' does not exist\n" + exp += "Thread-worker started\n" + assert exp == get_log_stream_value() + + st = c.status + assert st == tp2.TvmClientStatus.Ok + assert tp2.TvmClient.status_to_string(st) == 'TvmClient cache is ok' + + # assert c.last_update_time_of_public_keys == datetime.strptime('2050-01-01 03:00:00', '%Y-%m-%d %H:%M:%S') + # assert c.last_update_time_of_service_tickets == datetime.strptime('2050-01-01 03:00:01', '%Y-%m-%d %H:%M:%S') + + assert '3:serv:CBAQ__________9_IgYIKhCUkQY:CX' == c.get_service_ticket_for(client_id=19) + with pytest.raises(BrokenTvmClientSettings): + c.get_service_ticket_for(client_id=20) + + with pytest.raises(BrokenTvmClientSettings): + c.get_service_ticket_for('dest') + with pytest.raises(BrokenTvmClientSettings): + c.get_service_ticket_for(alias='dest') + with pytest.raises(BrokenTvmClientSettings): + c.get_service_ticket_for('dest2') + + except Exception: + print(get_log_stream_value()) + raise + finally: + print('==test_getting_client_without_aliases: 1') + if c is not None: + c.stop() + print('==test_getting_client_without_aliases: 2') + + +def test_checking_client(): + path = yc.source_path() + '/library/cpp/tvmauth/client/ut/files/' + shutil.copyfile(path + 'public_keys', './public_keys') + + c = None + log_stream.truncate(0) + try: + s = tp2.TvmApiClientSettings( + enable_user_ticket_checking=tp2.BlackboxEnv.Test, + ) + s.set_disk_cache_dir('./') + c = tp2.TvmClient(s) + assert c.status == tp2.TvmClientStatus.Ok + + with pytest.raises(BrokenTvmClientSettings): + c.check_service_ticket(SRV_TICKET) + assert c.check_user_ticket(TEST_TICKET) + + print('==test_checking_client: 1') + c.stop() + print('==test_checking_client: 2') + + s = tp2.TvmApiClientSettings( + self_client_id=100500, + enable_service_ticket_checking=True, + ) + s.set_disk_cache_dir('./') + c = tp2.TvmClient(s) + assert c.status == tp2.TvmClientStatus.Ok + + with pytest.raises(BrokenTvmClientSettings): + c.check_user_ticket(TEST_TICKET) + assert c.check_service_ticket(SRV_TICKET) + + print('==test_checking_client: 3') + c.stop() + print('==test_checking_client: 4') + except Exception: + print(get_log_stream_value()) + raise + finally: + print('==test_checking_client: 5') + if c is not None: + c.stop() + print('==test_checking_client: 6') + + +class myHTTPServer(SocketServer.ForkingMixIn, BaseHTTPServer.HTTPServer): + address_family = socket.AF_INET6 + pass + + +class myHandler(BaseHTTPServer.BaseHTTPRequestHandler): + def log_message(self, format, *args): + sys.stdout.write("%s - - [%s] %s\n" % (self.address_string(), self.log_date_time_string(), format % args)) + + +def test_user_bad_api(): + myHandler.log_message + pm = network.PortManager() + port = pm.get_tcp_port(8080) + server = myHTTPServer(('', port), myHandler) + thread = Process(target=server.serve_forever) + thread.start() + + log_stream.truncate(0) + try: + s = tp2.TvmApiClientSettings( + enable_user_ticket_checking=tp2.BlackboxEnv.Test, + ) + s.__set_localhost(port) + + with pytest.raises(RetriableException): + tp2.TvmClient(s) + except Exception: + print(get_log_stream_value()) + raise + finally: + thread.terminate() + + +def test_service_bad_api(): + pm = network.PortManager() + port = pm.get_tcp_port(8080) + server = myHTTPServer(('', port), myHandler) + thread = Process(target=server.serve_forever) + thread.start() + + log_stream.truncate(0) + try: + s = tp2.TvmApiClientSettings( + self_client_id=100500, + enable_service_ticket_checking=True, + ) + s.__set_localhost(port) + + with pytest.raises(RetriableException): + tp2.TvmClient(s) + except Exception: + print(get_log_stream_value()) + raise + finally: + thread.terminate() + + +def test_tickets_bad_api(): + pm = network.PortManager() + port = pm.get_tcp_port(8080) + server = myHTTPServer(('', port), myHandler) + thread = Process(target=server.serve_forever) + thread.start() + + log_stream.truncate(0) + try: + s = tp2.TvmApiClientSettings( + self_client_id=100500, + self_secret='qwerty', + dsts={'dest': 19}, + ) + s.__set_localhost(port) + + with pytest.raises(RetriableException): + tp2.TvmClient(s) + except Exception: + print(get_log_stream_value()) + raise + finally: + thread.terminate() + + +class myGoodHandler(myHandler): + def do_GET(self): + if self.path.startswith("/2/keys"): + self.send_response(200) + self.send_header('Content-type', 'text/plain') + self.send_header('Content-Length', len(tp2u.TVMKNIFE_PUBLIC_KEYS)) + self.end_headers() + self.wfile.write(tp2u.TVMKNIFE_PUBLIC_KEYS.encode('utf-8')) + return + + self.send_error(404, 'Not Found: %s' % self.path) + + def do_POST(self): + if self.path.startswith("/2/ticket"): + + self.send_response(200) + self.send_header('Content-type', 'application/json') + self.send_header('Content-Length', len(TVM_RESP)) + self.end_headers() + self.wfile.write(TVM_RESP) + return + + self.send_error(404, 'Not Found: %s' % self.path) + + +def test_ok_api(): + pm = network.PortManager() + port = pm.get_tcp_port(8080) + server = myHTTPServer(('', port), myGoodHandler) + thread = Process(target=server.serve_forever) + thread.start() + + c = None + log_stream.truncate(0) + try: + s = tp2.TvmApiClientSettings( + self_client_id=100500, + enable_service_ticket_checking=True, + self_secret='qwerty', + dsts={'dest': 19}, + ) + s.__set_localhost(port) + + c = tp2.TvmClient(s) + + time.sleep(1) + assert c.status == tp2.TvmClientStatus.Ok + + actual_log = get_log_stream_value() + assert actual_log.count('Thread-worker started') == 1 + + print('==test_ok_api: 1') + c.stop() + print('==test_ok_api: 2') + + with pytest.raises(NonRetriableException): + c.status + except Exception: + print(get_log_stream_value()) + raise + finally: + thread.terminate() + if c is not None: + c.stop() + + +AUTH_TOKEN = 'some string' +META = """{ +"bb_env" : "ProdYaTeam", +"tenants" : [ + { + "self": { + "alias" : "me", + "client_id": 100500 + }, + "dsts" : [ + { + "alias" : "bbox", + "client_id": 242 + }, + { + "alias" : "pass_likers", + "client_id": 11 + } + ] + }, + { + "self": { + "alias" : "push-client", + "client_id": 100501 + }, + "dsts" : [ + { + "alias" : "pass_likers", + "client_id": 100502 + } + ] + }, + { + "self": { + "alias" : "something_else", + "client_id": 100503 + }, + "dsts" : [ + ] + } +] +}""".encode( + 'utf-8' +) +TICKETS_ME = """{ + "pass_likers": { + "ticket": "3:serv:CBAQ__________9_IgYIKhCUkQY:CX", + "tvm_id": 11 + }, + "bbox": { + "ticket": "3:serv:CBAQ__________9_IgcIlJEGEPIB:N7luw0_rVmBosTTI130jwDbQd0-cMmqJeEl0ma4ZlIo_mHXjBzpOuMQ3A9YagbmOBOt8TZ_gzGvVSegWZkEeB24gM22acw0w-RcHaQKrzSOA5Zq8WLNIC8QUa4_WGTlAsb7R7eC4KTAGgouIquNAgMBdTuGOuZHnMLvZyLnOMKc", + "tvm_id": 242 + } +}""".encode( # noqa + 'utf-8' +) +BIRTH_TIME = 14380887840 + + +class tvmtoolGoodHandler(myHandler): + def do_GET(self): + if self.path.startswith("/tvm/ping"): + self.send_response(200) + self.end_headers() + self.wfile.write("OK".encode('utf-8')) + return + + if self.headers.get('Authorization', '') != AUTH_TOKEN: + self.send_error(401, 'Unauthorized') + return + + if self.path.startswith("/tvm/keys"): + self.send_response(200) + self.send_header('Content-type', 'text/plain') + self.send_header('Content-Length', len(tp2u.TVMKNIFE_PUBLIC_KEYS)) + self.send_header('X-Ya-Tvmtool-Data-Birthtime', BIRTH_TIME) + self.end_headers() + self.wfile.write(tp2u.TVMKNIFE_PUBLIC_KEYS.encode('utf-8')) + return + + if self.path.startswith("/tvm/tickets"): + self.send_response(200) + self.send_header('Content-type', 'application/json') + self.send_header('Content-Length', len(TICKETS_ME)) + self.send_header('X-Ya-Tvmtool-Data-Birthtime', BIRTH_TIME) + self.end_headers() + self.wfile.write(TICKETS_ME) + return + + if self.path.startswith("/tvm/private_api/__meta__"): + self.send_response(200) + self.send_header('Content-type', 'application/json') + self.send_header('Content-Length', len(META)) + self.end_headers() + self.wfile.write(META) + return + + self.send_error(404, 'Not Found: %s' % self.path) + + +def test_bad_tool(): + pm = network.PortManager() + port = pm.get_tcp_port(8080) + server = myHTTPServer(('', port), tvmtoolGoodHandler) + thread = Process(target=server.serve_forever) + thread.start() + + log_stream.truncate(0) + try: + s = tp2.TvmToolClientSettings( + self_alias='no one', + auth_token=AUTH_TOKEN, + port=port, + ) + + print("=====test_bad_tool 01") + with pytest.raises(NonRetriableException): + tp2.TvmClient(s) + print("=====test_bad_tool 02") + + exp = "Meta info fetched from localhost:%d\n" % port + assert get_log_stream_value() == exp + log_stream.truncate(0) + + s = tp2.TvmToolClientSettings( + self_alias='me', + auth_token=AUTH_TOKEN, + port=0, + ) + + with pytest.raises(NonRetriableException): + tp2.TvmClient(s) + + s = tp2.TvmToolClientSettings( + self_alias='me', + auth_token=AUTH_TOKEN, + hostname='::1', + port=port, + override_bb_env=tp2.BlackboxEnv.Stress, + ) + + assert get_log_stream_value() == '' + + with pytest.raises(BrokenTvmClientSettings): + tp2.TvmClient(s) + + exp = "Meta info fetched from ::1:%d\n" % port + exp += "Meta: self_tvm_id=100500, bb_env=ProdYateam, idm_slug=<NULL>, dsts=[(pass_likers:11)(bbox:242)]\n" + assert get_log_stream_value() == exp + except Exception: + print(get_log_stream_value()) + raise + finally: + thread.terminate() + + +def test_ok_tool(): + pm = network.PortManager() + port = pm.get_tcp_port(8080) + server = myHTTPServer(('', port), tvmtoolGoodHandler) + thread = Process(target=server.serve_forever) + thread.start() + + log_stream.truncate(0) + c = None + try: + s = tp2.TvmToolClientSettings( + self_alias='me', + auth_token=AUTH_TOKEN, + port=port, + ) + + c = tp2.TvmClient(s) + + assert c.check_service_ticket(SRV_TICKET) + assert c.check_user_ticket(PROD_YATEAM_TICKET) + with pytest.raises(TvmException): + c.check_user_ticket(TEST_YATEAM_TICKET) + + assert c.status == tp2.TvmClientStatus.Ok + + assert ( + '3:serv:CBAQ__________9_IgcIlJEGEPIB:N7luw0_rVmBosTTI130jwDbQd0-cMmqJeEl0ma4ZlIo_mHXjBzpOuMQ3A9YagbmOBOt8TZ_gzGvVSegWZkEeB24gM22acw0w-RcHaQKrzSOA5Zq8WLNIC8QUa4_WGTlAsb7R7eC4KTAGgouIquNAgMBdTuGOuZHnMLvZyLnOMKc' # noqa + == c.get_service_ticket_for('bbox') + ) + assert '3:serv:CBAQ__________9_IgYIKhCUkQY:CX' == c.get_service_ticket_for(client_id=11) + + c.stop() + + exp = "Meta info fetched from localhost:%d\n" % port + exp += "Meta: self_tvm_id=100500, bb_env=ProdYateam, idm_slug=<NULL>, dsts=[(pass_likers:11)(bbox:242)]\n" + exp += "Tickets fetched from tvmtool: 2425-09-17T11:04:00.000000Z\n" + exp += "Public keys fetched from tvmtool: 2425-09-17T11:04:00.000000Z\n" + exp += "Thread-worker started\n" + exp += "Thread-worker stopped\n" + assert get_log_stream_value() == exp + + s = tp2.TvmToolClientSettings( + self_alias='me', + auth_token=AUTH_TOKEN, + port=port, + override_bb_env=tp2.BlackboxEnv.Prod, + ) + + c = tp2.TvmClient(s) + + assert c.check_service_ticket(SRV_TICKET) + assert c.check_user_ticket(PROD_TICKET) + with pytest.raises(TvmException): + c.check_user_ticket(TEST_TICKET) + + c.stop() + except Exception: + print(get_log_stream_value()) + raise + finally: + thread.terminate() + print('==test_ok_tool: 1') + if c is not None: + c.stop() + print('==test_ok_tool: 2') + + +def test_fake_mock(): + fake_tvm_client = mock.Mock() + with TvmClientPatcher(fake_tvm_client): + fake_tvm_client.get_service_ticket_for.return_value = 'ololo' + assert 'ololo' == tp2.TvmClient().get_service_ticket_for() + fake_tvm_client.check_service_ticket.return_value = ticket_parser2.low_level.ServiceContext( + 100500, 'qwerty', tp2u.TVMKNIFE_PUBLIC_KEYS + ).check(SRV_TICKET) + assert 123 == tp2.TvmClient().check_service_ticket('').src + + with TvmClientPatcher(MockedTvmClient()) as p: + p.get_mocked_tvm_client().check_service_ticket = mock.Mock( + side_effect=TicketParsingException("Unsupported version", tp2.Status.UnsupportedVersion, "2:err"), + ) + + c = tp2.TvmClient() + assert tp2.TvmClientStatus.Ok == c.status + with pytest.raises(TicketParsingException): + c.check_service_ticket(SRV_TICKET) + + m = MockedTvmClient() + m.get_service_ticket_for = mock.Mock( + side_effect=['SERVICE_TICKET_FOR_MY_FIRST_CALL', 'SERVICE_TICKET_FOR_MY_SECOND_CALL'], + ) + with TvmClientPatcher(m): + c = tp2.TvmClient() + assert tp2.TvmClientStatus.Ok == c.status + assert 'SERVICE_TICKET_FOR_MY_FIRST_CALL' == c.get_service_ticket_for() + assert 'SERVICE_TICKET_FOR_MY_SECOND_CALL' == c.get_service_ticket_for() + + +def test_default_mock(): + with TvmClientPatcher(): + c = tp2.TvmClient() + assert tp2.TvmClientStatus.Ok == c.status + assert 123 == c.check_service_ticket(SRV_TICKET).src + assert 123 == c.check_user_ticket(TEST_TICKET).default_uid + assert 'Some service ticket' == c.get_service_ticket_for("foo") + assert 'TvmClient cache is ok' == c.status_to_string(c.status) + + c.stop() + with pytest.raises(NonRetriableException): + c.status + with pytest.raises(NonRetriableException): + c.check_service_ticket(SRV_TICKET) + with pytest.raises(NonRetriableException): + c.check_user_ticket(TEST_TICKET) + with pytest.raises(NonRetriableException): + c.get_service_ticket_for("foo") + + +def test_mock(): + with TvmClientPatcher(MockedTvmClient(self_client_id=100501)): + c = tp2.TvmClient() + assert tp2.TvmClientStatus.Ok == c.status + with pytest.raises(TicketParsingException): + c.check_service_ticket(SRV_TICKET) + assert 123 == c.check_user_ticket(TEST_TICKET).default_uid + assert 'Some service ticket' == c.get_service_ticket_for("foo") diff --git a/library/python/deprecated/ticket_parser2/src/ut/test_common.py b/library/python/deprecated/ticket_parser2/src/ut/test_common.py new file mode 100644 index 0000000000..63759eba39 --- /dev/null +++ b/library/python/deprecated/ticket_parser2/src/ut/test_common.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python +from __future__ import print_function + +import ticket_parser2 as tp2 +from ticket_parser2 import BlackboxClientId + + +def test_version(): + assert tp2.__version__[:-5] == 'py_' + + +def test_blackbox_client_id(): + assert BlackboxClientId.Prod.value == '222' + assert BlackboxClientId.Test.value == '224' + assert BlackboxClientId.ProdYateam.value == '223' + assert BlackboxClientId.TestYateam.value == '225' + assert BlackboxClientId.Stress.value == '226' + assert BlackboxClientId.Mimino.value == '239' diff --git a/library/python/deprecated/ticket_parser2/src/ut/test_service.py b/library/python/deprecated/ticket_parser2/src/ut/test_service.py new file mode 100644 index 0000000000..3976632c7c --- /dev/null +++ b/library/python/deprecated/ticket_parser2/src/ut/test_service.py @@ -0,0 +1,242 @@ +#!/usr/bin/env python +from __future__ import print_function + +import pytest +from ticket_parser2 import ( + ServiceTicket, + Status, +) +from ticket_parser2.low_level import ServiceContext +from ticket_parser2.exceptions import ( + ContextException, + EmptyTvmKeysException, + MalformedTvmKeysException, + MalformedTvmSecretException, + TicketParsingException, +) +import ticket_parser2.unittest as tp2u + + +EMPTY_TVM_KEYS = ( + '1:CpgCCpMCCAEQABqIAjCCAQQCggEAcLEXeH67FQESFUn4_7wnX7wN0PUrBoUsm3QQ4W5vC-qz6sXaEjSwnTV8w1o-z6X9KPL' + 'lhzMQvuS38NCNfK4uvJ4Zvfp3YsXJ25-rYtbnrYJHNvHohD-kPCCw_yZpMp21JdWigzQGuV7CtrxUhF-NNrsnUaJrE5-OpEWN' + 't4X6nCItKIYeVcSK6XJUbEWbrNCRbvkSc4ak2ymFeMuHYJVjxh4eQbk7_ZPzodP0WvF6eUYrYeb42imVEOR8ofVLQWE5DVnb1' + 'z_TqZm4i1XkS7jMwZuBxBRw8DGdYei0lT_sAf7KST2jC0590NySB3vsBgWEVs1OdUUWA6r-Dvx9dsOQtSCVkQYQAAqZAgqUAg' + 'gCEAAaiQIwggEFAoIBAQDhEBM5-6YsPWfogKtbluJoCX1WV2KdzOaQ0-OlRbBzeCzw-eQKu12c8WakHBbeCMd1I1TU64SDkDo' + 'rWjXGIa_2xT6N3zzNAE50roTbPCcmeQrps26woTYfYIuqDdoxYKZNr0lvNLLW47vBr7EKqo1S4KSj7aXK_XYeEvUgIgf3nVIc' + 'Nrio7VTnFmGGVQCepaL1Hi1gN4yIXjVZ06PBPZ-DxSRu6xOGbFrfKMJeMPs7KOyE-26Q3xOXdTIa1X-zYIucTd_bxUCL4BVbw' + 'W2AvbbFsaG7ISmVdGu0XUTmhXs1KrEfUVLRJhE4Dx99hAZXm1_HlYMUeJcMQ_oHOhV94ENFIJaRBhACCpYBCpEBCAMQABqGAT' + 'CBgwKBgF9t2YJGAJkRRFq6fWhi3m1TFW1UOE0f6ZrfYhHAkpqGlKlh0QVfeTNPpeJhi75xXzCe6oReRUm-0DbqDNhTShC7uGU' + 'v1INYnRBQWH6E-5Fc5XrbDFSuGQw2EYjNfHy_HefHJXxQKAqPvxBDKMKkHgV58WtM6rC8jRi9sdX_ig2NIJeRBhABCpYBCpEB' + 'CAQQABqGATCBgwKBgGB4d6eLGUBv-Q6EPLehC4S-yuE2HB-_rJ7WkeYwyp-xIPolPrd-PQme2utHB4ZgpXHIu_OFksDe_0bPg' + 'ZniNRSVRbl7W49DgS5Ya3kMfrYB4DnF5Fta5tn1oV6EwxYD4JONpFTenOJALPGTPawxXEfon_peiHOSBuQMu3_Vn-l1IJiRBh' + 'ADCpcBCpIBCAUQABqHATCBhAKBgQCTJMKIfmfeZpaI7Q9rnsc29gdWawK7TnpVKRHws1iY7EUlYROeVcMdAwEqVM6f8BVCKLG' + 'gzQ7Gar_uuxfUGKwqEQzoppDraw4F75J464-7D5f6_oJQuGIBHZxqbMONtLjBCXRUhQW5szBLmTQ_R3qaJb5vf-h0APZfkYhq' + '1cTttSCZkQYQBAqWAQqRAQgLEAAahgEwgYMCgYBvvGVH_M2H8qxxv94yaDYUTWbRnJ1uiIYc59KIQlfFimMPhSS7x2tqUa2-h' + 'I55JiII0Xym6GNkwLhyc1xtWChpVuIdSnbvttbrt4weDMLHqTwNOF6qAsVKGKT1Yh8yf-qb-DSmicgvFc74mBQm_6gAY1iQsf' + '33YX8578ClhKBWHSCVkQYQAAqXAQqSAQgMEAAahwEwgYQCgYEAkuzFcd5TJu7lYWYe2hQLFfUWIIj91BvQQLa_Thln4YtGCO8' + 'gG1KJqJm-YlmJOWQG0B7H_5RVhxUxV9KpmFnsDVkzUFKOsCBaYGXc12xPVioawUlAwp5qp3QQtZyx_se97YIoLzuLr46UkLcL' + 'nkIrp-Jo46QzYi_QHq45WTm8MQ0glpEGEAIKlwEKkgEIDRAAGocBMIGEAoGBAIUzbxOknXf_rNt17_ir8JlWvrtnCWsQd1MAn' + 'l5mgArvavDtKeBYHzi5_Ak7DHlLzuA6YE8W175FxLFKpN2hkz-l-M7ltUSd8N1BvJRhK4t6WffWfC_1wPyoAbeSN2Yb1jygtZ' + 'JQ8wGoXHcJQUXiMit3eFNyylwsJFj1gzAR4JCdIJeRBhABCpYBCpEBCA4QABqGATCBgwKBgFMcbEpl9ukVR6AO_R6sMyiU11I' + '8b8MBSUCEC15iKsrVO8v_m47_TRRjWPYtQ9eZ7o1ocNJHaGUU7qqInFqtFaVnIceP6NmCsXhjs3MLrWPS8IRAy4Zf4FKmGOx3' + 'N9O2vemjUygZ9vUiSkULdVrecinRaT8JQ5RG4bUMY04XGIwFIJiRBhADCpYBCpEBCA8QABqGATCBgwKBgGpCkW-NR3li8GlRv' + 'qpq2YZGSIgm_PTyDI2Zwfw69grsBmPpVFW48Vw7xoMN35zcrojEpialB_uQzlpLYOvsMl634CRIuj-n1QE3-gaZTTTE8mg-AR' + '4mcxnTKThPnRQpbuOlYAnriwiasWiQEMbGjq_HmWioYYxFo9USlklQn4-9IJmRBhAE' +) +INVALID_SERVICE_TICKET = ( + '3:serv:CBAQ__________9_czEaCGJiOnNlc3My:WUPx1cTf05fjD1exB35T5j2DCHWH1YaLJon_a4rN-D7JfXHK1Ai4wM4uS' + 'fboHD9xmGQH7extqtlEk1tCTCGm5qbRVloJwWzCZBXo3zKX6i1oBYP_89WcjCNPVe1e8jwGdLsnu6PpxL5cn0xCksiStILH5U' + 'mDR6xfkJdnmMG94o8' +) +MALFORMED_TVM_KEYS = ( + '1:CpgCCpMCCAEQABqIAjCCAQQCggEAcLEXeH67FQESFUn4_7wnX7wN0PUrBoUsm3QQ4W5vC-qz6sXaEjSwnTV8w1o-z6X9KPL' + 'lhzMQvuS38NCNfK4uvJ4Zvfp3YsXJ25-rYtbnrYJHNvHohD-kPCCw_yZpMp21JdWigzQGuV7CtrxUhF-NNrsnUaJrE5-OpEWN' + 't4X6nCItKIYeVcSK6XJUbEWbrNCRbvkSc4ak2ymFeMuHYJVjxh4eQbk7_ZPzodP0WvF6eUYrYeb42imVEOR8ofVLQWE5DVnb1' + 'z_TqZm4i1XkS7jMwZuBxBRw8DGdYei0lT_sAf7KST2jC0590NySB3vsBgWEVs1OdUUWA6r-Dvx9dsOQtSCVkQYQAAqZAgqUAg' + 'gCEAAaiQIwggEFAoIBAQDhEBM5-6YsPWfogKtbluJoCX1WV2KdzOaQ0-OlRbBzeCzw-eQKu12c8WakHBbeCMd1I1TU64SDkDo' + 'rWjXGIa_2xT6N3zzNAE50roTbPCcmeQrps26woTYfYIuqDdoxYKZNr0lvNLLW47vBr7EKqo1S4KSj7aXK_XYeEvUgIgf3nVIc' + 'Nrio7VTnFmGGVQCepaL1Hi1gN4yIXjVZ06PBPZ-DxSRu6xOGbFrfKMJeMPs7KOyE-26Q3xOXdTIa1X-zYIucTd_bxUCL4BVbw' + 'W2AvbbFsaG7ISmVdGu0XUTmhXs1KrEfUVLRJhE4Dx99hAZXm1_HlYMUeJcMQ_oHOhV94ENFIJaRBhACCpYBCpEBCAMQABqGAT' + 'CBgwKBgF9t2YJGAJkRRFq6fWhi3m1TFW1UOE0f6ZrfYhHAkpqGlKlh0QVfeTNPpeJhi75xXzCe6oReRUm-0DbqDNhTShC7uGU' + 'v1INYnRBQWH6E-5Fc5XrbDFSuGQw2EYjNfHy_HefHJXxQKAqPvxBDKMKkHgV58WtM6rC8jRi9sdX_ig2NIJeRBhABCpYBCpEB' + 'CAQQABqGATCBgwKBgGB4d6eLGUBv-Q6EPLehC4S-yuE2HB-_rJ7WkeYwyp-xIPolPrd-PQme2utHB4ZgpXHIu_OFksDe_0bPg' + 'ZniNRSVRbl7W49DgS5Ya3kMfrYB4DnF5Fta5tn1oV6EwxYD4JONpFTenOJALPGTPawxXEfon_peiHOSBuQMu3_Vn-l1IJiRBh' + 'ADCpcBCpIBCAUQABqHATCBhAKBgQCTJMKIfmfeZpaI7Q9rnsc29gdWawK7TnpVKRHws1iY7EUlYROeVcMdAwEqVM6f8BVCKLG' + 'gzQ7Gar_uuxfUGKwqEQzoppDraw4F75J464-7D5f6_oJQuGIBHZxqbMONtLjBCXRUhQW5szBLmTQ_R3qaJb5vf-h0APZfkYhq' + '1cTttSCZkQYQBAqWAQqRAQgLEAAahgEwgYMCgYBvvGVH_M2H8qxxv94yaDYUTWbRnJ1uiIYc59KIQlfFimMPhSS7x2tqUa2-h' + 'I55JiII0Xym6GNkwLhyc1xtWChpVuIdSnbvttbrt4weDMLHqTwNOF6qAsVKGKT1Yh8yf-qb-DSmicgvFc74mBQm_6gAY1iQsf' + '33YX8578ClhKBWHSCVkQYQAAqXAQqSAQgMEAAahwEwgYQCgYEAkuzFcd5TJu7lYWYe2hQLFfUWIIj91BvQQLa_Thln4YtGCO8' + 'gG1KJqJm-YlmJOWQG0B7H_5RVhxUxV9KpmFnsDVkzUFKOsCBaYGXc12xPVioawUlAwp5qp3QQtZyx_se97YIoLzuLr46UkLcL' + 'nkIrp-Jo46QzYi_QHq45WTm8MQ0glpEGEAIKlwEKkgEIDRAAGocBMIGEAoGBAIUzbxOknXf_rNt17_ir8JlWvrtnCWsQd1MAn' + 'l5mgArvavDtKeBYHzi5_Ak7DHlLzuA6YE8W175FxLFKpN2hkz-l-M7ltUSd8N1BvJRhK4t6WffWfC_1wPyoAbeSN2Yb1jygtZ' + 'JQ8wGoXHcJQUXiMit3eFNyylwsJFj1gzAR4JCdIJeRBhABCpYBCpEBCA4QABqGATCBgwKBgFMcbEpl9ukVR6AO_R6sMyiU11I' + '8b8MBSUCEC15iKsrVO8v_m47_TRRjWPYtQ9eZ7o1ocNJHaGUU7qqInFqtFaVnIceP6NmCsXhjs3MLrWPS8IRAy4Zf4FKmGOx3' + 'N9O2vemjUygZ9vUiSkULdVrecinRaT8JQ5RG4bUMY04XGIwFIJiRBhADCpYBCpEBCA8QABqGATCBgwKBgGpCkW-NR3li8GlRv' + 'qpq2YZGSIgm_PTyDI2Zwfw69grsBmPpVFW48Vw7xoMN35zcrojEpialB_uQzlpLYOvsMl634CRIuj-n1QE3-gaZTTTE8mg-AR' + '4mcxnTKThPnRQpbuOlYAnriwiasWiQEMbGjq_HmWioYYxFo9USlklQn4-9IJmRBhAEEpUBCpIBCAYQABqHATCBhAKBgQCoZkF' + 'Gm9oLTqjeXZAq6j5S6i7K20V0lNdBBLqfmFBIRuTkYxhs4vUYnWjZrKRAd5bp6_py0csmFmpl_5Yh0b-2pdo_E5PNP7LGRzKy' + 'KSiFddyykKKzVOazH8YYldDAfE8Z5HoS9e48an5JsPg0jr-TPu34DnJq3yv2a6dqiKL9zSCakQYSlQEKkgEIEBAAGocBMIGEA' + 'oGBALhrihbf3EpjDQS2sCQHazoFgN0nBbE9eesnnFTfzQELXb2gnJU9enmV_aDqaHKjgtLIPpCgn40lHrn5k6mvH5OdedyI6c' + 'CzE-N-GFp3nAq0NDJyMe0fhtIRD__CbT0ulcvkeow65ubXWfw6dBC2gR_34rdMe_L_TGRLMWjDULbNIJ' +) +MALFORMED_TVM_SECRET = 'adcvxcv./-+' +OUR_ID = 28 +SECRET = 'GRMJrKnj4fOVnvOqe-WyD1' +SRC_ID = 229 + +UNSUPPORTED_VERSION_SERVICE_TICKET = ( + '2:serv:CBAQ__________9_IhkI5QEQHBoIYmI6c2VzczEaCGJiOnNlc3My:WUPx1cTf05fjD1exB35T5j2DCHWH1YaLJon_a' + '4rN-D7JfXHK1Ai4wM4uSfboHD9xmGQH7extqtlEk1tCTCGm5qbRVloJwWzCZBXo3zKX6i1oBYP_89WcjCNPVe1e8jwGdLsnu6' + 'PpxL5cn0xCksiStILH5UmDR6xfkJdnmMG94o8' +) +VALID_SERVICE_TICKET_1 = ( + '3:serv:CBAQ__________9_IhkI5QEQHBoIYmI6c2VzczEaCGJiOnNlc3My:WUPx1cTf05fjD1exB35T5j2DCHWH1YaLJon_a' + '4rN-D7JfXHK1Ai4wM4uSfboHD9xmGQH7extqtlEk1tCTCGm5qbRVloJwWzCZBXo3zKX6i1oBYP_89WcjCNPVe1e8jwGdLsnu6' + 'PpxL5cn0xCksiStILH5UmDR6xfkJdnmMG94o8' +) +VALID_SERVICE_TICKET_SIGNLESS_1 = '3:serv:CBAQ__________9_IhkI5QEQHBoIYmI6c2VzczEaCGJiOnNlc3My:' +VALID_SERVICE_TICKET_2 = ( + '3:serv:CBAQ__________9_IskICOUBEBwaCGJiOnNlc3MxGgliYjpzZXNzMTAaCmJiOnNlc3MxMDAaCWJiOnNlc3MxMRoJYm' + 'I6c2VzczEyGgliYjpzZXNzMTMaCWJiOnNlc3MxNBoJYmI6c2VzczE1GgliYjpzZXNzMTYaCWJiOnNlc3MxNxoJYmI6c2VzczE' + '4GgliYjpzZXNzMTkaCGJiOnNlc3MyGgliYjpzZXNzMjAaCWJiOnNlc3MyMRoJYmI6c2VzczIyGgliYjpzZXNzMjMaCWJiOnNl' + 'c3MyNBoJYmI6c2VzczI1GgliYjpzZXNzMjYaCWJiOnNlc3MyNxoJYmI6c2VzczI4GgliYjpzZXNzMjkaCGJiOnNlc3MzGgliY' + 'jpzZXNzMzAaCWJiOnNlc3MzMRoJYmI6c2VzczMyGgliYjpzZXNzMzMaCWJiOnNlc3MzNBoJYmI6c2VzczM1GgliYjpzZXNzMz' + 'YaCWJiOnNlc3MzNxoJYmI6c2VzczM4GgliYjpzZXNzMzkaCGJiOnNlc3M0GgliYjpzZXNzNDAaCWJiOnNlc3M0MRoJYmI6c2V' + 'zczQyGgliYjpzZXNzNDMaCWJiOnNlc3M0NBoJYmI6c2VzczQ1GgliYjpzZXNzNDYaCWJiOnNlc3M0NxoJYmI6c2VzczQ4Ggli' + 'YjpzZXNzNDkaCGJiOnNlc3M1GgliYjpzZXNzNTAaCWJiOnNlc3M1MRoJYmI6c2VzczUyGgliYjpzZXNzNTMaCWJiOnNlc3M1N' + 'BoJYmI6c2VzczU1GgliYjpzZXNzNTYaCWJiOnNlc3M1NxoJYmI6c2VzczU4GgliYjpzZXNzNTkaCGJiOnNlc3M2GgliYjpzZX' + 'NzNjAaCWJiOnNlc3M2MRoJYmI6c2VzczYyGgliYjpzZXNzNjMaCWJiOnNlc3M2NBoJYmI6c2VzczY1GgliYjpzZXNzNjYaCWJ' + 'iOnNlc3M2NxoJYmI6c2VzczY4GgliYjpzZXNzNjkaCGJiOnNlc3M3GgliYjpzZXNzNzAaCWJiOnNlc3M3MRoJYmI6c2Vzczcy' + 'GgliYjpzZXNzNzMaCWJiOnNlc3M3NBoJYmI6c2Vzczc1GgliYjpzZXNzNzYaCWJiOnNlc3M3NxoJYmI6c2Vzczc4GgliYjpzZ' + 'XNzNzkaCGJiOnNlc3M4GgliYjpzZXNzODAaCWJiOnNlc3M4MRoJYmI6c2VzczgyGgliYjpzZXNzODMaCWJiOnNlc3M4NBoJYm' + 'I6c2Vzczg1GgliYjpzZXNzODYaCWJiOnNlc3M4NxoJYmI6c2Vzczg4GgliYjpzZXNzODkaCGJiOnNlc3M5GgliYjpzZXNzOTA' + 'aCWJiOnNlc3M5MRoJYmI6c2VzczkyGgliYjpzZXNzOTMaCWJiOnNlc3M5NBoJYmI6c2Vzczk1GgliYjpzZXNzOTYaCWJiOnNl' + 'c3M5NxoJYmI6c2Vzczk4GgliYjpzZXNzOTk:JYmABAVLM6y7_T4n1pRcwBfwDfzMV4JJ3cpbEG617zdGgKRZwL7MalsYn5bq1' + 'F2ibujMrsF9nzZf8l4s_e-Ivjkz_xu4KMzSp-pUh9V7XIF_smj0WHYpv6gOvWNuK8uIvlZTTKwtQX0qZOL9m-MEeZiHoQPKZG' + 'CfJ_qxMUp-J8I' +) +VALID_SERVICE_TICKET_3 = ( + '3:serv:CBAQ__________9_IgUI5QEQHA:Sd6tmA1CNy2Nf7XevC3x7zr2DrGNRmcl-TxUsDtDW2xI3YXyCxBltWeg0-KtDlq' + 'yYuPOP5Jd_-XXNA12KlOPnNzrz3jm-5z8uQl6CjCcrVHUHJ75pGC8r9UOlS8cOgeXQB5dYP-fOWyo5CNadlozx1S2meCIxncb' + 'QRV1kCBi4KU' +) +VALID_SERVICE_TICKET_ISSUER = ( + '3:serv:CBAQ__________9_IgsI5QEQHCDr1MT4Ag:Gu66XJT_nKnIRJjFy1561wFhIqkJItcSTGftLo7Yvi7i5wIdV-QuKT_' + '-IMPpgjxnnGbt1Dy3Ys2TEoeJAb0TdaCYG1uy3vpoLONmTx9AenN5dx1HHf46cypLK5D3OdiTjxvqI9uGmSIKrSdRxU8gprpu' + '5QiBDPZqVCWhM60FVSY' +) + + +def test_context(): + service_context = ServiceContext(OUR_ID, SECRET, tp2u.TVMKNIFE_PUBLIC_KEYS) + service_context.reset_keys(tp2u.TVMKNIFE_PUBLIC_KEYS) + + +def test_context_exceptions(): + with pytest.raises(MalformedTvmSecretException): + ServiceContext(OUR_ID, MALFORMED_TVM_SECRET, tp2u.TVMKNIFE_PUBLIC_KEYS) + with pytest.raises(MalformedTvmKeysException): + ServiceContext(OUR_ID, SECRET, MALFORMED_TVM_KEYS) + with pytest.raises(EmptyTvmKeysException): + ServiceContext(OUR_ID, SECRET, EMPTY_TVM_KEYS) + + service_context = ServiceContext(OUR_ID, None, tp2u.TVMKNIFE_PUBLIC_KEYS) + with pytest.raises(MalformedTvmSecretException): + service_context.sign(1490000001, 13) + + service_context = ServiceContext(OUR_ID, SECRET, None) + with pytest.raises(EmptyTvmKeysException): + service_context.check('abcde') + + with pytest.raises(ContextException): + service_context = ServiceContext(OUR_ID, None, None) + + +def test_context_sign(): + service_context = ServiceContext(OUR_ID, SECRET, tp2u.TVMKNIFE_PUBLIC_KEYS) + assert '6H8RjdP4cCrTpMEd3XArBTrKFMQbgXLHbB2FJgQ-yO0' == service_context.sign('1490000001', '13,19', 'bb:sess1') + assert 'HAes0pEg8wb9M9YmKWPjwxm91mDp-GMTruOb6bzmuRE' == service_context.sign( + 1490000001, [13, 19], ['bb:sess1', 'bb:sess2'] + ) + assert 'JU5tIwr3qS1K4dse2KafQzRXX_TGtlS3jE1inK7QyRM' == service_context.sign(1490000001, 13, []) + assert 'JU5tIwr3qS1K4dse2KafQzRXX_TGtlS3jE1inK7QyRM' == service_context.sign(1490000001, 13) + + +def test_ticket1(): + service_context = ServiceContext(OUR_ID, SECRET, tp2u.TVMKNIFE_PUBLIC_KEYS) + ticket = service_context.check(VALID_SERVICE_TICKET_1) + assert ticket.src == SRC_ID + assert ticket.scopes == ['bb:sess1', 'bb:sess2'] + assert ticket.has_scope('bb:sess1') + assert ticket.has_scope('bb:sess2') + assert not ticket.has_scope('bb:sess3') + assert ( + ticket.debug_info() + == 'ticket_type=serv;expiration_time=9223372036854775807;src=229;dst=28;scope=bb:sess1;scope=bb:sess2;' + ) + assert VALID_SERVICE_TICKET_SIGNLESS_1 == ServiceTicket.remove_signature(VALID_SERVICE_TICKET_1) + assert ticket.issuer_uid is None + assert ( + repr(ticket) + == 'ticket_type=serv;expiration_time=9223372036854775807;src=229;dst=28;scope=bb:sess1;scope=bb:sess2;' + ) + assert ( + str(ticket) + == 'ticket_type=serv;expiration_time=9223372036854775807;src=229;dst=28;scope=bb:sess1;scope=bb:sess2;' + ) + + +def test_ticket2(): + service_context = ServiceContext(OUR_ID, SECRET, tp2u.TVMKNIFE_PUBLIC_KEYS) + ticket = service_context.check(VALID_SERVICE_TICKET_2) + assert ( + ticket.debug_info() + == 'ticket_type=serv;expiration_time=9223372036854775807;src=229;dst=28;scope=bb:sess1;scope=bb:sess10;scope=bb:sess100;scope=bb:sess11;scope=bb:sess12;scope=bb:sess13;scope=bb:sess14;scope=bb:sess15;scope=bb:sess16;scope=bb:sess17;scope=bb:sess18;scope=bb:sess19;scope=bb:sess2;scope=bb:sess20;scope=bb:sess21;scope=bb:sess22;scope=bb:sess23;scope=bb:sess24;scope=bb:sess25;scope=bb:sess26;scope=bb:sess27;scope=bb:sess28;scope=bb:sess29;scope=bb:sess3;scope=bb:sess30;scope=bb:sess31;scope=bb:sess32;scope=bb:sess33;scope=bb:sess34;scope=bb:sess35;scope=bb:sess36;scope=bb:sess37;scope=bb:sess38;scope=bb:sess39;scope=bb:sess4;scope=bb:sess40;scope=bb:sess41;scope=bb:sess42;scope=bb:sess43;scope=bb:sess44;scope=bb:sess45;scope=bb:sess46;scope=bb:sess47;scope=bb:sess48;scope=bb:sess49;scope=bb:sess5;scope=bb:sess50;scope=bb:sess51;scope=bb:sess52;scope=bb:sess53;scope=bb:sess54;scope=bb:sess55;scope=bb:sess56;scope=bb:sess57;scope=bb:sess58;scope=bb:sess59;scope=bb:sess6;scope=bb:sess60;scope=bb:sess61;scope=bb:sess62;scope=bb:sess63;scope=bb:sess64;scope=bb:sess65;scope=bb:sess66;scope=bb:sess67;scope=bb:sess68;scope=bb:sess69;scope=bb:sess7;scope=bb:sess70;scope=bb:sess71;scope=bb:sess72;scope=bb:sess73;scope=bb:sess74;scope=bb:sess75;scope=bb:sess76;scope=bb:sess77;scope=bb:sess78;scope=bb:sess79;scope=bb:sess8;scope=bb:sess80;scope=bb:sess81;scope=bb:sess82;scope=bb:sess83;scope=bb:sess84;scope=bb:sess85;scope=bb:sess86;scope=bb:sess87;scope=bb:sess88;scope=bb:sess89;scope=bb:sess9;scope=bb:sess90;scope=bb:sess91;scope=bb:sess92;scope=bb:sess93;scope=bb:sess94;scope=bb:sess95;scope=bb:sess96;scope=bb:sess97;scope=bb:sess98;scope=bb:sess99;' # noqa + ) + assert ticket.issuer_uid is None + + +def test_ticket3(): + service_context = ServiceContext(OUR_ID, SECRET, tp2u.TVMKNIFE_PUBLIC_KEYS) + ticket = service_context.check(VALID_SERVICE_TICKET_3) + assert ticket.debug_info() == 'ticket_type=serv;expiration_time=9223372036854775807;src=229;dst=28;' + assert ticket.issuer_uid is None + + +def test_ticket_issuer(): + service_context = ServiceContext(OUR_ID, SECRET, tp2u.TVMKNIFE_PUBLIC_KEYS) + ticket = service_context.check(VALID_SERVICE_TICKET_ISSUER) + assert ( + ticket.debug_info() + == 'ticket_type=serv;expiration_time=9223372036854775807;src=229;dst=28;issuer_uid=789654123;' + ) + assert 789654123 == ticket.issuer_uid + + +def test_ticket_exceptions(): + service_context = ServiceContext(OUR_ID, SECRET, tp2u.TVMKNIFE_PUBLIC_KEYS) + service_context.reset_keys(tp2u.TVMKNIFE_PUBLIC_KEYS) + with pytest.raises(TicketParsingException) as ex: + service_context.check(INVALID_SERVICE_TICKET) + assert ex.value.status == Status.Malformed + + with pytest.raises(TicketParsingException) as ex: + service_context.check(UNSUPPORTED_VERSION_SERVICE_TICKET) + assert ex.value.status == Status.UnsupportedVersion + + +def test_create_ticket_for_tests(): + with pytest.raises(TicketParsingException): + tp2u.create_service_ticket_for_unittest(Status.Expired, 42) + s = tp2u.create_service_ticket_for_unittest(Status.Ok, 42) + assert s + assert s.src == 42 + assert s.issuer_uid is None + assert s.debug_info() == 'ticket_type=serv;src=42;dst=100500;' + + s = tp2u.create_service_ticket_for_unittest(Status.Ok, 42, 100501) + assert s + assert s.src == 42 + assert s.issuer_uid == 100501 + assert s.debug_info() == 'ticket_type=serv;src=42;dst=100500;issuer_uid=100501;' diff --git a/library/python/deprecated/ticket_parser2/src/ut/test_user.py b/library/python/deprecated/ticket_parser2/src/ut/test_user.py new file mode 100644 index 0000000000..75b62f6e7e --- /dev/null +++ b/library/python/deprecated/ticket_parser2/src/ut/test_user.py @@ -0,0 +1,218 @@ +#!/usr/bin/env python +from __future__ import print_function + +import pytest +from ticket_parser2 import ( + BlackboxEnv, + Status, + UserTicket, +) +from ticket_parser2.low_level import UserContext +from ticket_parser2.exceptions import ( + EmptyTvmKeysException, + MalformedTvmKeysException, + TicketParsingException, +) +import ticket_parser2.unittest as tp2u + + +EMPTY_TVM_KEYS = ( + '1:EpUBCpIBCAYQABqHATCBhAKBgQCoZkFGm9oLTqjeXZAq6j5S6i7K20V0lNdBBLqfmFBIRuTkYxhs4vUYnWjZrKRAd5bp6_p' + 'y0csmFmpl_5Yh0b-2pdo_E5PNP7LGRzKyKSiFddyykKKzVOazH8YYldDAfE8Z5HoS9e48an5JsPg0jr-TPu34DnJq3yv2a6dq' + 'iKL9zSCakQY' +) +EXPIRED_USER_TICKET = ( + '3:user:CA0QABokCgMIyAMKAgh7EMgDGghiYjpzZXNzMRoIYmI6c2VzczIgEigB:D0CmYVwWg91LDYejjeQ2UP8AeiA_mr1q1' + 'CUD_lfJ9zQSEYEOYGDTafg4Um2rwOOvQnsD1JHM4zHyMUJ6Jtp9GAm5pmhbXBBZqaCcJpyxLTEC8a81MhJFCCJRvu_G1FiAgR' + 'gB25gI3HIbkvHFUEqAIC_nANy7NFQnbKk2S-EQPGY' +) +MALFORMED_TVM_KEYS = ( + '1:CpgCCpMCCAEQABqIAjCCAQQCggEAcLEXeH67FQESFUn4_7wnX7wN0PUrBoUsm3QQ4W5vC-qz6sXaEjSwnTV8w1o-z6X9KPL' + 'lhzMQvuS38NCNfK4uvJ4Zvfp3YsXJ25-rYtbnrYJHNvHohD-kPCCw_yZpMp21JdWigzQGuV7CtrxUhF-NNrsnUaJrE5-OpEWN' + 't4X6nCItKIYeVcSK6XJUbEWbrNCRbvkSc4ak2ymFeMuHYJVjxh4eQbk7_ZPzodP0WvF6eUYrYeb42imVEOR8ofVLQWE5DVnb1' + 'z_TqZm4i1XkS7jMwZuBxBRw8DGdYei0lT_sAf7KST2jC0590NySB3vsBgWEVs1OdUUWA6r-Dvx9dsOQtSCVkQYQAAqZAgqUAg' + 'gCEAAaiQIwggEFAoIBAQDhEBM5-6YsPWfogKtbluJoCX1WV2KdzOaQ0-OlRbBzeCzw-eQKu12c8WakHBbeCMd1I1TU64SDkDo' + 'rWjXGIa_2xT6N3zzNAE50roTbPCcmeQrps26woTYfYIuqDdoxYKZNr0lvNLLW47vBr7EKqo1S4KSj7aXK_XYeEvUgIgf3nVIc' + 'Nrio7VTnFmGGVQCepaL1Hi1gN4yIXjVZ06PBPZ-DxSRu6xOGbFrfKMJeMPs7KOyE-26Q3xOXdTIa1X-zYIucTd_bxUCL4BVbw' + 'W2AvbbFsaG7ISmVdGu0XUTmhXs1KrEfUVLRJhE4Dx99hAZXm1_HlYMUeJcMQ_oHOhV94ENFIJaRBhACCpYBCpEBCAMQABqGAT' + 'CBgwKBgF9t2YJGAJkRRFq6fWhi3m1TFW1UOE0f6ZrfYhHAkpqGlKlh0QVfeTNPpeJhi75xXzCe6oReRUm-0DbqDNhTShC7uGU' + 'v1INYnRBQWH6E-5Fc5XrbDFSuGQw2EYjNfHy_HefHJXxQKAqPvxBDKMKkHgV58WtM6rC8jRi9sdX_ig2NIJeRBhABCpYBCpEB' + 'CAQQABqGATCBgwKBgGB4d6eLGUBv-Q6EPLehC4S-yuE2HB-_rJ7WkeYwyp-xIPolPrd-PQme2utHB4ZgpXHIu_OFksDe_0bPg' + 'ZniNRSVRbl7W49DgS5Ya3kMfrYB4DnF5Fta5tn1oV6EwxYD4JONpFTenOJALPGTPawxXEfon_peiHOSBuQMu3_Vn-l1IJiRBh' + 'ADCpcBCpIBCAUQABqHATCBhAKBgQCTJMKIfmfeZpaI7Q9rnsc29gdWawK7TnpVKRHws1iY7EUlYROeVcMdAwEqVM6f8BVCKLG' + 'gzQ7Gar_uuxfUGKwqEQzoppDraw4F75J464-7D5f6_oJQuGIBHZxqbMONtLjBCXRUhQW5szBLmTQ_R3qaJb5vf-h0APZfkYhq' + '1cTttSCZkQYQBAqWAQqRAQgLEAAahgEwgYMCgYBvvGVH_M2H8qxxv94yaDYUTWbRnJ1uiIYc59KIQlfFimMPhSS7x2tqUa2-h' + 'I55JiII0Xym6GNkwLhyc1xtWChpVuIdSnbvttbrt4weDMLHqTwNOF6qAsVKGKT1Yh8yf-qb-DSmicgvFc74mBQm_6gAY1iQsf' + '33YX8578ClhKBWHSCVkQYQAAqXAQqSAQgMEAAahwEwgYQCgYEAkuzFcd5TJu7lYWYe2hQLFfUWIIj91BvQQLa_Thln4YtGCO8' + 'gG1KJqJm-YlmJOWQG0B7H_5RVhxUxV9KpmFnsDVkzUFKOsCBaYGXc12xPVioawUlAwp5qp3QQtZyx_se97YIoLzuLr46UkLcL' + 'nkIrp-Jo46QzYi_QHq45WTm8MQ0glpEGEAIKlwEKkgEIDRAAGocBMIGEAoGBAIUzbxOknXf_rNt17_ir8JlWvrtnCWsQd1MAn' + 'l5mgArvavDtKeBYHzi5_Ak7DHlLzuA6YE8W175FxLFKpN2hkz-l-M7ltUSd8N1BvJRhK4t6WffWfC_1wPyoAbeSN2Yb1jygtZ' + 'JQ8wGoXHcJQUXiMit3eFNyylwsJFj1gzAR4JCdIJeRBhABCpYBCpEBCA4QABqGATCBgwKBgFMcbEpl9ukVR6AO_R6sMyiU11I' + '8b8MBSUCEC15iKsrVO8v_m47_TRRjWPYtQ9eZ7o1ocNJHaGUU7qqInFqtFaVnIceP6NmCsXhjs3MLrWPS8IRAy4Zf4FKmGOx3' + 'N9O2vemjUygZ9vUiSkULdVrecinRaT8JQ5RG4bUMY04XGIwFIJiRBhADCpYBCpEBCA8QABqGATCBgwKBgGpCkW-NR3li8GlRv' + 'qpq2YZGSIgm_PTyDI2Zwfw69grsBmPpVFW48Vw7xoMN35zcrojEpialB_uQzlpLYOvsMl634CRIuj-n1QE3-gaZTTTE8mg-AR' + '4mcxnTKThPnRQpbuOlYAnriwiasWiQEMbGjq_HmWioYYxFo9USlklQn4-9IJmRBhAEEpUBCpIBCAYQABqHATCBhAKBgQCoZkF' + 'Gm9oLTqjeXZAq6j5S6i7K20V0lNdBBLqfmFBIRuTkYxhs4vUYnWjZrKRAd5bp6_py0csmFmpl_5Yh0b-2pdo_E5PNP7LGRzKy' + 'KSiFddyykKKzVOazH8YYldDAfE8Z5HoS9e48an5JsPg0jr-TPu34DnJq3yv2a6dqiKL9zSCakQYSlQEKkgEIEBAAGocBMIGEA' + 'oGBALhrihbf3EpjDQS2sCQHazoFgN0nBbE9eesnnFTfzQELXb2gnJU9enmV_aDqaHKjgtLIPpCgn40lHrn5k6mvH5OdedyI6c' + 'CzE-N-GFp3nAq0NDJyMe0fhtIRD__CbT0ulcvkeow65ubXWfw6dBC2gR_34rdMe_L_TGRLMWjDULbNIJ' +) +MALFORMED_USER_TICKET = ( + '3:user:CA0Q__________9_GiQKAwjIAwoCCHsQyAMaCGJiOnNlc3MxcXn9krYk19LCvlFrhMW-R4q8mKfXJXCd-RBVBgUQzC' + 'OR1Dx2FiOyU-BxUoIsaU0PiwTjbVY5I2onJDilge70Cl5zEPI9pfab2qwklACq_ZBUvD1tzrfNUr88otBGAziHASJWgyVDkhy' + 'Q3p7YbN38qpb0vGQrYNxlk4e2I' +) +SIGN_BROKEN_USER_TICKET = ( + '3:user:CA0Q__________9_GiQKAwjIAwoCCHsQyAMaCGJiOnNlc3MxGghiYjpzZXNzMiASKAE:KJFv5EcXn9krYk19LCvlFr' + 'hMW-R4q8mKfXJXCd-RBVBgUQzCOR1Dx2FiOyU-BxUoIsaU0PiwI2onJDilge70Cl5zEPI9pfab2qwklACq_ZBUvD1tzrfNUr8' + '8otBGAziHASJWgyVDkhyQ3p7YbN38qpb0vGQrYNxlk4e2' +) +UNSUPPORTED_VERSION_USER_TICKET = ( + '2:user:CA0Q__________9_GiQKAwjIAwoCCHsQyAMaCGJiOnNlc3MxGghiYjpzZXNzMiASKAE:KJFv5EcXn9krYk19LCvlFr' + 'hMW-R4q8mKfXJXCd-RBVBgUQzCOR1Dx2FiOyU-BxUoIsaU0PiwTjbVY5I2onJDilge70Cl5zEPI9pfab2qwklACq_ZBUvD1tz' + 'rfNUr88otBGAziHASJWgyVDkhyQ3p7YbN38qpb0vGQrYNxlk4e2I' +) +VALID_SERVICE_TICKET = ( + '3:serv:CBAQ__________9_IhkI5QEQHBoIYmI6c2VzczEaCGJiOnNlc3My:WUPx1cTf05fjD1exB35T5j2DCHWH1YaLJon_a' + '4rN-D7JfXHK1Ai4wM4uSfboHD9xmGQH7extqtlEk1tCTCGm5qbRVloJwWzCZBXo3zKX6i1oBYP_89WcjCNPVe1e8jwGdLsnu6' + 'PpxL5cn0xCksiStILH5UmDR6xfkJdnmMG94o8' +) +VALID_USER_TICKET_1 = ( + '3:user:CA0Q__________9_GiQKAwjIAwoCCHsQyAMaCGJiOnNlc3MxGghiYjpzZXNzMiASKAE:KJFv5EcXn9krYk19LCvlFr' + 'hMW-R4q8mKfXJXCd-RBVBgUQzCOR1Dx2FiOyU-BxUoIsaU0PiwTjbVY5I2onJDilge70Cl5zEPI9pfab2qwklACq_ZBUvD1tz' + 'rfNUr88otBGAziHASJWgyVDkhyQ3p7YbN38qpb0vGQrYNxlk4e2I' +) +VALID_USER_TICKET_SIGNLESS_1 = '3:user:CA0Q__________9_GiQKAwjIAwoCCHsQyAMaCGJiOnNlc3MxGghiYjpzZXNzMiASKAE:' +VALID_USER_TICKET_2 = ( + '3:user:CA0Q__________9_GhAKAwjIAwoCCHsQyAMgEigB:KRibGYTJUA2ns0Fn7VYqeMZ1-GdscB1o9pRzELyr7QJrJsfsE' + '8Y_HoVvB8Npr-oalv6AXOpagSc8HpZjAQz8zKMAVE_tI0tL-9DEsHirpawEbpy7OWV7-k18o1m-RaDaKeTlIB45KHbBul1-9a' + 'eKkortBfbbXtz_Qy9r_mfFPiQ' +) +VALID_USER_TICKET_3 = ( + '3:user:CA0Q__________9_Go8bCgIIAAoCCAEKAggCCgIIAwoCCAQKAggFCgIIBgoCCAcKAggICgIICQoCCAoKAggLCgIIDA' + 'oCCA0KAggOCgIIDwoCCBAKAggRCgIIEgoCCBMKAggUCgIIFQoCCBYKAggXCgIIGAoCCBkKAggaCgIIGwoCCBwKAggdCgIIHgo' + 'CCB8KAgggCgIIIQoCCCIKAggjCgIIJAoCCCUKAggmCgIIJwoCCCgKAggpCgIIKgoCCCsKAggsCgIILQoCCC4KAggvCgIIMAoC' + 'CDEKAggyCgIIMwoCCDQKAgg1CgIINgoCCDcKAgg4CgIIOQoCCDoKAgg7CgIIPAoCCD0KAgg-CgIIPwoCCEAKAghBCgIIQgoCC' + 'EMKAghECgIIRQoCCEYKAghHCgIISAoCCEkKAghKCgIISwoCCEwKAghNCgIITgoCCE8KAghQCgIIUQoCCFIKAghTCgIIVAoCCF' + 'UKAghWCgIIVwoCCFgKAghZCgIIWgoCCFsKAghcCgIIXQoCCF4KAghfCgIIYAoCCGEKAghiCgIIYwoCCGQKAghlCgIIZgoCCGc' + 'KAghoCgIIaQoCCGoKAghrCgIIbAoCCG0KAghuCgIIbwoCCHAKAghxCgIIcgoCCHMKAgh0CgIIdQoCCHYKAgh3CgIIeAoCCHkK' + 'Agh6CgIIewoCCHwKAgh9CgIIfgoCCH8KAwiAAQoDCIEBCgMIggEKAwiDAQoDCIQBCgMIhQEKAwiGAQoDCIcBCgMIiAEKAwiJA' + 'QoDCIoBCgMIiwEKAwiMAQoDCI0BCgMIjgEKAwiPAQoDCJABCgMIkQEKAwiSAQoDCJMBCgMIlAEKAwiVAQoDCJYBCgMIlwEKAw' + 'iYAQoDCJkBCgMImgEKAwibAQoDCJwBCgMInQEKAwieAQoDCJ8BCgMIoAEKAwihAQoDCKIBCgMIowEKAwikAQoDCKUBCgMIpgE' + 'KAwinAQoDCKgBCgMIqQEKAwiqAQoDCKsBCgMIrAEKAwitAQoDCK4BCgMIrwEKAwiwAQoDCLEBCgMIsgEKAwizAQoDCLQBCgMI' + 'tQEKAwi2AQoDCLcBCgMIuAEKAwi5AQoDCLoBCgMIuwEKAwi8AQoDCL0BCgMIvgEKAwi_AQoDCMABCgMIwQEKAwjCAQoDCMMBC' + 'gMIxAEKAwjFAQoDCMYBCgMIxwEKAwjIAQoDCMkBCgMIygEKAwjLAQoDCMwBCgMIzQEKAwjOAQoDCM8BCgMI0AEKAwjRAQoDCN' + 'IBCgMI0wEKAwjUAQoDCNUBCgMI1gEKAwjXAQoDCNgBCgMI2QEKAwjaAQoDCNsBCgMI3AEKAwjdAQoDCN4BCgMI3wEKAwjgAQo' + 'DCOEBCgMI4gEKAwjjAQoDCOQBCgMI5QEKAwjmAQoDCOcBCgMI6AEKAwjpAQoDCOoBCgMI6wEKAwjsAQoDCO0BCgMI7gEKAwjv' + 'AQoDCPABCgMI8QEKAwjyAQoDCPMBCgMI9AEKAwj1AQoDCPYBCgMI9wEKAwj4AQoDCPkBCgMI-gEKAwj7AQoDCPwBCgMI_QEKA' + 'wj-AQoDCP8BCgMIgAIKAwiBAgoDCIICCgMIgwIKAwiEAgoDCIUCCgMIhgIKAwiHAgoDCIgCCgMIiQIKAwiKAgoDCIsCCgMIjA' + 'IKAwiNAgoDCI4CCgMIjwIKAwiQAgoDCJECCgMIkgIKAwiTAgoDCJQCCgMIlQIKAwiWAgoDCJcCCgMImAIKAwiZAgoDCJoCCgM' + 'ImwIKAwicAgoDCJ0CCgMIngIKAwifAgoDCKACCgMIoQIKAwiiAgoDCKMCCgMIpAIKAwilAgoDCKYCCgMIpwIKAwioAgoDCKkC' + 'CgMIqgIKAwirAgoDCKwCCgMIrQIKAwiuAgoDCK8CCgMIsAIKAwixAgoDCLICCgMIswIKAwi0AgoDCLUCCgMItgIKAwi3AgoDC' + 'LgCCgMIuQIKAwi6AgoDCLsCCgMIvAIKAwi9AgoDCL4CCgMIvwIKAwjAAgoDCMECCgMIwgIKAwjDAgoDCMQCCgMIxQIKAwjGAg' + 'oDCMcCCgMIyAIKAwjJAgoDCMoCCgMIywIKAwjMAgoDCM0CCgMIzgIKAwjPAgoDCNACCgMI0QIKAwjSAgoDCNMCCgMI1AIKAwj' + 'VAgoDCNYCCgMI1wIKAwjYAgoDCNkCCgMI2gIKAwjbAgoDCNwCCgMI3QIKAwjeAgoDCN8CCgMI4AIKAwjhAgoDCOICCgMI4wIK' + 'AwjkAgoDCOUCCgMI5gIKAwjnAgoDCOgCCgMI6QIKAwjqAgoDCOsCCgMI7AIKAwjtAgoDCO4CCgMI7wIKAwjwAgoDCPECCgMI8' + 'gIKAwjzAgoDCPQCCgMI9QIKAwj2AgoDCPcCCgMI-AIKAwj5AgoDCPoCCgMI-wIKAwj8AgoDCP0CCgMI_gIKAwj_AgoDCIADCg' + 'MIgQMKAwiCAwoDCIMDCgMIhAMKAwiFAwoDCIYDCgMIhwMKAwiIAwoDCIkDCgMIigMKAwiLAwoDCIwDCgMIjQMKAwiOAwoDCI8' + 'DCgMIkAMKAwiRAwoDCJIDCgMIkwMKAwiUAwoDCJUDCgMIlgMKAwiXAwoDCJgDCgMImQMKAwiaAwoDCJsDCgMInAMKAwidAwoD' + 'CJ4DCgMInwMKAwigAwoDCKEDCgMIogMKAwijAwoDCKQDCgMIpQMKAwimAwoDCKcDCgMIqAMKAwipAwoDCKoDCgMIqwMKAwisA' + 'woDCK0DCgMIrgMKAwivAwoDCLADCgMIsQMKAwiyAwoDCLMDCgMItAMKAwi1AwoDCLYDCgMItwMKAwi4AwoDCLkDCgMIugMKAw' + 'i7AwoDCLwDCgMIvQMKAwi-AwoDCL8DCgMIwAMKAwjBAwoDCMIDCgMIwwMKAwjEAwoDCMUDCgMIxgMKAwjHAwoDCMgDCgMIyQM' + 'KAwjKAwoDCMsDCgMIzAMKAwjNAwoDCM4DCgMIzwMKAwjQAwoDCNEDCgMI0gMKAwjTAwoDCNQDCgMI1QMKAwjWAwoDCNcDCgMI' + '2AMKAwjZAwoDCNoDCgMI2wMKAwjcAwoDCN0DCgMI3gMKAwjfAwoDCOADCgMI4QMKAwjiAwoDCOMDCgMI5AMKAwjlAwoDCOYDC' + 'gMI5wMKAwjoAwoDCOkDCgMI6gMKAwjrAwoDCOwDCgMI7QMKAwjuAwoDCO8DCgMI8AMKAwjxAwoDCPIDCgMI8wMQyAMaCGJiOn' + 'Nlc3MxGgliYjpzZXNzMTAaCmJiOnNlc3MxMDAaCWJiOnNlc3MxMRoJYmI6c2VzczEyGgliYjpzZXNzMTMaCWJiOnNlc3MxNBo' + 'JYmI6c2VzczE1GgliYjpzZXNzMTYaCWJiOnNlc3MxNxoJYmI6c2VzczE4GgliYjpzZXNzMTkaCGJiOnNlc3MyGgliYjpzZXNz' + 'MjAaCWJiOnNlc3MyMRoJYmI6c2VzczIyGgliYjpzZXNzMjMaCWJiOnNlc3MyNBoJYmI6c2VzczI1GgliYjpzZXNzMjYaCWJiO' + 'nNlc3MyNxoJYmI6c2VzczI4GgliYjpzZXNzMjkaCGJiOnNlc3MzGgliYjpzZXNzMzAaCWJiOnNlc3MzMRoJYmI6c2VzczMyGg' + 'liYjpzZXNzMzMaCWJiOnNlc3MzNBoJYmI6c2VzczM1GgliYjpzZXNzMzYaCWJiOnNlc3MzNxoJYmI6c2VzczM4GgliYjpzZXN' + 'zMzkaCGJiOnNlc3M0GgliYjpzZXNzNDAaCWJiOnNlc3M0MRoJYmI6c2VzczQyGgliYjpzZXNzNDMaCWJiOnNlc3M0NBoJYmI6' + 'c2VzczQ1GgliYjpzZXNzNDYaCWJiOnNlc3M0NxoJYmI6c2VzczQ4GgliYjpzZXNzNDkaCGJiOnNlc3M1GgliYjpzZXNzNTAaC' + 'WJiOnNlc3M1MRoJYmI6c2VzczUyGgliYjpzZXNzNTMaCWJiOnNlc3M1NBoJYmI6c2VzczU1GgliYjpzZXNzNTYaCWJiOnNlc3' + 'M1NxoJYmI6c2VzczU4GgliYjpzZXNzNTkaCGJiOnNlc3M2GgliYjpzZXNzNjAaCWJiOnNlc3M2MRoJYmI6c2VzczYyGgliYjp' + 'zZXNzNjMaCWJiOnNlc3M2NBoJYmI6c2VzczY1GgliYjpzZXNzNjYaCWJiOnNlc3M2NxoJYmI6c2VzczY4GgliYjpzZXNzNjka' + 'CGJiOnNlc3M3GgliYjpzZXNzNzAaCWJiOnNlc3M3MRoJYmI6c2VzczcyGgliYjpzZXNzNzMaCWJiOnNlc3M3NBoJYmI6c2Vzc' + 'zc1GgliYjpzZXNzNzYaCWJiOnNlc3M3NxoJYmI6c2Vzczc4GgliYjpzZXNzNzkaCGJiOnNlc3M4GgliYjpzZXNzODAaCWJiOn' + 'Nlc3M4MRoJYmI6c2VzczgyGgliYjpzZXNzODMaCWJiOnNlc3M4NBoJYmI6c2Vzczg1GgliYjpzZXNzODYaCWJiOnNlc3M4Nxo' + 'JYmI6c2Vzczg4GgliYjpzZXNzODkaCGJiOnNlc3M5GgliYjpzZXNzOTAaCWJiOnNlc3M5MRoJYmI6c2VzczkyGgliYjpzZXNz' + 'OTMaCWJiOnNlc3M5NBoJYmI6c2Vzczk1GgliYjpzZXNzOTYaCWJiOnNlc3M5NxoJYmI6c2Vzczk4GgliYjpzZXNzOTkgEigB:' + 'CX8PIOrxJnQqFXl7wAsiHJ_1VGjoI-asNlCXb8SE8jtI2vdh9x6CqbAurSgIlAAEgotVP-nuUR38x_a9YJuXzmG5AvJ458apW' + 'QtODHIDIX6ZaIwMxjS02R7S5LNqXa0gAuU_R6bCWpZdWe2uLMkdpu5KHbDgW08g-uaP_nceDOk' +) + + +def test_context(): + user_context = UserContext(BlackboxEnv.Test, tp2u.TVMKNIFE_PUBLIC_KEYS) + user_context.reset_keys(tp2u.TVMKNIFE_PUBLIC_KEYS) + + +def test_context_exceptions(): + with pytest.raises(MalformedTvmKeysException): + UserContext(BlackboxEnv.Test, MALFORMED_TVM_KEYS) + with pytest.raises(EmptyTvmKeysException): + UserContext(BlackboxEnv.Stress, EMPTY_TVM_KEYS) + + +def test_ticket(): + user_context = UserContext(BlackboxEnv.Test, tp2u.TVMKNIFE_PUBLIC_KEYS) + ticket = user_context.check(VALID_USER_TICKET_1) + assert ticket.scopes == ['bb:sess1', 'bb:sess2'] + assert ticket.has_scope('bb:sess1') + assert ticket.has_scope('bb:sess2') + assert not ticket.has_scope('bb:sess3') + assert ticket.uids == [456, 123] + assert ticket.default_uid == 456 + assert ( + ticket.debug_info() + == 'ticket_type=user;expiration_time=9223372036854775807;scope=bb:sess1;scope=bb:sess2;default_uid=456;uid=456;uid=123;env=Test;' + ) + assert VALID_USER_TICKET_SIGNLESS_1 == UserTicket.remove_signature(VALID_USER_TICKET_1) + assert ( + repr(ticket) + == 'ticket_type=user;expiration_time=9223372036854775807;scope=bb:sess1;scope=bb:sess2;default_uid=456;uid=456;uid=123;env=Test;' + ) + assert ( + str(ticket) + == 'ticket_type=user;expiration_time=9223372036854775807;scope=bb:sess1;scope=bb:sess2;default_uid=456;uid=456;uid=123;env=Test;' + ) + + +def test_ticket_exceptions(): + user_context = UserContext(BlackboxEnv.Test, tp2u.TVMKNIFE_PUBLIC_KEYS) + with pytest.raises(TicketParsingException) as ex: + user_context.check(SIGN_BROKEN_USER_TICKET) + assert ex.value.status == Status.SignBroken + assert ( + ex.value.debug_info + == 'ticket_type=user;expiration_time=9223372036854775807;scope=bb:sess1;scope=bb:sess2;default_uid=456;uid=456;uid=123;env=Test;' + ) + + with pytest.raises(TicketParsingException) as ex: + user_context.check(MALFORMED_USER_TICKET) + assert ex.value.status == Status.Malformed + assert ex.value.debug_info == 'status=malformed;' + + with pytest.raises(TicketParsingException) as ex: + user_context.check(VALID_SERVICE_TICKET) + assert ex.value.status == Status.InvalidTicketType + assert ex.value.debug_info == 'ticket_type=not-user;' + + user_context = UserContext(BlackboxEnv.Prod, tp2u.TVMKNIFE_PUBLIC_KEYS) + with pytest.raises(TicketParsingException) as ex: + user_context.check(VALID_USER_TICKET_1) + assert ex.value.status == Status.InvalidBlackboxEnv + + +def test_create_ticket_for_tests(): + with pytest.raises(TicketParsingException): + tp2u.create_user_ticket_for_unittest(Status.Expired, 42, ['ololo', 'abc']) + u = tp2u.create_user_ticket_for_unittest(Status.Ok, 42, ['ololo', 'abc'], [23, 56]) + assert u + assert u.default_uid == 42 + assert u.scopes == ['abc', 'ololo'] + assert u.uids == [23, 42, 56] + assert u.debug_info() == 'ticket_type=user;scope=abc;scope=ololo;default_uid=42;uid=23;uid=42;uid=56;env=Test;' + + with pytest.raises(Exception): + tp2u.create_user_ticket_for_unittest(Status.Ok, 0) diff --git a/library/python/deprecated/ticket_parser2/src/utils.h b/library/python/deprecated/ticket_parser2/src/utils.h new file mode 100644 index 0000000000..3ec03935c4 --- /dev/null +++ b/library/python/deprecated/ticket_parser2/src/utils.h @@ -0,0 +1,131 @@ +#pragma once + +#include <library/cpp/tvmauth/version.h> +#include <library/cpp/tvmauth/client/facade.h> +#include <library/cpp/tvmauth/client/misc/utils.h> +#include <library/cpp/tvmauth/client/misc/api/threaded_updater.h> +#include <library/cpp/tvmauth/client/misc/tool/settings.h> + +#include <util/system/getpid.h> + +namespace NTvmAuth { + class TPidCheckedClient: public TTvmClient { + public: + using TTvmClient::TTvmClient; + + TString GetServiceTicketFor(const TClientSettings::TAlias& dst) const { + pid_.check(); + return TTvmClient::GetServiceTicketFor(dst); + } + + TString GetServiceTicketFor(const TTvmId dst) const { + pid_.check(); + return TTvmClient::GetServiceTicketFor(dst); + } + + TCheckedServiceTicket CheckServiceTicket(TStringBuf ticket) const { + pid_.check(); + return TTvmClient::CheckServiceTicket(ticket); + } + + TCheckedUserTicket CheckUserTicket(TStringBuf ticket) const { + pid_.check(); + return TTvmClient::CheckUserTicket(ticket); + } + + TCheckedUserTicket CheckUserTicketWithOveridedEnv(TStringBuf ticket, EBlackboxEnv env) const { + pid_.check(); + return TTvmClient::CheckUserTicket(ticket, env); + } + + static TStringBuf StatusToString(TClientStatus::ECode s) { + switch (s) { + case TClientStatus::Ok: + return "TvmClient cache is ok"; + case TClientStatus::Warning: + return "Normal operation of TvmClient is still possible but there are problems with refreshing cache " + "so it is expiring; " + "is tvm-api.yandex.net accessible? " + "have you changed your TVM-secret or your backend (dst) deleted its TVM-client?"; + case TClientStatus::Error: + return "TvmClient cache is already invalid (expired) or soon will be: " + "you can't check valid ServiceTicket or be authenticated by your backends (dsts)"; + case TClientStatus::IncompleteTicketsSet: + return "TvmClient cant fetch some of your tickets, this should not happen. "; + } + + return "impossible case"; + } + + private: + struct TPidCheck { + TPidCheck() + : pid_(GetPID()) + { + } + + void check() const { + const TProcessId pid = GetPID(); + Y_ENSURE_EX(pid == pid_, + TNonRetriableException() + << "Creating TvmClient is forbidden before fork. Original pid: " << pid_ + << ". Current pid: " << pid); + } + + private: + const TProcessId pid_; + } const pid_; + }; + + TString GetServiceTicketForId(const TPidCheckedClient& cl, TTvmId dst) { + return cl.GetServiceTicketFor(dst); + } + + class TCustomUpdater: public NTvmApi::TThreadedUpdater { + public: + TCustomUpdater(const NTvmApi::TClientSettings& settings, TLoggerPtr logger) + : TThreadedUpdater(settings, logger) + { + WorkerAwakingPeriod_ = TDuration::MilliSeconds(100); + PublicKeysDurations_.RefreshPeriod = TDuration::MilliSeconds(100); + Init(); + StartWorker(); + } + }; + + TPidCheckedClient* CreateTvmApiClient(NTvmApi::TClientSettings& s, TLoggerPtr logger) { + s.LibVersionPrefix = "py_"; + Y_ENSURE(s.IsIncompleteTicketsSetAnError, "incomplete tickets set is not supported in ticket_parser2"); + return new TPidCheckedClient(s, logger); + } + + class TTvmToolClientSettings: public NTvmTool::TClientSettings { + public: + using TClientSettings::TClientSettings; + }; + + TPidCheckedClient* CreateTvmToolClient(const TTvmToolClientSettings& s, TLoggerPtr logger) { + // We need to disable roles logic: client doesn't allow to use it correctly + NTvmTool::TClientSettings settingsCopy = s; + settingsCopy.ShouldCheckSrc = false; + settingsCopy.ShouldCheckDefaultUid = false; + + return new TPidCheckedClient(settingsCopy, logger); + } + + TString GetPyVersion() { + return TString("py_") + LibVersion(); + } + + void StartTvmClientStopping(TPidCheckedClient* cl) { + NInternal::TClientCaningKnife::StartTvmClientStopping(cl); + } + + bool IsTvmClientStopped(TPidCheckedClient* cl) { + return NInternal::TClientCaningKnife::IsTvmClientStopped(cl); + } + + void DestroyTvmClient(TPidCheckedClient* cl) { + delete cl; + } +} diff --git a/library/python/deprecated/ticket_parser2/ticket_parser2/__init__.py b/library/python/deprecated/ticket_parser2/ticket_parser2/__init__.py new file mode 100644 index 0000000000..863b250f0a --- /dev/null +++ b/library/python/deprecated/ticket_parser2/ticket_parser2/__init__.py @@ -0,0 +1,45 @@ +try: + from ticket_parser2_py3.ticket_parser2_pymodule import __version__ as ticket_parser2_pymodule_version +except ImportError: + from ticket_parser2.ticket_parser2_pymodule import __version__ as ticket_parser2_pymodule_version + +try: + from ticket_parser2_py3.ticket_parser2_pymodule import ( # noqa + BlackboxClientId, + BlackboxEnv, + ServiceTicket, + Status, + UserTicket, + TvmApiClientSettings, + TvmToolClientSettings, + TvmClientStatus, + TvmClient as __TvmClientImpl, + ) +except ImportError: + from ticket_parser2.ticket_parser2_pymodule import ( # noqa + BlackboxClientId, + BlackboxEnv, + ServiceTicket, + Status, + UserTicket, + TvmApiClientSettings, + TvmToolClientSettings, + TvmClientStatus, + TvmClient as __TvmClientImpl, + ) + +import warnings + + +class TvmClient(__TvmClientImpl): + pass + + +__version__ = ticket_parser2_pymodule_version + + +warnings.warn( + message="ticket_parser2 is deprecated: please use https://a.yandex-team.ru/arc/trunk/arcadia/library/python/tvmauth instead. https://clubs.at.yandex-team.ru/passport/3619", + category=DeprecationWarning, + stacklevel=2, +) diff --git a/library/python/deprecated/ticket_parser2/ticket_parser2/api/__init__.py b/library/python/deprecated/ticket_parser2/ticket_parser2/api/__init__.py new file mode 100644 index 0000000000..2ae28399f5 --- /dev/null +++ b/library/python/deprecated/ticket_parser2/ticket_parser2/api/__init__.py @@ -0,0 +1 @@ +pass diff --git a/library/python/deprecated/ticket_parser2/ticket_parser2/api/v1/__init__.py b/library/python/deprecated/ticket_parser2/ticket_parser2/api/v1/__init__.py new file mode 100644 index 0000000000..344aac31c5 --- /dev/null +++ b/library/python/deprecated/ticket_parser2/ticket_parser2/api/v1/__init__.py @@ -0,0 +1,50 @@ +try: + from ticket_parser2_py3 import ( # noqa + BlackboxClientId, + BlackboxEnv, + ServiceTicket, + Status, + UserTicket, + TvmApiClientSettings, + TvmToolClientSettings, + TvmClientStatus, + TvmClient, + ) +except ImportError: + from ticket_parser2 import ( # noqa + BlackboxClientId, + BlackboxEnv, + ServiceTicket, + Status, + UserTicket, + TvmApiClientSettings, + TvmToolClientSettings, + TvmClientStatus, + TvmClient, + ) + +try: + from ticket_parser2_py3.low_level import ( # noqa + ServiceContext, + UserContext, + ) +except ImportError: + from ticket_parser2.low_level import ( # noqa + ServiceContext, + UserContext, + ) + + +__all__ = [ + 'BlackboxClientId', + 'BlackboxEnv', + 'ServiceContext', + 'ServiceTicket', + 'Status', + 'UserContext', + 'UserTicket', + 'TvmApiClientSettings', + 'TvmToolClientSettings', + 'TvmClientStatus', + 'TvmClient', +] diff --git a/library/python/deprecated/ticket_parser2/ticket_parser2/api/v1/exceptions.py b/library/python/deprecated/ticket_parser2/ticket_parser2/api/v1/exceptions.py new file mode 100644 index 0000000000..dee69e7d4c --- /dev/null +++ b/library/python/deprecated/ticket_parser2/ticket_parser2/api/v1/exceptions.py @@ -0,0 +1,30 @@ +try: + from ticket_parser2_py3.ticket_parser2_pymodule import ( # noqa + ContextException, + EmptyTvmKeysException, + MalformedTvmKeysException, + MalformedTvmSecretException, + TicketParsingException, + TvmException, + ClientException, + BrokenTvmClientSettings, + RetriableException, + NonRetriableException, + MissingServiceTicket, + PermissionDenied, + ) +except ImportError: + from ticket_parser2.ticket_parser2_pymodule import ( # noqa + ContextException, + EmptyTvmKeysException, + MalformedTvmKeysException, + MalformedTvmSecretException, + TicketParsingException, + TvmException, + ClientException, + BrokenTvmClientSettings, + RetriableException, + NonRetriableException, + MissingServiceTicket, + PermissionDenied, + ) diff --git a/library/python/deprecated/ticket_parser2/ticket_parser2/api/v1/unittest.py b/library/python/deprecated/ticket_parser2/ticket_parser2/api/v1/unittest.py new file mode 100644 index 0000000000..45affaa1e7 --- /dev/null +++ b/library/python/deprecated/ticket_parser2/ticket_parser2/api/v1/unittest.py @@ -0,0 +1,43 @@ +try: + from ticket_parser2_py3.ticket_parser2_pymodule import ( # noqa + create_service_ticket_for_unittest, + create_user_ticket_for_unittest, + ) +except ImportError: + from ticket_parser2.ticket_parser2_pymodule import ( # noqa + create_service_ticket_for_unittest, + create_user_ticket_for_unittest, + ) + + +TVMKNIFE_PUBLIC_KEYS = ( + "1:CpgCCpMCCAEQABqIAjCCAQQCggEAcLEXeH67FQESFUn4_7wnX7wN0PUrBoUsm3QQ4W5vC-qz6sXaEjSwnTV8w1o-z6X9KPL" + "lhzMQvuS38NCNfK4uvJ4Zvfp3YsXJ25-rYtbnrYJHNvHohD-kPCCw_yZpMp21JdWigzQGuV7CtrxUhF-NNrsnUaJrE5-OpEWN" + "t4X6nCItKIYeVcSK6XJUbEWbrNCRbvkSc4ak2ymFeMuHYJVjxh4eQbk7_ZPzodP0WvF6eUYrYeb42imVEOR8ofVLQWE5DVnb1" + "z_TqZm4i1XkS7jMwZuBxBRw8DGdYei0lT_sAf7KST2jC0590NySB3vsBgWEVs1OdUUWA6r-Dvx9dsOQtSCVkQYQAAqZAgqUAg" + "gCEAAaiQIwggEFAoIBAQDhEBM5-6YsPWfogKtbluJoCX1WV2KdzOaQ0-OlRbBzeCzw-eQKu12c8WakHBbeCMd1I1TU64SDkDo" + "rWjXGIa_2xT6N3zzNAE50roTbPCcmeQrps26woTYfYIuqDdoxYKZNr0lvNLLW47vBr7EKqo1S4KSj7aXK_XYeEvUgIgf3nVIc" + "Nrio7VTnFmGGVQCepaL1Hi1gN4yIXjVZ06PBPZ-DxSRu6xOGbFrfKMJeMPs7KOyE-26Q3xOXdTIa1X-zYIucTd_bxUCL4BVbw" + "W2AvbbFsaG7ISmVdGu0XUTmhXs1KrEfUVLRJhE4Dx99hAZXm1_HlYMUeJcMQ_oHOhV94ENFIJaRBhACCpYBCpEBCAMQABqGAT" + "CBgwKBgF9t2YJGAJkRRFq6fWhi3m1TFW1UOE0f6ZrfYhHAkpqGlKlh0QVfeTNPpeJhi75xXzCe6oReRUm-0DbqDNhTShC7uGU" + "v1INYnRBQWH6E-5Fc5XrbDFSuGQw2EYjNfHy_HefHJXxQKAqPvxBDKMKkHgV58WtM6rC8jRi9sdX_ig2NIJeRBhABCpYBCpEB" + "CAQQABqGATCBgwKBgGB4d6eLGUBv-Q6EPLehC4S-yuE2HB-_rJ7WkeYwyp-xIPolPrd-PQme2utHB4ZgpXHIu_OFksDe_0bPg" + "ZniNRSVRbl7W49DgS5Ya3kMfrYB4DnF5Fta5tn1oV6EwxYD4JONpFTenOJALPGTPawxXEfon_peiHOSBuQMu3_Vn-l1IJiRBh" + "ADCpcBCpIBCAUQABqHATCBhAKBgQCTJMKIfmfeZpaI7Q9rnsc29gdWawK7TnpVKRHws1iY7EUlYROeVcMdAwEqVM6f8BVCKLG" + "gzQ7Gar_uuxfUGKwqEQzoppDraw4F75J464-7D5f6_oJQuGIBHZxqbMONtLjBCXRUhQW5szBLmTQ_R3qaJb5vf-h0APZfkYhq" + "1cTttSCZkQYQBAqWAQqRAQgLEAAahgEwgYMCgYBvvGVH_M2H8qxxv94yaDYUTWbRnJ1uiIYc59KIQlfFimMPhSS7x2tqUa2-h" + "I55JiII0Xym6GNkwLhyc1xtWChpVuIdSnbvttbrt4weDMLHqTwNOF6qAsVKGKT1Yh8yf-qb-DSmicgvFc74mBQm_6gAY1iQsf" + "33YX8578ClhKBWHSCVkQYQAAqXAQqSAQgMEAAahwEwgYQCgYEAkuzFcd5TJu7lYWYe2hQLFfUWIIj91BvQQLa_Thln4YtGCO8" + "gG1KJqJm-YlmJOWQG0B7H_5RVhxUxV9KpmFnsDVkzUFKOsCBaYGXc12xPVioawUlAwp5qp3QQtZyx_se97YIoLzuLr46UkLcL" + "nkIrp-Jo46QzYi_QHq45WTm8MQ0glpEGEAIKlwEKkgEIDRAAGocBMIGEAoGBAIUzbxOknXf_rNt17_ir8JlWvrtnCWsQd1MAn" + "l5mgArvavDtKeBYHzi5_Ak7DHlLzuA6YE8W175FxLFKpN2hkz-l-M7ltUSd8N1BvJRhK4t6WffWfC_1wPyoAbeSN2Yb1jygtZ" + "JQ8wGoXHcJQUXiMit3eFNyylwsJFj1gzAR4JCdIJeRBhABCpYBCpEBCA4QABqGATCBgwKBgFMcbEpl9ukVR6AO_R6sMyiU11I" + "8b8MBSUCEC15iKsrVO8v_m47_TRRjWPYtQ9eZ7o1ocNJHaGUU7qqInFqtFaVnIceP6NmCsXhjs3MLrWPS8IRAy4Zf4FKmGOx3" + "N9O2vemjUygZ9vUiSkULdVrecinRaT8JQ5RG4bUMY04XGIwFIJiRBhADCpYBCpEBCA8QABqGATCBgwKBgGpCkW-NR3li8GlRv" + "qpq2YZGSIgm_PTyDI2Zwfw69grsBmPpVFW48Vw7xoMN35zcrojEpialB_uQzlpLYOvsMl634CRIuj-n1QE3-gaZTTTE8mg-AR" + "4mcxnTKThPnRQpbuOlYAnriwiasWiQEMbGjq_HmWioYYxFo9USlklQn4-9IJmRBhAEEpUBCpIBCAYQABqHATCBhAKBgQCoZkF" + "Gm9oLTqjeXZAq6j5S6i7K20V0lNdBBLqfmFBIRuTkYxhs4vUYnWjZrKRAd5bp6_py0csmFmpl_5Yh0b-2pdo_E5PNP7LGRzKy" + "KSiFddyykKKzVOazH8YYldDAfE8Z5HoS9e48an5JsPg0jr-TPu34DnJq3yv2a6dqiKL9zSCakQYSlQEKkgEIEBAAGocBMIGEA" + "oGBALhrihbf3EpjDQS2sCQHazoFgN0nBbE9eesnnFTfzQELXb2gnJU9enmV_aDqaHKjgtLIPpCgn40lHrn5k6mvH5OdedyI6c" + "CzE-N-GFp3nAq0NDJyMe0fhtIRD__CbT0ulcvkeow65ubXWfw6dBC2gR_34rdMe_L_TGRLMWjDULbNIJqRBg" +) diff --git a/library/python/deprecated/ticket_parser2/ticket_parser2/exceptions.py b/library/python/deprecated/ticket_parser2/ticket_parser2/exceptions.py new file mode 100644 index 0000000000..dee69e7d4c --- /dev/null +++ b/library/python/deprecated/ticket_parser2/ticket_parser2/exceptions.py @@ -0,0 +1,30 @@ +try: + from ticket_parser2_py3.ticket_parser2_pymodule import ( # noqa + ContextException, + EmptyTvmKeysException, + MalformedTvmKeysException, + MalformedTvmSecretException, + TicketParsingException, + TvmException, + ClientException, + BrokenTvmClientSettings, + RetriableException, + NonRetriableException, + MissingServiceTicket, + PermissionDenied, + ) +except ImportError: + from ticket_parser2.ticket_parser2_pymodule import ( # noqa + ContextException, + EmptyTvmKeysException, + MalformedTvmKeysException, + MalformedTvmSecretException, + TicketParsingException, + TvmException, + ClientException, + BrokenTvmClientSettings, + RetriableException, + NonRetriableException, + MissingServiceTicket, + PermissionDenied, + ) diff --git a/library/python/deprecated/ticket_parser2/ticket_parser2/low_level.py b/library/python/deprecated/ticket_parser2/ticket_parser2/low_level.py new file mode 100644 index 0000000000..58d9f933e8 --- /dev/null +++ b/library/python/deprecated/ticket_parser2/ticket_parser2/low_level.py @@ -0,0 +1,10 @@ +try: + from ticket_parser2_py3.ticket_parser2_pymodule import ( # noqa + ServiceContext, + UserContext, + ) +except ImportError: + from ticket_parser2.ticket_parser2_pymodule import ( # noqa + ServiceContext, + UserContext, + ) diff --git a/library/python/deprecated/ticket_parser2/ticket_parser2/mock.py b/library/python/deprecated/ticket_parser2/ticket_parser2/mock.py new file mode 100644 index 0000000000..201f2045bf --- /dev/null +++ b/library/python/deprecated/ticket_parser2/ticket_parser2/mock.py @@ -0,0 +1,141 @@ +from __future__ import absolute_import + +try: + import mock # noqa +except ImportError: + import unittest.mock # noqa + +try: + import ticket_parser2_py3 as tp2 # noqa + import ticket_parser2_py3.low_level as tp2l # noqa + import ticket_parser2_py3.exceptions as tp2e # noqa + import ticket_parser2_py3.unittest as tp2u # noqa +except ImportError: + import ticket_parser2 as tp2 # noqa + import ticket_parser2.low_level as tp2l # noqa + import ticket_parser2.exceptions as tp2e # noqa + import ticket_parser2.unittest as tp2u # noqa + + +__doc__ = """ +Use TvmClientPatcher to replace TvmClient with MockedTvmClient. +MockedTvmClient can check ServiceTickets and UserTickets from `tvmknife unittest` +Read more: https://wiki.yandex-team.ru/passport/tvm2/debug/#tvmknife +Examples are in docstring for TvmClientPatcher. +""" + + +PUBLIC_KEYS = tp2u.TVMKNIFE_PUBLIC_KEYS + + +class MockedTvmClient(object): + def __init__(self, status=tp2.TvmClientStatus.Ok, self_client_id=100500, bb_env=tp2.BlackboxEnv.Test): + self._status = status + self._serv_ctx = tp2l.ServiceContext(self_client_id, None, PUBLIC_KEYS) + self._user_ctx = tp2l.UserContext(bb_env, PUBLIC_KEYS) + self._stopped = False + + def __check(self): + if self._stopped: + raise tp2e.NonRetriableException("TvmClient is already stopped") + + def stop(self): + self._stopped = True + + @property + def status(self): + self.__check() + return self._status + + @staticmethod + def status_to_string(status): + return tp2.TvmClient.status_to_string(status) + + def get_service_ticket_for(self, alias=None, client_id=None): + """ + You can generate any ticket you want with `tvmknife unittest` and override this function with your ticket + https://wiki.yandex-team.ru/passport/tvm2/debug/ + """ + self.__check() + if alias is None and client_id is None: + raise tp2e.TvmException("One of args is required: 'alias' or 'client_id'") + return "Some service ticket" + + def check_service_ticket(self, ticket): + self.__check() + return self._serv_ctx.check(ticket) + + def check_user_ticket(self, ticket): + self.__check() + return self._user_ctx.check(ticket) + + +class TvmClientPatcher(object): + """ + Example: + with TvmClientPatcher(): + c = TvmClient() + assert TvmClientStatus.Ok == c.status + assert 123 == c.check_service_ticket(SRV_TICKET).src + assert 123 == c.check_user_ticket(USER_TICKET_TEST).default_uid + assert 'Some service ticket' == c.get_service_ticket_for("foo") + + Example: + with TvmClientPatcher(MockedTvmClient(self_client_id=100501)): + c = TvmClient() + assert TvmClientStatus.Ok == c.status + with pytest.raises(TicketParsingException): + c.check_service_ticket(SRV_TICKET) + assert 123 == c.check_user_ticket(TEST_TICKET).default_uid + assert 'Some service ticket' == c.get_service_ticket_for("foo") + + Example: + with TvmClientPatcher(MockedTvmClient()) as p: + p.get_mocked_tvm_client().check_service_ticket = mock.Mock( + side_effect=TicketParsingException("Unsupported version", Status.UnsupportedVersion, "2:err"), + ) + + c = TvmClient() + assert TvmClientStatus.Ok == c.status + with pytest.raises(TicketParsingException): + c.check_service_ticket(SRV_TICKET) + + Example: + m = MockedTvmClient() + m.get_service_ticket_for = mock.Mock(side_effect=[ + 'SERVICE_TICKET_FOR_MY_FIRST_CALL', + 'SERVICE_TICKET_FOR_MY_SECOND_CALL'], + ) + with TvmClientPatcher(m): + c = TvmClient() + assert TvmClientStatus.Ok == c.status + assert 'SERVICE_TICKET_FOR_MY_FIRST_CALL' == c.get_service_ticket_for() + assert 'SERVICE_TICKET_FOR_MY_SECOND_CALL' == c.get_service_ticket_for() + """ + + def __init__(self, mocked_tvm_client=None): + if mocked_tvm_client is None: + mocked_tvm_client = MockedTvmClient() + self._mocked_tvm_client = mocked_tvm_client + self._patch = mock.patch.object( + tp2.TvmClient, + '__new__', + mock.Mock(return_value=mocked_tvm_client), + ) + + def start(self): + self._patch.start() + return self + + def stop(self): + self._patch.stop() + + def __enter__(self): + self.start() + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + self.stop() + + def get_mocked_tvm_client(self): + return self._mocked_tvm_client diff --git a/library/python/deprecated/ticket_parser2/ticket_parser2/ticket_parser2_pymodule.pyx b/library/python/deprecated/ticket_parser2/ticket_parser2/ticket_parser2_pymodule.pyx new file mode 100644 index 0000000000..daeed81cf4 --- /dev/null +++ b/library/python/deprecated/ticket_parser2/ticket_parser2/ticket_parser2_pymodule.pyx @@ -0,0 +1,878 @@ +# coding: utf-8 +import datetime +import logging +import time +from cpython cimport PyObject +from libcpp cimport bool as bool_t +from libcpp.map cimport map as cmap +from libcpp.pair cimport pair +from libc.stdint cimport uint32_t, uint64_t +from libc.time cimport time_t +from cython.operator cimport dereference +cimport cpython.ref as cpy_ref + +from enum import ( + Enum, + IntEnum, +) + +from util.datetime.base cimport TInstant +from util.generic.hash cimport THashMap +from util.generic.maybe cimport TMaybe +from util.generic.ptr cimport THolder +from util.generic.string cimport TString, TStringBuf +from util.generic.vector cimport TVector + + +cdef extern from "Python.h": + cdef void PyEval_InitThreads() + +class TvmException(Exception): + pass + +class ContextException(TvmException): + pass + +class EmptyTvmKeysException(ContextException): + pass + +class MalformedTvmKeysException(ContextException): + pass + +class MalformedTvmSecretException(ContextException): + pass + +class NotAllowedException(TvmException): + pass + +class ClientException(TvmException): + pass + +class RetriableException(ClientException): + pass + +class NonRetriableException(ClientException): + pass + +class BrokenTvmClientSettings(NonRetriableException): + pass + +class MissingServiceTicket(NonRetriableException): + pass + +class PermissionDenied(NonRetriableException): + pass + +class TicketParsingException(TvmException): + def __init__(self, message, status, debug_info): + self.message = message + self.status = status + self.debug_info = debug_info + +cdef public PyObject* pyEmptyTvmKeysException = <PyObject*>EmptyTvmKeysException +cdef public PyObject* pyMalformedTvmKeysException = <PyObject*>MalformedTvmKeysException +cdef public PyObject* pyMalformedTvmSecretException = <PyObject*>MalformedTvmSecretException +cdef public PyObject* pyNotAllowedException = <PyObject*>NotAllowedException +cdef public PyObject* pyTicketParsingException = <PyObject*>TicketParsingException +cdef public PyObject* pyClientException = <PyObject*>ClientException +cdef public PyObject* pyBrokenTvmClientSettings = <PyObject*>BrokenTvmClientSettings +cdef public PyObject* pyRetriableException = <PyObject*>RetriableException +cdef public PyObject* pyNonRetriableException = <PyObject*>NonRetriableException +cdef public PyObject* pyMissingServiceTicket = <PyObject*>MissingServiceTicket +cdef public PyObject* pyPermissionDenied = <PyObject*>PermissionDenied + + +cdef extern from "library/cpp/containers/stack_vector/stack_vec.h" nogil: + cdef cppclass TSmallVec[T](TVector): + pass + +cdef extern from "library/python/deprecated/ticket_parser2/src/exception.h": + cdef void raise_py_error() + +cdef extern from "library/cpp/tvmauth/ticket_status.h" namespace "NTvmAuth" nogil: + cdef cppclass EStatus "NTvmAuth::ETicketStatus": + pass + TStringBuf StatusToString(EStatus status); + +cdef extern from "library/cpp/tvmauth/ticket_status.h" namespace "NTvmAuth::ETicketStatus" nogil: + cdef EStatus cOk "NTvmAuth::ETicketStatus::Ok" + cdef EStatus cExpired "NTvmAuth::ETicketStatus::Expired" + cdef EStatus cInvalidBlackboxEnv "NTvmAuth::ETicketStatus::InvalidBlackboxEnv" + cdef EStatus cInvalidDst "NTvmAuth::ETicketStatus::InvalidDst" + cdef EStatus cInvalidTicketType "NTvmAuth::ETicketStatus::InvalidTicketType" + cdef EStatus cMalformed "NTvmAuth::ETicketStatus::Malformed" + cdef EStatus cMissingKey "NTvmAuth::ETicketStatus::MissingKey" + cdef EStatus cSignBroken "NTvmAuth::ETicketStatus::SignBroken" + cdef EStatus cUnsupportedVersion "NTvmAuth::ETicketStatus::UnsupportedVersion" + +class Status(IntEnum): + """ + Status mean result of ticket check + """ + Ok = <int>cOk + Expired = <int>cExpired + InvalidBlackboxEnv = <int>cInvalidBlackboxEnv + InvalidDst = <int>cInvalidDst + InvalidTicketType = <int>cInvalidTicketType + Malformed = <int>cMalformed + MissingKey = <int>cMissingKey + SignBroken = <int>cSignBroken + UnsupportedVersion = <int>cUnsupportedVersion + +cdef extern from "library/cpp/tvmauth/checked_user_ticket.h" namespace "NTvmAuth" nogil: + cdef cppclass EBlackboxEnv "NTvmAuth::EBlackboxEnv": + pass + +cdef extern from "library/cpp/tvmauth/checked_user_ticket.h" namespace "NTvmAuth::EBlackboxEnv" nogil: + cdef EBlackboxEnv cProd "NTvmAuth::EBlackboxEnv::Prod" + cdef EBlackboxEnv cTest "NTvmAuth::EBlackboxEnv::Test" + cdef EBlackboxEnv cProdYateam "NTvmAuth::EBlackboxEnv::ProdYateam" + cdef EBlackboxEnv cTestYateam "NTvmAuth::EBlackboxEnv::TestYateam" + cdef EBlackboxEnv cStress "NTvmAuth::EBlackboxEnv::Stress" + +class BlackboxEnv(IntEnum): + """ + BlackboxEnv describes environment of Passport: + https://wiki.yandex-team.ru/passport/tvm2/user-ticket/#0-opredeljaemsjasokruzhenijami + """ + Prod = <int>cProd + Test = <int>cTest + ProdYateam = <int>cProdYateam + TestYateam = <int>cTestYateam + Stress = <int>cStress + +class BlackboxClientId(Enum): + Prod = '222' + Test = '224' + ProdYateam = '223' + TestYateam = '225' + Stress = '226' + Mimino = '239' + +cdef extern from "library/cpp/tvmauth/type.h" namespace "NTvmAuth" nogil: + ctypedef uint32_t TTvmId + ctypedef uint64_t TUid + + cdef cppclass TScopes(TSmallVec[TStringBuf]): + pass + + cdef cppclass TUids(TSmallVec[TUid]): + pass + +cdef extern from "library/cpp/tvmauth/src/service_impl.h" namespace "NTvmAuth" nogil: + cdef cppclass TCheckedServiceTicket: + cppclass TImpl: + TImpl() except +raise_py_error + bool_t operator bool() except +raise_py_error + TString DebugInfo() except +raise_py_error + bool_t HasScope(TStringBuf scopeName) except +raise_py_error + time_t GetExpirationTime() except +raise_py_error + const TScopes& GetScopes() except +raise_py_error + TTvmId GetSrc() except +raise_py_error + EStatus GetStatus() except +raise_py_error + TMaybe[TUid] GetIssuerUid() except +raise_py_error + + @staticmethod + THolder[TCheckedServiceTicket.TImpl] CreateTicketForTests(EStatus, TTvmId, TMaybe[TUid]) except +raise_py_error + + cdef cppclass TServiceContext: + cppclass TImpl: + TImpl(TStringBuf secretBase64, int clientId, TStringBuf tvmKeysResponse) except +raise_py_error + TImpl(int clientId, TStringBuf tvmKeysResponse) except +raise_py_error + TImpl(TStringBuf secretBase64) except +raise_py_error + THolder[TCheckedServiceTicket.TImpl] Check(TStringBuf ticketBody) except +raise_py_error + void ResetKeys(TStringBuf tvmKeysResponse) except +raise_py_error + TString SignCgiParamsForTvm(TStringBuf ts, TStringBuf dst, TStringBuf scopes) except +raise_py_error const + +cdef extern from "library/cpp/tvmauth/src/user_impl.h" namespace "NTvmAuth" nogil: + cdef cppclass TCheckedUserTicket: + cppclass TImpl: + TImpl() except +raise_py_error + bool_t operator bool() except +raise_py_error + bool_t HasScope(TStringBuf scopeName) except +raise_py_error + TString DebugInfo() except +raise_py_error + TUid GetDefaultUid() except +raise_py_error + time_t GetExpirationTime() except +raise_py_error + const TScopes& GetScopes() except +raise_py_error + EStatus GetStatus() except +raise_py_error + const TUids& GetUids() except +raise_py_error + + @staticmethod + THolder[TCheckedUserTicket.TImpl] CreateTicketForTests(EStatus, TUid, TScopes, TUids) except +raise_py_error + + cdef cppclass TUserContext: + cppclass TImpl: + TImpl(EBlackboxEnv env, TStringBuf tvmKeysResponse) except +raise_py_error + THolder[TCheckedUserTicket.TImpl] Check(TStringBuf ticketBody) except +raise_py_error + void ResetKeys(TStringBuf tvmKeysResponse) except +raise_py_error + +cdef extern from "library/cpp/tvmauth/utils.h" namespace "NTvmAuth::NUtils" nogil: + TStringBuf RemoveTicketSignature(TStringBuf ticketBody) except +raise_py_error + +cdef extern from "library/cpp/tvmauth/client/misc/api/settings.h" namespace "NTvmAuth::NTvmApi" nogil: + cdef cppclass TClientSettings: + cppclass TDst: + TDst(TTvmId) except +raise_py_error + + ctypedef THashMap[TString, TDst] TDstMap + ctypedef TVector[TDst] TDstVector + + TClientSettings() except +raise_py_error + void CheckValid() except +raise_py_error + + TString DiskCacheDir + TTvmId SelfTvmId + TString Secret # Actual type is NSecretString::TSecretString, but for operator=() it is enough + + TDstVector FetchServiceTicketsForDsts + TDstMap FetchServiceTicketsForDstsWithAliases + bool_t CheckServiceTickets + TMaybe[EBlackboxEnv] CheckUserTicketsWithBbEnv + + TString TvmHost + int TvmPort + + +cdef extern from "library/cpp/tvmauth/client/client_status.h" namespace "NTvmAuth" nogil: + cdef cppclass TClientStatus: + cppclass ECode "ECode": + pass + ECode GetCode() + TClientStatus.ECode cCsOk "NTvmAuth::TClientStatus::Ok" + TClientStatus.ECode cCsWarning "NTvmAuth::TClientStatus::Warning" + TClientStatus.ECode cCsError "NTvmAuth::TClientStatus::Error" + + +class TvmClientStatus(IntEnum): + """ + Description: + https://a.yandex-team.ru/arc/trunk/arcadia/library/python/deprecated/ticket_parser2/README.md#high-level-interface + """ + Ok = <int>cCsOk + ExpiringCache = <int>cCsWarning + InvalidCache = <int>cCsError + IncompleteListOfServiceTickets = <int>3 + +cdef extern from "library/cpp/tvmauth/src/utils.h" namespace "NTvmAuth::NInternal" nogil: + cdef cppclass TCanningKnife: + @staticmethod + TCheckedServiceTicket.TImpl* GetS(TCheckedServiceTicket& t) + @staticmethod + TCheckedUserTicket.TImpl* GetU(TCheckedUserTicket& t) + +cdef extern from "library/python/deprecated/ticket_parser2/src/logger.h" namespace "NTvmAuth" nogil: + cdef cppclass IPyLogger: + IPyLogger(cpy_ref.PyObject *obj) + void Log(int lvl, const TString& msg) + +cdef extern from "library/python/deprecated/ticket_parser2/src/utils.h" namespace "NTvmAuth" nogil: + cdef cppclass TPidCheckedClient: + TPidCheckedClient(TCustomUpdater*) except +raise_py_error + TClientStatus GetStatus() except +raise_py_error + TStringBuf GetStatusString() except +raise_py_error + TInstant GetUpdateTimeOfPublicKeys() except +raise_py_error + TInstant GetUpdateTimeOfServiceTickets() except +raise_py_error + TString GetServiceTicketFor(const TString& dst) except +raise_py_error + TCheckedServiceTicket CheckServiceTicket(TStringBuf ticket) except +raise_py_error + TCheckedUserTicket CheckUserTicket(TStringBuf ticket) except +raise_py_error + TCheckedUserTicket CheckUserTicketWithOveridedEnv(TStringBuf ticket, EBlackboxEnv env) except +raise_py_error + @staticmethod + TStringBuf StatusToString(TClientStatus.ECode status) except +raise_py_error + + cdef TString GetServiceTicketForId(const TPidCheckedClient&, TTvmId) except +raise_py_error + cdef TPidCheckedClient* CreateTvmApiClient(TClientSettings& settings, IPyLogger*) except +raise_py_error + cdef TPidCheckedClient* CreateTvmToolClient(const TTvmToolClientSettings&, IPyLogger*) except +raise_py_error + cdef TString GetPyVersion() except +raise_py_error + cdef void StartTvmClientStopping(TPidCheckedClient*) + cdef bool_t IsTvmClientStopped(TPidCheckedClient*) + cdef void DestroyTvmClient(TPidCheckedClient*) + + cdef cppclass TCustomUpdater: + TCustomUpdater(const TClientSettings&, IPyLogger*) except +raise_py_error + + cdef cppclass TTvmToolClientSettings: + TTvmToolClientSettings(TString) except +raise_py_error + TTvmToolClientSettings& SetPort(int) + TTvmToolClientSettings& SetHostname(const TString&) except +raise_py_error + TTvmToolClientSettings& SetAuthToken(const TString&) except +raise_py_error + TTvmToolClientSettings& OverrideBlackboxEnv(EBlackboxEnv env) except +raise_py_error + +__version__ = GetPyVersion().decode('utf-8') + +cdef class ServiceContext: + """ + WARNING: it is low level API: first of all try use TvmClient. It is not deprecated but don't use it. + Long lived object for keeping client's credentials for TVM + """ + cdef TServiceContext.TImpl* baseptr + def __cinit__(self, int client_id, secret, tvm_keys): + if tvm_keys is None and secret is None: + raise ContextException("secret and tvm_keys both can't be None") + if secret is None: + self.baseptr = new TServiceContext.TImpl(client_id, <TString>tvm_keys.encode('utf-8')) + elif tvm_keys is None: + self.baseptr = new TServiceContext.TImpl(<TString>secret.encode('utf-8')) + else: + self.baseptr = new TServiceContext.TImpl(<TString>secret.encode('utf-8'), client_id, <TString>tvm_keys.encode('utf-8')) + + def __dealloc__(self): + del self.baseptr + + cdef __sign(self, TString timestamp, TString dst, TString scopes): + return self.baseptr.SignCgiParamsForTvm(timestamp, dst, scopes).decode('utf-8') + + @staticmethod + cdef __check(TCheckedServiceTicket.TImpl* ticket): + tick = ServiceTicket() + tick.baseptr = ticket + raw_status = tick.baseptr.GetStatus() + status = Status(<int>raw_status) + if status != Status.Ok: + raise TicketParsingException(StatusToString(raw_status).decode('utf-8'), status, tick.debug_info()) + return tick + + def check(self, ticket_body): + return ServiceContext.__check(self.baseptr.Check(<TString>ticket_body.encode('utf-8')).Release()) + + def reset_keys(self, tvm_keys): + self.baseptr.ResetKeys(<TString>tvm_keys.encode('utf-8')) + + def sign(self, timestamp, dst, scopes=None): + if isinstance(timestamp, int): + timestamp = str(timestamp) + if isinstance(dst, list): + dst = ','.join(map(lambda x: x if isinstance(x, str) else str(x), dst)) + elif isinstance(dst, int): + dst = str(dst) + if isinstance(scopes, list): + scopes = ','.join(map(lambda x: x if isinstance(x, str) else str(x), scopes)) + elif scopes is None: + scopes = '' + return self.__sign(timestamp.encode('utf-8'), dst.encode('utf-8'), scopes.encode('utf-8')) + +cdef class ServiceTicket: + cdef TCheckedServiceTicket.TImpl* baseptr + def __dealloc__(self): + del self.baseptr + + def __nonzero__(self): + return <bool_t>(dereference(self.baseptr)) + + def __str__(self): + return self.debug_info() + + def __repr__(self): + return str(self) + + def debug_info(self): + """ + :return: Human readable data for debug purposes + """ + return self.baseptr.DebugInfo().decode('utf8') + + def has_scope(self, scope_name): + return self.baseptr.HasScope(<TString>scope_name.encode('utf-8')) + + @staticmethod + def remove_signature(ticket_body): + """ + :param ticket_body: Full ticket body + :return: Safe for logging part of ticket - it can be parsed later with `tvmknife parse_ticket -t ...` + """ + return RemoveTicketSignature(<TString>ticket_body.encode('utf-8')).decode('utf-8') + + @property + def scopes(self): + rlist = [] + scopes = self.baseptr.GetScopes() + for i in range(scopes.size()): + rlist.append(scopes[i].decode('utf-8')) + return rlist + + @property + def src(self): + """ + You should check SrcID by yourself with your ACL. + + :return: ID of request source service + """ + return self.baseptr.GetSrc() + + @property + def issuer_uid(self): + """ + IssuerUID is UID of developer who is debuging something, so he(she) issued ServiceTicket with his(her) ssh-sign: + it is grant_type=sshkey in tvm-api + https://wiki.yandex-team.ru/passport/tvm2/debug/#sxoditvapizakrytoeserviceticketami. + + :return: UID or `None` + """ + u = self.baseptr.GetIssuerUid() + + if u.Defined(): + return u.GetRef() + + +def create_service_ticket_for_unittest(status, int src, issuer_uid=None): + cdef TMaybe[TUid] uid + if issuer_uid is not None: + uid = <int>issuer_uid + return ServiceContext.__check(TCheckedServiceTicket.TImpl.CreateTicketForTests( + <EStatus><int>status, src, uid).Release()) + + +cdef class UserContext: + """ + WARNING: it is low level API: first of all try use TvmClient. It is not deprecated but don't use it. + Long lived object for keeping client's credentials for TVM + """ + cdef TUserContext.TImpl* baseptr + def __cinit__(self, int env, tvm_keys): + self.baseptr = new TUserContext.TImpl(<EBlackboxEnv>env, <TString>tvm_keys.encode('utf-8')) + + def __dealloc__(self): + del self.baseptr + + @staticmethod + cdef __check(TCheckedUserTicket.TImpl* ticket): + tick = UserTicket() + tick.baseptr = ticket + raw_status = tick.baseptr.GetStatus() + status = Status(<int>raw_status) + if status != Status.Ok: + raise TicketParsingException(StatusToString(raw_status).decode('utf-8'), status, tick.debug_info()) + return tick + + def check(self, ticket_body): + return UserContext.__check(self.baseptr.Check(<TString>ticket_body.encode('utf-8')).Release()) + + def reset_keys(self, tvm_keys): + self.baseptr.ResetKeys(<TString>tvm_keys.encode('utf-8')) + +cdef class UserTicket: + """ + UserTicket contains only valid users. + Details: https://wiki.yandex-team.ru/passport/tvm2/user-ticket/#chtoestvusertickete + """ + cdef TCheckedUserTicket.TImpl* baseptr + def __dealloc__(self): + del self.baseptr + + def __str__(self): + return self.debug_info() + + def __repr__(self): + return str(self) + + def debug_info(self): + """ + :return: Human readable data for debug purposes + """ + return self.baseptr.DebugInfo().decode('utf8') + + @property + def default_uid(self): + """ + Default UID maybe 0 + + :return: default user + """ + return self.baseptr.GetDefaultUid() + + def has_scope(self, scope_name): + return self.baseptr.HasScope(<TString>scope_name.encode('utf-8')) + + @staticmethod + def remove_signature(ticket_body): + """ + :param ticket_body: Full ticket body + :return: Safe for logging part of ticket - it can be parsed later with `tvmknife parse_ticket -t ...` + """ + return RemoveTicketSignature(<TString>ticket_body.encode('utf-8')).decode('utf-8') + + @property + def scopes(self): + """ + Scopes is array of scopes inherited from credential - never empty + + :return: Array of scopes + """ + rlist = [] + scopes = self.baseptr.GetScopes() + for i in range(scopes.size()): + rlist.append(scopes[i].decode('utf-8')) + return rlist + + @property + def uids(self): + """ + UIDs is array of valid users - never empty + + :return: Array of valid users + """ + rlist = [] + uids = self.baseptr.GetUids() + for i in range(uids.size()): + rlist.append(uids[i]) + return rlist + + def __nonzero__(self): + return <bool_t>(dereference(self.baseptr)) + + +def create_user_ticket_for_unittest(status, int default_uid, scopes=[], uids=[]): + cdef TScopes sc + cdef TVector[TString] sc_tmp + cdef TUids ui + + for v in scopes: + sc_tmp.push_back(v.encode('utf-8')) + sc.push_back(sc_tmp.back()) + for v in uids: + ui.push_back(<int>v) + + return UserContext.__check(TCheckedUserTicket.TImpl.CreateTicketForTests( + <EStatus><int>status, default_uid, sc, ui).Release()) + + +cdef class TvmApiClientSettings: + """ + Settings for TVM client. Uses https://tvm-api.yandex.net to get state. + """ + cdef TClientSettings* baseptr + + def __init__(self, + self_client_id=None, + enable_service_ticket_checking=False, + enable_user_ticket_checking=None, + self_secret=None, + dsts=None, + ): + """ + Examples: + - Checking of ServiceTickets: + TvmApiClientSettings(self_client_id=100500, enable_service_ticket_checking=True) + - Checking of UserTickets: + TvmApiClientSettings(enable_user_ticket_checking=BlackboxEnv.Test) + - Fetching of ServiceTickets (with aliases): + # init + s = TvmApiClientSettings( + self_client_id=100500, + self_secret='my_secret', + dsts={'my backend': int(config.get_back_client_id())}, + ) + ... + # per request + service_ticket_for_backend = c.get_service_ticket_for('my_backend') + + # Key in dict is internal ALIAS of destination in your code. + # It allowes not to bring destination's client_id to each calling point. + - Fetching of ServiceTickets (with client_id): + # init + s = TvmApiClientSettings( + self_client_id=100500, + self_secret='my_secret', + dsts=[42], + ) + ... + # per request + service_ticket_for_backend = c.get_service_ticket_for(42) + + :param self_client_id: int - TVM-client_id of your service + :param enable_service_ticket_checking: boolean - flag for SeviceTicket checking + :param enable_user_ticket_checking: enum EBlackboxEnv - blackbox enviroment enables UserTicket checking with env + :param self_secret: string - TVM-secret of your service + :param dsts: dict (string -> int) - map of alias to client_id of your destination + or list (int) - client_id of your destination + + :raises `~BrokenTvmClientSettings`: Raised in case of settings validation fails. + """ + pass + + def __cinit__(self, + self_client_id=None, + enable_service_ticket_checking=False, + enable_user_ticket_checking=None, + self_secret=None, + dsts=None, + ): + self.baseptr = new TClientSettings() + + if self_client_id is not None: + self.baseptr.SelfTvmId = <int>self_client_id + + if enable_service_ticket_checking: + self.baseptr.CheckServiceTickets = True + + if enable_user_ticket_checking is not None: # check for None because enum has valid value == 0 + self.baseptr.CheckUserTicketsWithBbEnv = <EBlackboxEnv><int>enable_user_ticket_checking + + if self_secret: + self.baseptr.Secret = <TString>self_secret.encode('utf-8') + + if isinstance(dsts, dict): + for k, v in dsts.items(): + self.baseptr.FetchServiceTicketsForDstsWithAliases.insert(pair[TString, TClientSettings.TDst](k.encode('utf-8'), TClientSettings.TDst(<int>v))) + elif isinstance(dsts, list): + for v in dsts: + self.baseptr.FetchServiceTicketsForDsts.push_back(TClientSettings.TDst(<int>v)) + elif dsts is not None: + raise TvmException("dsts must be dict or list") + + self.baseptr.CheckValid() + + def __dealloc__(self): + del self.baseptr + + def set_disk_cache_dir(self, dir): + """ + Set path to directory for disk cache + Requires read/write permissions. Checks permissions + WARNING: The same directory can be used only: + - for TVM clients with the same settings + OR + - for new client replacing previous - with another config. + System user must be the same for processes with these clients inside. + Implementation doesn't provide other scenarios. + + :param dir: directory should exist + """ + self.baseptr.DiskCacheDir = <TString>dir.encode('utf-8') + + cdef TString __host + cdef int __port + + def __set_localhost(self, port): + self.__host = TString('localhost') + self.__port = <int>port + self.baseptr.TvmHost = self.__host + self.baseptr.TvmPort = self.__port + + +cdef class TvmToolClientSettings: + """ + Uses local http-interface to get state: http://localhost/tvm/. + This interface can be provided with tvmtool (local daemon) or Qloud/YP (local http api in container). + See more: https://wiki.yandex-team.ru/passport/tvm2/qloud/. + """ + cdef TTvmToolClientSettings* baseptr + + def __init__(self, + self_alias, + auth_token=None, + port=None, + hostname="localhost", + override_bb_env=None, + ): + """ + Examples: + - Ctor for Qloud: + TvmToolClientSettings("me") # 'me' was specified as alias for your tvm client_id in Qloud interface + - Ctor for local tvmtool: + TvmToolClientSettings("me", auth_token="AAAAAAAAAAAAAAAAAAAAAA", port=18080) + - Ctor for remote tvmtool - in dev-environment (if you need this): + TvmToolClientSettings("me", auth_token="AAAAAAAAAAAAAAAAAAAAAA", port=18080, hostname="front.dev.yandex.net") + - Get ticket from client: + c = TvmClient(TvmToolClientSettings("me")) # 'me' was specified as alias for your tvm client in Qloud interface + t = c.get_service_ticket_for("push-client") # 'push-client' was specified as alias for dst in Qloud interface + t = c.get_service_ticket_for(100500) # 100500 was specified as dst in Qloud interface + - Check user ticket for another bb_env: + TvmToolClientSettings("me", override_bb_env=BlackboxEnv.ProdYateam) # BlackboxEnv.Prod was specified for tvmtool + + :param self_alias: string - alias for your TVM-client_id - needs to be specified in settings of tvmtool/Qloud/YP + :param auth_token: string - default value == env['TVMTOOL_LOCAL_AUTHTOKEN'] (provided with Yandex.Deploy) or env['QLOUD_TVM_TOKEN'] (provided with Qloud) + :param port: int - autodetected for Qloud/YP. TCP port for HTTP-interface provided with tvmtool/Qloud/YP + :param hostname: string - hostname for tvmtool + :param override_bb_env: enum EBlackboxEnv - blackbox enviroment overrides env from tvmtool. Allowed only: + - Prod/ProdYateam -> Prod/ProdYateam + - Test/TestYateam -> Test/TestYateam + - Stress -> Stress + You can contact tvm-dev@yandex-team.ru if limitations are too strict + """ + pass + + def __cinit__(self, + self_alias, + auth_token=None, + port=None, + hostname="localhost", + override_bb_env=None, + ): + self.baseptr = new TTvmToolClientSettings(<TString>self_alias.encode('utf-8')) + + if auth_token is not None: + self.baseptr.SetAuthToken(<TString>auth_token.encode('utf-8')) + + if port is not None: + self.baseptr.SetPort(<int>port) + + if hostname is not None: + self.baseptr.SetHostname(<TString>hostname.encode('utf-8')) + + if override_bb_env is not None: + self.baseptr.OverrideBlackboxEnv(<EBlackboxEnv><int>override_bb_env) + + def __dealloc__(self): + del self.baseptr + + +cdef public api void cy_call_func(object self, char* method, int lvl, const char* data, size_t length) with gil: + cdef object message = data[:length] + + try: + func = getattr(self, method.decode("utf-8")); + except AttributeError as e: + return + + func(lvl, message.rstrip()) + + +cdef class TvmClient: + """ + Long lived thread-safe object for interacting with TVM. + Each client starts system thread. !!SO DO NOT FORK YOUR PROCESS AFTER CREATING TvmClient!! + In 99% cases TvmClient shoud be created at service startup and live for the whole process lifetime. + If your case in this 1% and you need to RESTART client, you should to use method 'stop()' for old client. + + You can get logs from 'TVM': + log = logging.getLogger('TVM') + """ + cdef TPidCheckedClient* baseptr + + __logger = logging.getLogger('TVM') + __loghandles = { + 0: __logger.error, + 1: __logger.error, + 2: __logger.error, + 3: __logger.error, + 4: __logger.warning, + 5: __logger.info, + 6: __logger.info, + 7: __logger.debug, + } + + def __init__(self, settings): + """ + :param settings: TvmApiClientSettings or TvmToolClientSettings - settings for client + + :raises `NonRetriableException`: Raised in case of settings validation fails. + :raises `RetriableException`: Raised if network unavailable. + """ + pass + + def __cinit__(self, settings): + if isinstance(settings, TvmToolClientSettings): + self.baseptr = CreateTvmToolClient(dereference((<TvmToolClientSettings>settings).baseptr),\ + new IPyLogger(<cpy_ref.PyObject*>self)) + elif isinstance(settings, TvmApiClientSettings): + if (<TvmApiClientSettings>settings).__host.empty(): + self.baseptr = CreateTvmApiClient(dereference((<TvmApiClientSettings>settings).baseptr),\ + new IPyLogger(<cpy_ref.PyObject*>self)) + else: + self.baseptr = new TPidCheckedClient(new TCustomUpdater( \ + dereference((<TvmApiClientSettings>settings).baseptr), \ + new IPyLogger(<cpy_ref.PyObject*>self))) + else: + raise BrokenTvmClientSettings("'settings' must be instance of TvmApiClientSettings or TvmToolClientSettings") + + def stop(self): + """ + First call will delete object. Next calls will be no-op. + """ + # stop() (and delete inside of it) probably will be called from main thread. + # There is TThread::Join() inside which waites worker thread. + # Worker thread can reach state when it is waiting for main thread: it needs to acquire lock in logging, + # but it can be released only by main thread. + # We can't delete TvmClient with one step because of deadlock (PASSP-21494). + # It is C++ function which is not interruptible: + # so we are interrupting C++ function by handes to allow main Python thread to release lock + StartTvmClientStopping(self.baseptr) + while not IsTvmClientStopped(self.baseptr): + time.sleep(0.1) + DestroyTvmClient(self.baseptr) + self.baseptr = NULL + + def __dealloc__(self): + self.stop() + + def __log(self, int lvl, msg): + self.__loghandles[lvl](msg.decode("utf-8")) + + @property + def status(self): + """ + :return: Current status of client - :class:`~TvmClientStatus` + """ + self.__check() + return TvmClientStatus(<int>self.baseptr.GetStatus().GetCode()) + + @staticmethod + def status_to_string(status): + """ + :return: Status of client as string + """ + return TPidCheckedClient.StatusToString(<TClientStatus.ECode><int>status).decode('utf-8') + +# @property +# def last_update_time_of_public_keys(self): +# self.__check() +# return datetime.datetime.fromtimestamp(self.baseptr.GetUpdateTimeOfPublicKeys().Seconds()) + +# @property +# def last_update_time_of_service_tickets(self): +# self.__check() +# return datetime.datetime.fromtimestamp(self.baseptr.GetUpdateTimeOfServiceTickets().Seconds()) + + def get_service_ticket_for(self, alias=None, client_id=None): + """ + Fetching must be enabled in TvmApiClientSettings + + :param alias: string - see docstring for TvmApiClientSettings.__init__ + :param client_id: int - any destination you specified in TvmApiClientSettings + + :raises `BrokenTvmClientSettings`: Raised in case of unconfigured using. + + :returns: string - ServiceTicket + """ + self.__check() + if alias is not None: + return self.baseptr.GetServiceTicketFor(<TString>alias.encode('utf-8')).decode('utf-8') + if client_id is not None: + return GetServiceTicketForId(dereference(self.baseptr), int(client_id)).decode('utf-8') + raise TvmException("One of args is required: 'alias' or 'client_id'") + + def check_service_ticket(self, ticket): + """ + :param ticket: string - ticket body + + :raises `BrokenTvmClientSettings`: Raised in case of unconfigured using. + :raises `TicketParsingException`: Raised in case of invalid ticket. + + :return: Valid ticket structure + """ + self.__check() + return ServiceContext.__check(TCanningKnife.GetS(self.baseptr.CheckServiceTicket(<TString>ticket.encode('utf-8')))) + + def check_user_ticket(self, ticket, overrided_bb_env=None): + """ + :param ticket: string - ticket body + :param overrided_bb_env: enum EBlackboxEnv + + :raises `BrokenTvmClientSettings`: Raised in case of unconfigured using. + :raises `TicketParsingException`: Raised in case of invalid ticket. + + :return: Valid ticket structure + """ + self.__check() + if overrided_bb_env is None: + return UserContext.__check(TCanningKnife.GetU( + self.baseptr.CheckUserTicket(<TString>ticket.encode('utf-8')))) + else: + return UserContext.__check(TCanningKnife.GetU( + self.baseptr.CheckUserTicketWithOveridedEnv(<TString>ticket.encode('utf-8'), <EBlackboxEnv><int>overrided_bb_env))) + + def __check(self): + if NULL == self.baseptr: + raise NonRetriableException("TvmClient is already stopped") + +PyEval_InitThreads() diff --git a/library/python/deprecated/ticket_parser2/ticket_parser2/unittest.py b/library/python/deprecated/ticket_parser2/ticket_parser2/unittest.py new file mode 100644 index 0000000000..45affaa1e7 --- /dev/null +++ b/library/python/deprecated/ticket_parser2/ticket_parser2/unittest.py @@ -0,0 +1,43 @@ +try: + from ticket_parser2_py3.ticket_parser2_pymodule import ( # noqa + create_service_ticket_for_unittest, + create_user_ticket_for_unittest, + ) +except ImportError: + from ticket_parser2.ticket_parser2_pymodule import ( # noqa + create_service_ticket_for_unittest, + create_user_ticket_for_unittest, + ) + + +TVMKNIFE_PUBLIC_KEYS = ( + "1:CpgCCpMCCAEQABqIAjCCAQQCggEAcLEXeH67FQESFUn4_7wnX7wN0PUrBoUsm3QQ4W5vC-qz6sXaEjSwnTV8w1o-z6X9KPL" + "lhzMQvuS38NCNfK4uvJ4Zvfp3YsXJ25-rYtbnrYJHNvHohD-kPCCw_yZpMp21JdWigzQGuV7CtrxUhF-NNrsnUaJrE5-OpEWN" + "t4X6nCItKIYeVcSK6XJUbEWbrNCRbvkSc4ak2ymFeMuHYJVjxh4eQbk7_ZPzodP0WvF6eUYrYeb42imVEOR8ofVLQWE5DVnb1" + "z_TqZm4i1XkS7jMwZuBxBRw8DGdYei0lT_sAf7KST2jC0590NySB3vsBgWEVs1OdUUWA6r-Dvx9dsOQtSCVkQYQAAqZAgqUAg" + "gCEAAaiQIwggEFAoIBAQDhEBM5-6YsPWfogKtbluJoCX1WV2KdzOaQ0-OlRbBzeCzw-eQKu12c8WakHBbeCMd1I1TU64SDkDo" + "rWjXGIa_2xT6N3zzNAE50roTbPCcmeQrps26woTYfYIuqDdoxYKZNr0lvNLLW47vBr7EKqo1S4KSj7aXK_XYeEvUgIgf3nVIc" + "Nrio7VTnFmGGVQCepaL1Hi1gN4yIXjVZ06PBPZ-DxSRu6xOGbFrfKMJeMPs7KOyE-26Q3xOXdTIa1X-zYIucTd_bxUCL4BVbw" + "W2AvbbFsaG7ISmVdGu0XUTmhXs1KrEfUVLRJhE4Dx99hAZXm1_HlYMUeJcMQ_oHOhV94ENFIJaRBhACCpYBCpEBCAMQABqGAT" + "CBgwKBgF9t2YJGAJkRRFq6fWhi3m1TFW1UOE0f6ZrfYhHAkpqGlKlh0QVfeTNPpeJhi75xXzCe6oReRUm-0DbqDNhTShC7uGU" + "v1INYnRBQWH6E-5Fc5XrbDFSuGQw2EYjNfHy_HefHJXxQKAqPvxBDKMKkHgV58WtM6rC8jRi9sdX_ig2NIJeRBhABCpYBCpEB" + "CAQQABqGATCBgwKBgGB4d6eLGUBv-Q6EPLehC4S-yuE2HB-_rJ7WkeYwyp-xIPolPrd-PQme2utHB4ZgpXHIu_OFksDe_0bPg" + "ZniNRSVRbl7W49DgS5Ya3kMfrYB4DnF5Fta5tn1oV6EwxYD4JONpFTenOJALPGTPawxXEfon_peiHOSBuQMu3_Vn-l1IJiRBh" + "ADCpcBCpIBCAUQABqHATCBhAKBgQCTJMKIfmfeZpaI7Q9rnsc29gdWawK7TnpVKRHws1iY7EUlYROeVcMdAwEqVM6f8BVCKLG" + "gzQ7Gar_uuxfUGKwqEQzoppDraw4F75J464-7D5f6_oJQuGIBHZxqbMONtLjBCXRUhQW5szBLmTQ_R3qaJb5vf-h0APZfkYhq" + "1cTttSCZkQYQBAqWAQqRAQgLEAAahgEwgYMCgYBvvGVH_M2H8qxxv94yaDYUTWbRnJ1uiIYc59KIQlfFimMPhSS7x2tqUa2-h" + "I55JiII0Xym6GNkwLhyc1xtWChpVuIdSnbvttbrt4weDMLHqTwNOF6qAsVKGKT1Yh8yf-qb-DSmicgvFc74mBQm_6gAY1iQsf" + "33YX8578ClhKBWHSCVkQYQAAqXAQqSAQgMEAAahwEwgYQCgYEAkuzFcd5TJu7lYWYe2hQLFfUWIIj91BvQQLa_Thln4YtGCO8" + "gG1KJqJm-YlmJOWQG0B7H_5RVhxUxV9KpmFnsDVkzUFKOsCBaYGXc12xPVioawUlAwp5qp3QQtZyx_se97YIoLzuLr46UkLcL" + "nkIrp-Jo46QzYi_QHq45WTm8MQ0glpEGEAIKlwEKkgEIDRAAGocBMIGEAoGBAIUzbxOknXf_rNt17_ir8JlWvrtnCWsQd1MAn" + "l5mgArvavDtKeBYHzi5_Ak7DHlLzuA6YE8W175FxLFKpN2hkz-l-M7ltUSd8N1BvJRhK4t6WffWfC_1wPyoAbeSN2Yb1jygtZ" + "JQ8wGoXHcJQUXiMit3eFNyylwsJFj1gzAR4JCdIJeRBhABCpYBCpEBCA4QABqGATCBgwKBgFMcbEpl9ukVR6AO_R6sMyiU11I" + "8b8MBSUCEC15iKsrVO8v_m47_TRRjWPYtQ9eZ7o1ocNJHaGUU7qqInFqtFaVnIceP6NmCsXhjs3MLrWPS8IRAy4Zf4FKmGOx3" + "N9O2vemjUygZ9vUiSkULdVrecinRaT8JQ5RG4bUMY04XGIwFIJiRBhADCpYBCpEBCA8QABqGATCBgwKBgGpCkW-NR3li8GlRv" + "qpq2YZGSIgm_PTyDI2Zwfw69grsBmPpVFW48Vw7xoMN35zcrojEpialB_uQzlpLYOvsMl634CRIuj-n1QE3-gaZTTTE8mg-AR" + "4mcxnTKThPnRQpbuOlYAnriwiasWiQEMbGjq_HmWioYYxFo9USlklQn4-9IJmRBhAEEpUBCpIBCAYQABqHATCBhAKBgQCoZkF" + "Gm9oLTqjeXZAq6j5S6i7K20V0lNdBBLqfmFBIRuTkYxhs4vUYnWjZrKRAd5bp6_py0csmFmpl_5Yh0b-2pdo_E5PNP7LGRzKy" + "KSiFddyykKKzVOazH8YYldDAfE8Z5HoS9e48an5JsPg0jr-TPu34DnJq3yv2a6dqiKL9zSCakQYSlQEKkgEIEBAAGocBMIGEA" + "oGBALhrihbf3EpjDQS2sCQHazoFgN0nBbE9eesnnFTfzQELXb2gnJU9enmV_aDqaHKjgtLIPpCgn40lHrn5k6mvH5OdedyI6c" + "CzE-N-GFp3nAq0NDJyMe0fhtIRD__CbT0ulcvkeow65ubXWfw6dBC2gR_34rdMe_L_TGRLMWjDULbNIJqRBg" +) |