aboutsummaryrefslogtreecommitdiffstats
path: root/library/python/deprecated/ticket_parser2
diff options
context:
space:
mode:
authorqrort <qrort@yandex-team.com>2022-11-30 23:47:12 +0300
committerqrort <qrort@yandex-team.com>2022-11-30 23:47:12 +0300
commit22f8ae0e3f5d68b92aecccdf96c1d841a0334311 (patch)
treebffa27765faf54126ad44bcafa89fadecb7a73d7 /library/python/deprecated/ticket_parser2
parent332b99e2173f0425444abb759eebcb2fafaa9209 (diff)
downloadydb-22f8ae0e3f5d68b92aecccdf96c1d841a0334311.tar.gz
validate canons without yatest_common
Diffstat (limited to 'library/python/deprecated/ticket_parser2')
-rw-r--r--library/python/deprecated/ticket_parser2/README.md3
-rw-r--r--library/python/deprecated/ticket_parser2/examples/create_with_tvmapi/__init__.py75
-rw-r--r--library/python/deprecated/ticket_parser2/examples/create_with_tvmtool/__init__.py29
-rw-r--r--library/python/deprecated/ticket_parser2/examples/service_using_tvm_client/__init__.py0
-rw-r--r--library/python/deprecated/ticket_parser2/examples/service_using_tvm_client/serv.py39
-rw-r--r--library/python/deprecated/ticket_parser2/mock/ticket_parser2_mock/__init__.py0
-rw-r--r--library/python/deprecated/ticket_parser2/mock/ticket_parser2_mock/api/__init__.py0
-rw-r--r--library/python/deprecated/ticket_parser2/mock/ticket_parser2_mock/api/v1/__init__.py0
-rw-r--r--library/python/deprecated/ticket_parser2/mock/ticket_parser2_mock/api/v1/tvm_client.py147
-rw-r--r--library/python/deprecated/ticket_parser2/so/ticket_parser2_pymodule.exports1
-rw-r--r--library/python/deprecated/ticket_parser2/src/exception.h80
-rw-r--r--library/python/deprecated/ticket_parser2/src/logger.h31
-rw-r--r--library/python/deprecated/ticket_parser2/src/ut/test_client.py710
-rw-r--r--library/python/deprecated/ticket_parser2/src/ut/test_common.py18
-rw-r--r--library/python/deprecated/ticket_parser2/src/ut/test_service.py242
-rw-r--r--library/python/deprecated/ticket_parser2/src/ut/test_user.py218
-rw-r--r--library/python/deprecated/ticket_parser2/src/utils.h131
-rw-r--r--library/python/deprecated/ticket_parser2/ticket_parser2/__init__.py45
-rw-r--r--library/python/deprecated/ticket_parser2/ticket_parser2/api/__init__.py1
-rw-r--r--library/python/deprecated/ticket_parser2/ticket_parser2/api/v1/__init__.py50
-rw-r--r--library/python/deprecated/ticket_parser2/ticket_parser2/api/v1/exceptions.py30
-rw-r--r--library/python/deprecated/ticket_parser2/ticket_parser2/api/v1/unittest.py43
-rw-r--r--library/python/deprecated/ticket_parser2/ticket_parser2/exceptions.py30
-rw-r--r--library/python/deprecated/ticket_parser2/ticket_parser2/low_level.py10
-rw-r--r--library/python/deprecated/ticket_parser2/ticket_parser2/mock.py141
-rw-r--r--library/python/deprecated/ticket_parser2/ticket_parser2/ticket_parser2_pymodule.pyx878
-rw-r--r--library/python/deprecated/ticket_parser2/ticket_parser2/unittest.py43
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"
+)