aboutsummaryrefslogtreecommitdiffstats
path: root/library/recipes
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/recipes
parent332b99e2173f0425444abb759eebcb2fafaa9209 (diff)
downloadydb-22f8ae0e3f5d68b92aecccdf96c1d841a0334311.tar.gz
validate canons without yatest_common
Diffstat (limited to 'library/recipes')
-rw-r--r--library/recipes/common/__init__.py74
-rw-r--r--library/recipes/tirole/README.md16
-rw-r--r--library/recipes/tirole/__main__.py102
-rw-r--r--library/recipes/tirole/data/sign.keys1
-rw-r--r--library/recipes/tirole/recipe.inc8
-rw-r--r--library/recipes/tvmapi/README.md16
-rw-r--r--library/recipes/tvmapi/__main__.py121
-rw-r--r--library/recipes/tvmapi/clients/clients.json302
-rw-r--r--library/recipes/tvmapi/data/abc.json4
-rw-r--r--library/recipes/tvmapi/data/client_secret.secret1
-rw-r--r--library/recipes/tvmapi/data/config.xml107
-rw-r--r--library/recipes/tvmapi/data/secret.key1
-rw-r--r--library/recipes/tvmapi/data/staff.json4
-rw-r--r--library/recipes/tvmapi/data/tvm.sql128
-rw-r--r--library/recipes/tvmapi/data/tvmdb.credentials4
-rw-r--r--library/recipes/tvmapi/recipe.inc12
-rw-r--r--library/recipes/tvmtool/README.md81
-rw-r--r--library/recipes/tvmtool/__main__.py107
-rw-r--r--library/recipes/tvmtool/a.yaml23
-rw-r--r--library/recipes/tvmtool/examples/ut_simple/test.py26
-rw-r--r--library/recipes/tvmtool/examples/ut_with_custom_config/custom.cfg8
-rw-r--r--library/recipes/tvmtool/examples/ut_with_custom_config/test.py23
-rw-r--r--library/recipes/tvmtool/examples/ut_with_roles/custom.cfg10
-rw-r--r--library/recipes/tvmtool/examples/ut_with_roles/roles/some_slug.json19
-rw-r--r--library/recipes/tvmtool/examples/ut_with_roles/test.py26
-rw-r--r--library/recipes/tvmtool/examples/ut_with_tvmapi/test.py49
-rw-r--r--library/recipes/tvmtool/examples/ut_with_tvmapi/tvmtool.conf17
-rw-r--r--library/recipes/tvmtool/examples/ut_with_tvmapi_and_tirole/roles_dir/mapping.yaml5
-rw-r--r--library/recipes/tvmtool/examples/ut_with_tvmapi_and_tirole/roles_dir/some_slug_2.json14
-rw-r--r--library/recipes/tvmtool/examples/ut_with_tvmapi_and_tirole/test.py50
-rw-r--r--library/recipes/tvmtool/examples/ut_with_tvmapi_and_tirole/tvmtool.conf10
-rw-r--r--library/recipes/tvmtool/recipe.inc8
-rw-r--r--library/recipes/tvmtool/recipe_with_default_cfg.inc5
-rw-r--r--library/recipes/tvmtool/tvmtool.default.conf17
34 files changed, 1399 insertions, 0 deletions
diff --git a/library/recipes/common/__init__.py b/library/recipes/common/__init__.py
new file mode 100644
index 0000000000..84308b1327
--- /dev/null
+++ b/library/recipes/common/__init__.py
@@ -0,0 +1,74 @@
+import os.path
+import psutil
+import socket
+import subprocess
+import time
+import yatest.common
+
+
+def find_free_ports(count):
+ sockets = []
+ ports = []
+
+ for _ in range(count):
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.bind(('', 0))
+ ports.append(sock.getsockname()[1])
+ sockets.append(sock)
+
+ for sock in sockets:
+ sock.close()
+ return ports
+
+
+def start_daemon(command, environment, is_alive_check, pid_file_name, timeout=60, daemon_name=None):
+ daemon_name = daemon_name or os.path.basename(command[0])
+ stdout_path = yatest.common.output_path('{}.out.log').format(daemon_name)
+ stderr_path = yatest.common.output_path('{}.err.log').format(daemon_name)
+
+ process = subprocess.Popen(
+ command,
+ stdout=open(stdout_path, 'w'),
+ stderr=open(stderr_path, 'w'),
+ env=environment)
+ with open(pid_file_name, 'w') as fout:
+ fout.write(str(process.pid))
+
+ for attempts in range(timeout):
+ result = process.poll()
+ if result is not None:
+ raise RuntimeError(
+ 'Could not launch "{}" with exit code {}\nStdout: {}\nStderr: {}'
+ .format(daemon_name, result, stdout_path, stderr_path)
+ )
+
+ if is_alive_check():
+ return
+
+ time.sleep(1)
+
+ raise RuntimeError(
+ 'Could not launch "{}" for {} seconds\nStdout: {}\nStderr: {}'
+ .format(daemon_name, timeout, stdout_path, stderr_path)
+ )
+
+
+def pid_exists(pid):
+ try:
+ if psutil.Process(pid).status() == psutil.STATUS_ZOMBIE:
+ return False
+ except psutil.NoSuchProcess:
+ return False
+ return True
+
+
+def stop_daemon(pid, signal=15):
+ pid = int(pid)
+ if not pid_exists(pid):
+ return False
+
+ os.kill(pid, signal)
+ while pid_exists(pid):
+ time.sleep(1)
+
+ return True
diff --git a/library/recipes/tirole/README.md b/library/recipes/tirole/README.md
new file mode 100644
index 0000000000..1cade61912
--- /dev/null
+++ b/library/recipes/tirole/README.md
@@ -0,0 +1,16 @@
+Tirole recipe
+--
+
+Этот рецепт позволяет в тестах поднять демон, который скрывается за `tirole-api.yandex.net`.
+Демон слушает на порте из файла `tirole.port` - только http.
+
+База ролей в tirole - это каталог в Аркадии с файлами:
+ * `<slug>.json` - роли, которые надо отдавать в API
+ * `mapping.yaml` - соответствие между slug и tvmid
+
+В рецепте API принимает service-тикеты с dst==1000001: их можно получать из `tvmapi`/`tvmtool`, запущеного в рецепте.
+
+Примеры:
+1. `ut_simple`
+
+Вопросы можно писать в [PASSPORTDUTY](https://st.yandex-team.ru/createTicket?queue=PASSPORTDUTY&_form=77618)
diff --git a/library/recipes/tirole/__main__.py b/library/recipes/tirole/__main__.py
new file mode 100644
index 0000000000..e61c1517d7
--- /dev/null
+++ b/library/recipes/tirole/__main__.py
@@ -0,0 +1,102 @@
+import argparse
+import datetime
+import json
+import os
+import requests
+import sys
+
+import yatest.common
+from library.python.testing.recipe import declare_recipe
+from library.recipes.common import start_daemon, stop_daemon
+from yatest.common import network
+
+TIROLE_PORT_FILE = "tirole.port"
+TIROLE_PID_FILE = "tirole.pid"
+
+CONFIG_PATH = './tirole.config.json'
+
+
+PORT_MANAGER = network.PortManager()
+
+
+def _gen_config(roles_dir):
+ http_port = PORT_MANAGER.get_tcp_port(80)
+
+ cfg = {
+ "http_common": {
+ "listen_address": "localhost",
+ "port": http_port,
+ },
+ "logger": {
+ "file": yatest.common.output_path("tirole-common.log"),
+ },
+ "service": {
+ "common": {
+ "access_log": yatest.common.output_path("tirole-access.log"),
+ },
+ "tvm": {
+ "self_tvm_id": 1000001,
+ },
+ "key_map": {
+ "keys_file": yatest.common.source_path("library/recipes/tirole/data/sign.keys"),
+ "default_key": "1",
+ },
+ "unittest": {
+ "roles_dir": yatest.common.source_path(roles_dir) + "/",
+ },
+ },
+ }
+
+ with open(CONFIG_PATH, 'wt') as f:
+ json.dump(cfg, f, sort_keys=True, indent=4)
+
+ return http_port
+
+
+def start(argv):
+ _log('Starting Tirole recipe')
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--roles-dir', dest='roles_dir', type=str, required=True)
+ input_args = parser.parse_args(argv)
+
+ http_port = _gen_config(input_args.roles_dir)
+
+ print(http_port, file=sys.stderr)
+ with open(TIROLE_PORT_FILE, "w") as f:
+ f.write(str(http_port))
+
+ # launch
+ args = [
+ yatest.common.build_path() + '/passport/infra/daemons/tirole/cmd/tirole',
+ '-c',
+ CONFIG_PATH,
+ ]
+
+ def check():
+ try:
+ r = requests.get("http://localhost:%d/ping" % http_port)
+ if r.status_code == 200:
+ return True
+ else:
+ _log("ping: %d : %s" % (r.status_code, r.text))
+ except Exception as e:
+ _log("ping: %s" % e)
+ return False
+
+ start_daemon(command=args, environment=os.environ.copy(), is_alive_check=check, pid_file_name=TIROLE_PID_FILE)
+
+
+def stop(argv):
+ with open(TIROLE_PID_FILE) as f:
+ pid = f.read()
+ if not stop_daemon(pid):
+ _log("pid is dead: %s" % pid)
+
+
+def _log(msg):
+ print("%s : tirole-recipe : %s" % (datetime.datetime.now(), msg), file=sys.stdout)
+
+
+if __name__ == "__main__":
+ declare_recipe(start, stop)
diff --git a/library/recipes/tirole/data/sign.keys b/library/recipes/tirole/data/sign.keys
new file mode 100644
index 0000000000..bc1a0be4da
--- /dev/null
+++ b/library/recipes/tirole/data/sign.keys
@@ -0,0 +1 @@
+{"1": "733f9cdba433040287a4235247f8f31a326fee9e0f094d2987aac16d5eb0b883"}
diff --git a/library/recipes/tirole/recipe.inc b/library/recipes/tirole/recipe.inc
new file mode 100644
index 0000000000..50ed13c092
--- /dev/null
+++ b/library/recipes/tirole/recipe.inc
@@ -0,0 +1,8 @@
+DEPENDS(
+ library/recipes/tirole
+ passport/infra/daemons/tirole/cmd
+)
+
+DATA(
+ arcadia/library/recipes/tirole/data
+)
diff --git a/library/recipes/tvmapi/README.md b/library/recipes/tvmapi/README.md
new file mode 100644
index 0000000000..cab650a5f6
--- /dev/null
+++ b/library/recipes/tvmapi/README.md
@@ -0,0 +1,16 @@
+TVM-API recipe
+--
+
+Этот рецепт позволяет в тестах поднять демон, который скрывается за `tvm-api.yandex.net`.
+Демон слушает на порте из файла `tvmapi.port` - только http.
+
+База у этого демона в read-only режиме, список доступных TVM-приложений с секретами лежит [здесь](clients/clients.json).
+
+Публичные ключи этого демона позволяют проверять тикеты, сгенерированные через `tvmknife unittest`.
+
+Примеры:
+1. `ut_simple` - поднимается tvm-api
+
+Примеры комбинирования с tvmtool можно найти в `library/recipes/tvmtool`
+
+Вопросы можно писать в [PASSPORTDUTY](https://st.yandex-team.ru/createTicket?queue=PASSPORTDUTY&_form=77618)
diff --git a/library/recipes/tvmapi/__main__.py b/library/recipes/tvmapi/__main__.py
new file mode 100644
index 0000000000..93544eaeb6
--- /dev/null
+++ b/library/recipes/tvmapi/__main__.py
@@ -0,0 +1,121 @@
+import datetime
+import os
+import requests
+import subprocess
+import sys
+
+import yatest.common
+from library.python.testing.recipe import declare_recipe
+from library.recipes.common import start_daemon, stop_daemon
+from yatest.common import network
+
+TVMAPI_PORT_FILE = "tvmapi.port"
+TVMAPI_PID_FILE = "tvmapi.pid"
+
+TVMCERT_PORT_FILE = "tvmcert.port"
+
+CONFIG_PATH = './tvm-api.config.xml'
+
+
+def test_data_path():
+ return yatest.common.source_path() + '/library/recipes/tvmapi/data/'
+
+
+PORT_MANAGER = network.PortManager()
+
+
+def _gen_config(cfg_template):
+ http_port = PORT_MANAGER.get_tcp_port(80)
+ tvmcert_port = PORT_MANAGER.get_tcp_port(9001)
+
+ f = open(cfg_template)
+ cfg = f.read()
+
+ cfg = cfg.replace('{port}', str(http_port))
+
+ cfg = cfg.replace('{secret.key}', test_data_path() + 'secret.key')
+ cfg = cfg.replace('{test_secret.key}', test_data_path() + 'test_secret.key')
+
+ cfg = cfg.replace('{tvmdb_credentials}', test_data_path() + 'tvmdb.credentials')
+ cfg = cfg.replace('{client_secret}', test_data_path() + 'client_secret.secret')
+ cfg = cfg.replace('{tvm_cache}', test_data_path() + "tvm_cache")
+
+ cfg = cfg.replace('{abc.json}', test_data_path() + 'abc.json')
+ cfg = cfg.replace('{staff.json}', test_data_path() + 'staff.json')
+
+ cfg = cfg.replace('{tvmcert_port}', str(tvmcert_port))
+
+ print(cfg, file=sys.stderr)
+
+ f = open(CONFIG_PATH, 'wt')
+ f.write(cfg)
+
+ return http_port, tvmcert_port
+
+
+def _prepare_db(sql, db):
+ SQLITE_BIN = yatest.common.build_path() + '/contrib/tools/sqlite3/sqlite3'
+ if os.path.isfile(db):
+ os.remove(db)
+
+ input_sql = open(sql)
+ p = subprocess.run([SQLITE_BIN, db], stdin=input_sql)
+ assert 0 == p.returncode
+
+
+def start(argv):
+ _log('Starting TVM recipe')
+
+ def pop_arg(def_val):
+ if len(argv) > 0:
+ return yatest.common.source_path(argv.pop(0))
+ return test_data_path() + def_val
+
+ dbfile = pop_arg('tvm.sql')
+ cfg_template = pop_arg('config.xml')
+
+ _prepare_db(dbfile, './tvm.db')
+
+ http_port, tvmcert_port = _gen_config(cfg_template)
+
+ print(http_port, tvmcert_port, file=sys.stderr)
+ with open(TVMAPI_PORT_FILE, "w") as f:
+ f.write(str(http_port))
+
+ with open(TVMCERT_PORT_FILE, "w") as f:
+ f.write(str(tvmcert_port))
+
+ # launch tvm
+ args = [
+ yatest.common.build_path() + '/passport/infra/daemons/tvmapi/daemon/tvm',
+ '-c',
+ CONFIG_PATH,
+ ]
+
+ def check():
+ try:
+ r = requests.get("http://localhost:%d/nagios" % http_port)
+ if r.status_code == 200:
+ return True
+ else:
+ _log("ping: %d : %s" % (r.status_code, r.text))
+ except Exception as e:
+ _log("ping: %s" % e)
+ return False
+
+ start_daemon(command=args, environment=os.environ.copy(), is_alive_check=check, pid_file_name=TVMAPI_PID_FILE)
+
+
+def stop(argv):
+ with open(TVMAPI_PID_FILE) as f:
+ pid = f.read()
+ if not stop_daemon(pid):
+ _log("pid is dead: %s" % pid)
+
+
+def _log(msg):
+ print("%s : tvmapi-recipe : %s" % (datetime.datetime.now(), msg), file=sys.stdout)
+
+
+if __name__ == "__main__":
+ declare_recipe(start, stop)
diff --git a/library/recipes/tvmapi/clients/clients.json b/library/recipes/tvmapi/clients/clients.json
new file mode 100644
index 0000000000..bb7c9686f5
--- /dev/null
+++ b/library/recipes/tvmapi/clients/clients.json
@@ -0,0 +1,302 @@
+{
+ "1000501": {
+ "secret": "bAicxJVa5uVY7MjDlapthw"
+ },
+ "1000502": {
+ "secret": "e5kL0vM3nP-nPf-388Hi6Q"
+ },
+ "1000503": {
+ "secret": "S3TyTYVqjlbsflVEwxj33w"
+ },
+ "1000504": {
+ "secret": "CJua5YZXEPuVLgJDquPOTA"
+ },
+ "1000505": {
+ "secret": "z5oaXOjgB5nV5gycBpzZ-A"
+ },
+ "1000506": {
+ "secret": "VAMgcBS0wRB5fu-3jBoNUA"
+ },
+ "1000507": {
+ "secret": "4bT0rnjSnM0CBrskSLVViA"
+ },
+ "1000508": {
+ "secret": "MIMTd8qQQ3ALLXD6Irv_fA"
+ },
+ "1000509": {
+ "secret": "UAsWdsDA93sNfI8LfuPE5w"
+ },
+ "1000510": {
+ "secret": "LUTTSCreg1f976_B_EHKzg"
+ },
+ "1000511": {
+ "secret": "Qp7JAt_KUJ0PAFYi1Z96Cg"
+ },
+ "1000512": {
+ "secret": "FM1XM4Ek2QNyz-hpzA1v_g"
+ },
+ "1000513": {
+ "secret": "v7uPV5HZxYMxlH9D2fHKMw"
+ },
+ "1000514": {
+ "secret": "shkEKUUBGJ8t-GM4GNjKPg"
+ },
+ "1000515": {
+ "secret": "z8Rj_ogbBldm8XBtqIqB4w"
+ },
+ "1000516": {
+ "secret": "3B17sAZVKFP6MUWVzDPIzw"
+ },
+ "1000517": {
+ "secret": "Veli9VD280mLcIv0UtPbWw"
+ },
+ "1000518": {
+ "secret": "qbdUNAfMk7hX0M9xJtHEsA"
+ },
+ "1000519": {
+ "secret": "Uz-ISKFvVoVYiy9q-PC_9Q"
+ },
+ "1000520": {
+ "secret": "UN5tvVicOZaHYKFcII1q7g"
+ },
+ "1000521": {
+ "secret": "P5hRcHEkmK5zbZcEqAvlKA"
+ },
+ "1000522": {
+ "secret": "erqXUL7bRxOCJB5fEorfiw"
+ },
+ "1000523": {
+ "secret": "zFCVMjkmn0d2kt47unq4Uw"
+ },
+ "1000524": {
+ "secret": "J7cUdsWKVVoeqvbCjOSRhQ"
+ },
+ "1000525": {
+ "secret": "vcIV1ae41FnAF4OcOJANfQ"
+ },
+ "1000526": {
+ "secret": "6iecbb_OxUNcsDqD6dwWdw"
+ },
+ "1000527": {
+ "secret": "3nGLXI-LqzFICq_FVyg_dQ"
+ },
+ "1000528": {
+ "secret": "_98qV1ROSO4-rN6pdt_mxA"
+ },
+ "1000529": {
+ "secret": "gk8O8U6il5Fet6txZV8Wkw"
+ },
+ "1000530": {
+ "secret": "jhkJGPcsruRy8rrvjBqHCQ"
+ },
+ "1000531": {
+ "secret": "Jx_9QZcbS6pgi8tqM4FyeQ"
+ },
+ "1000532": {
+ "secret": "Pt_gGMVoe-LpjAGGUL2L_Q"
+ },
+ "1000533": {
+ "secret": "XCoskT_D_q-udy5misBRKg"
+ },
+ "1000534": {
+ "secret": "HRJ5deobpngW2_D6cs0mXQ"
+ },
+ "1000535": {
+ "secret": "bx2LxRdx8sR_qOFKJEmGqQ"
+ },
+ "1000536": {
+ "secret": "u8OGPAQAsA6TdEngaksR5g"
+ },
+ "1000537": {
+ "secret": "PpnbWrIJDEuBkoSJCoDr8g"
+ },
+ "1000538": {
+ "secret": "jZoAveXpNuJrgH-6RYbP2g"
+ },
+ "1000539": {
+ "secret": "7Jr4Fs82YwpPZ65Nq0fo7w"
+ },
+ "1000540": {
+ "secret": "64n_JH6faRdgTon7potVyg"
+ },
+ "1000541": {
+ "secret": "SxwDfkJySfnLPOvQBJlIaQ"
+ },
+ "1000542": {
+ "secret": "A0wk3RnDWU7e6GGCbuSqtw"
+ },
+ "1000543": {
+ "secret": "f2jmQiEjijWo8xivmuLQ0A"
+ },
+ "1000544": {
+ "secret": "onhYk5AkKuTEb-QDwyuAng"
+ },
+ "1000545": {
+ "secret": "bQxn_3sZvgPazJFMNUuFtw"
+ },
+ "1000546": {
+ "secret": "kzw-gG6HCYqd8FPNHwdFcw"
+ },
+ "1000547": {
+ "secret": "XHHuPPwLsrzE4I6RkPVMAg"
+ },
+ "1000548": {
+ "secret": "UsBWJoLx-nWlziCVwB3ffA"
+ },
+ "1000549": {
+ "secret": "EIZZooj2P6UO53YOdWyVQw"
+ },
+ "1000550": {
+ "secret": "xbopwHPpJ9R-bTDQGeRZNQ"
+ },
+ "1000551": {
+ "secret": "BrYem08Mz3Tt9RrM1wfk-w"
+ },
+ "1000552": {
+ "secret": "NlNnf6wL8Y8SjEg-IorTAQ"
+ },
+ "1000553": {
+ "secret": "EvZ6FrZkWGaBpaLrssWBcA"
+ },
+ "1000554": {
+ "secret": "liVByAp3FXOb4xGcV_U-hg"
+ },
+ "1000555": {
+ "secret": "fEof4p9_LWGwUSp2-HyAdw"
+ },
+ "1000556": {
+ "secret": "B4KRHvr6Z2HS8St4JNGZFg"
+ },
+ "1000557": {
+ "secret": "A90VljsKm1lpDge0OBGmTw"
+ },
+ "1000558": {
+ "secret": "qnuJcyD9p5TdHd6GoXDmxQ"
+ },
+ "1000559": {
+ "secret": "r1HDEiHbIWwR8EwVvAmodw"
+ },
+ "1000560": {
+ "secret": "jSbOzmOKPuFtPoLcSfETog"
+ },
+ "1000561": {
+ "secret": "QIN_pHBHI-2JE5w0mrnh3Q"
+ },
+ "1000562": {
+ "secret": "4aWu0E97B1yxoLEH7Cwh_g"
+ },
+ "1000563": {
+ "secret": "rgqM-66GNODKGrCKH5IXPA"
+ },
+ "1000564": {
+ "secret": "J8-Utmooq3nMQPAWBt9nDg"
+ },
+ "1000565": {
+ "secret": "P2K-8EjVdTMd6PZWSvMdmA"
+ },
+ "1000566": {
+ "secret": "rNhgkxjydpxaitLDZT8anQ"
+ },
+ "1000567": {
+ "secret": "BQ-RK_41r8FCtjWaA08vWg"
+ },
+ "1000568": {
+ "secret": "PcnbfQ5whheKwP_XhJ7tNg"
+ },
+ "1000569": {
+ "secret": "HqFWUa01Wq09p5VvgREyeA"
+ },
+ "1000570": {
+ "secret": "th6F_p-EqoMKCdy-Huf7Zw"
+ },
+ "1000571": {
+ "secret": "nji7fu5bGBdGNG6Yc1uvbg"
+ },
+ "1000572": {
+ "secret": "hYsochsur9VNiOjGaE0UYQ"
+ },
+ "1000573": {
+ "secret": "ZIhUGzPK8qsTI6SI7DsRdQ"
+ },
+ "1000574": {
+ "secret": "h3Fi3rWXKSzAgoG3cnuj-g"
+ },
+ "1000575": {
+ "secret": "lid7tysEVHMmWp158FsbCQ"
+ },
+ "1000576": {
+ "secret": "JuW7Y0IwyhXZAKdSQ0Ub9g"
+ },
+ "1000577": {
+ "secret": "QvPpqp7fLjLME2GUyCdcwQ"
+ },
+ "1000578": {
+ "secret": "DmLAHLp6nHmaBeSbNEPflQ"
+ },
+ "1000579": {
+ "secret": "xU7G-496l-1cs0kda_tY3g"
+ },
+ "1000580": {
+ "secret": "DyW0jyW4N2XIyluzICxOuA"
+ },
+ "1000581": {
+ "secret": "jmAkUgWa1HIEvb0Wty1znw"
+ },
+ "1000582": {
+ "secret": "9d1mWWTZj8gh72GANWr9Hg"
+ },
+ "1000583": {
+ "secret": "WHC11W2RMpGZBDSNbGmjLw"
+ },
+ "1000584": {
+ "secret": "E5FLiFaAo8vF-d0iGeiOQw"
+ },
+ "1000585": {
+ "secret": "PlO6AfAKNvGWO3hB3Brq0A"
+ },
+ "1000586": {
+ "secret": "TmpKdeV-_ZjJrdnUK1uLdw"
+ },
+ "1000587": {
+ "secret": "H4uSYOv-yfAAll2wn0UjAA"
+ },
+ "1000588": {
+ "secret": "XdVwnji2sutxZN_TmiEHjQ"
+ },
+ "1000589": {
+ "secret": "giDih1G7y3hMlKN-1WHs9A"
+ },
+ "1000590": {
+ "secret": "O4fYUDRWu0YudtWLkk3vmg"
+ },
+ "1000591": {
+ "secret": "scYvtH5Wk7zPjue1fj-TsQ"
+ },
+ "1000592": {
+ "secret": "rw7dQX1SZvdf_uZ954u-pg"
+ },
+ "1000593": {
+ "secret": "5oRwpw-GXoGk2qAT_6LfbQ"
+ },
+ "1000594": {
+ "secret": "bGVzBZdt8aIJfzjeO46WWw"
+ },
+ "1000595": {
+ "secret": "stH1g0OLh5qOduhoh1CEYQ"
+ },
+ "1000596": {
+ "secret": "N2ViD5vCYRdrPN1Q-iT9Mw"
+ },
+ "1000597": {
+ "secret": "lJluRpLdw90FWzhJtAraHQ"
+ },
+ "1000598": {
+ "secret": "mCD9wUI2JoDisHmLwIWIJw"
+ },
+ "1000599": {
+ "secret": "VAH7Kxuxyldq8lT4ecWS9A"
+ },
+ "1000600": {
+ "secret": "WiLXMmbqhyOqxicxAb76ow"
+ }
+} \ No newline at end of file
diff --git a/library/recipes/tvmapi/data/abc.json b/library/recipes/tvmapi/data/abc.json
new file mode 100644
index 0000000000..27725868b7
--- /dev/null
+++ b/library/recipes/tvmapi/data/abc.json
@@ -0,0 +1,4 @@
+[{"results":[
+{"id":44793,"person":{"id":16360,"login":"cerevra","first_name":{"ru":"Игорь","en":"Igor"},"last_name":{"ru":"Клеванец","en":"Klevanets"},"uid":"1120000000026887","name":{"ru":"Игорь Клеванец","en":"Igor Klevanets"}},"service":{"id":14,"slug":"passp","name":{"ru":"Паспорт","en":"Passport"},"parent":848},"role":{"id":631,"name":{"ru":"TVM ssh пользователь","en":"TVM ssh user"},"service":null,"scope":{"slug":"tvm_management","name":{"ru":"Управление TVM","en":"TVM management"}},"code":"tvm_ssh_user"},"created_at":"2017-12-11T20:26:03.999074Z","modified_at":"2018-05-04T10:05:42.653792Z","state":"approved"},
+{"id":44794,"person":{"id":16361,"login":"robot-passport-test","first_name":{"ru":"Robot","en":"Robot"},"last_name":{"ru":"Test","en":"Test"},"uid":"1120000000021014","name":{"ru":"Robot Test","en":"Robot Test"}},"service":{"id":2280,"slug":"passporttestservice","name":{"ru":"Паспорт","en":"Passport"},"parent":848},"role":{"id":631,"name":{"ru":"TVM ssh пользователь","en":"TVM ssh user"},"service":null,"scope":{"slug":"tvm_management","name":{"ru":"Управление TVM","en":"TVM management"}},"code":"tvm_ssh_user"},"created_at":"2017-12-11T20:26:03.999074Z","modified_at":"2018-05-04T10:05:42.653792Z","state":"approved"}
+]}]
diff --git a/library/recipes/tvmapi/data/client_secret.secret b/library/recipes/tvmapi/data/client_secret.secret
new file mode 100644
index 0000000000..d07b60a003
--- /dev/null
+++ b/library/recipes/tvmapi/data/client_secret.secret
@@ -0,0 +1 @@
+unused_value
diff --git a/library/recipes/tvmapi/data/config.xml b/library/recipes/tvmapi/data/config.xml
new file mode 100644
index 0000000000..d938087b05
--- /dev/null
+++ b/library/recipes/tvmapi/data/config.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0"?>
+<config xmlns:xi="http://www.w3.org/2003/XInclude">
+ <http_daemon>
+ <listen_address>localhost</listen_address>
+ <port>{port}</port>
+ <max_connections>4096</max_connections>
+ <max_queue_size>4096</max_queue_size>
+ </http_daemon>
+ <components>
+ <component name="tvm">
+ <force_down_file>./tvm.down</force_down_file>
+ <checksecret_client_id>39</checksecret_client_id>
+ <verifyssh_client_id>27</verifyssh_client_id>
+ <keys_acceptable_age>34560000000000</keys_acceptable_age>
+ <logger_common>
+ <level>DEBUG</level>
+ <print-level>yes</print-level>
+ <time-format>_DEFAULT_</time-format>
+ <file>./testing_out_stuff/tvm-error.log</file>
+ </logger_common>
+ <logger_access>
+ <level>INFO</level>
+ <file>./testing_out_stuff/tvm-access.log</file>
+ <time-format>%Y-%m-%d %T</time-format>
+ </logger_access>
+ <log_dbpool>./testing_out_stuff/tvm-dbpool.log</log_dbpool>
+ <log_notify>./testing_out_stuff/tvm-notify.log</log_notify>
+ <tvm_db>
+ <poolsize>1</poolsize>
+ <get_timeout>500</get_timeout>
+ <connect_timeout>500</connect_timeout>
+ <query_timeout>5000</query_timeout>
+ <fail_threshold>1500</fail_threshold>
+ <db_driver>sqlite</db_driver>
+ <db_host>.</db_host>
+ <db_port>3306</db_port>
+ <db_name>./tvm.db</db_name>
+ <db_credentials>{tvmdb_credentials}</db_credentials>
+ </tvm_db>
+
+ <tvm_client>
+ <disk_cache>{tvm_cache}</disk_cache>
+ <tvm>172</tvm>
+ <tvm_host>localhost</tvm_host>
+ <tvm_port>{port}</tvm_port>
+ <client_secret_file>{client_secret}</client_secret_file>
+ </tvm_client>
+
+ <staff>
+ <cache_path>{staff.json}</cache_path>
+ <tvm>2001974</tvm>
+ <db_host>.</db_host>
+ <db_port>80</db_port>
+ <connect_timeout>1000</connect_timeout>
+ <query_timeout>1000</query_timeout>
+ </staff>
+ <staff_processor>
+ <enabled>1</enabled>
+ <refresh_period>900</refresh_period>
+ <retries_per_request>3</retries_per_request>
+ <limit_per_request>1000</limit_per_request>
+ </staff_processor>
+ <abc>
+ <enabled>1</enabled>
+ <tvm>2012190</tvm>
+ <cache_path>{abc.json}</cache_path>
+ <refresh_period>900</refresh_period>
+ <retries_per_request>3</retries_per_request>
+ <limit_per_request>1000</limit_per_request>
+ <tvm_manager_role_id>631</tvm_manager_role_id>
+ <db_host>.</db_host>
+ <db_port>443</db_port>
+ <connect_timeout>1000</connect_timeout>
+ <query_timeout>1000</query_timeout>
+ </abc>
+ <cache>
+ <switching_threads>1</switching_threads>
+ <bucket_count>2048</bucket_count>
+ <bucket_size>128</bucket_size>
+ <ttl>75</ttl>
+ </cache>
+ <timestamp_allowed_diff>60</timestamp_allowed_diff>
+ <db_fetcher>
+ <refresh_period>600</refresh_period>
+ <key_file>{secret.key}</key_file>
+ <retries_per_request>3</retries_per_request>
+ <disk_cache>./db.cache</disk_cache>
+ <prefered_private_key_idx>14</prefered_private_key_idx>
+ <min_key_count>1</min_key_count>
+ </db_fetcher>
+ <passport_ids>
+ <bb_prod>162</bb_prod>
+ <bb_prod_yateam>164</bb_prod_yateam>
+ <bb_test>166</bb_test>
+ <bb_test_yateam>168</bb_test_yateam>
+ <bb_stress>170</bb_stress>
+ <bb_mimino>188</bb_mimino>
+ <tvm>172</tvm>
+ </passport_ids>
+ <pregeneration>
+ <period>60</period>
+ <key_ttl>60</key_ttl>
+ <raw_list_file>./raw_list</raw_list_file>
+ </pregeneration>
+ </component>
+ </components>
+</config>
diff --git a/library/recipes/tvmapi/data/secret.key b/library/recipes/tvmapi/data/secret.key
new file mode 100644
index 0000000000..d959e077c9
--- /dev/null
+++ b/library/recipes/tvmapi/data/secret.key
@@ -0,0 +1 @@
+BtniSXCXhroPtOgXA61i5ZxSeX/solWR
diff --git a/library/recipes/tvmapi/data/staff.json b/library/recipes/tvmapi/data/staff.json
new file mode 100644
index 0000000000..ce16637583
--- /dev/null
+++ b/library/recipes/tvmapi/data/staff.json
@@ -0,0 +1,4 @@
+[{"links": {}, "page": 1, "limit": 1000, "result": [
+{"keys": [{"key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDiaMj8sW6KLfOGMbnxZ9RX5LI6+yXWNsHd+DuJKAdGPT526HyfUKoFYV4a/SWTXqq0sPOGZvgphFUZ0VhteZ2dOKNPPrDYumtB/DfBMbT0Q32vCAfKc6ggPkGOdtNzZRZg92SfAzMLvlDguBfqgN+z/Jraa7QpqzpaYd2aoG7GWAlT+ViK3VrbeL5R9Jzts5qP92baq+gZ1MBtmjCKXON/tG9NfJXPEImUduHE4e0uaLF0ZWQXPr6iLR4WC1OR+QyYFnhVmmFAiG1Z5T8o6WGb210gE7oaDhUeZAD3CZseT6vyZSyvBpeREI89kBOV44KlO1ExhIBFblWk07Jlvl9j cerevra@yandex-team.ru", "fingerprint": "ef:bd:51:d4:7f:6e:be:40:f8:8f:9c:36:03:ae:3a:58"}], "login": "cerevra", "uid": "1120000000026887", "id":1},
+{"keys": [{"key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDnEfnmPTd+PgE1PoF9X5iXeInqM3ygruOGwAaWk/n9uTbK1GhrslbzUEQOsbq4k6urmeYu8iTzfE/NR+pScubrEV/tvOsUp9ysTzQQVFsolcoUWf0PV4bMTmhRqYm782yE7o0dZ6b3aFDkRQgRchcq2uSIepCZ3sIVKKfhSiUBia7faPwf5szLga/xXs0sTDzR1ZcbSxQdn/h0ZORiu0nreLZp2hIak9U+bCfgzXmoeWM3QieWgkK+m6IJslek0gqo6wXmwssg26Pv1zJVrul/qL36KaGnBqC/2kppOUbfHQHO4cqR1QWP2OYlwx2EQQlinAAmSkyiz6Wu9TybaHJT tester@yandex-team.ru", "fingerprint": "8b:ca:b6:37:49:0f:53:2a:4d:3a:7a:39:30:12:26:05"}], "login": "robot-passport-test", "uid": "1120000000021014", "id":2}
+]}]
diff --git a/library/recipes/tvmapi/data/tvm.sql b/library/recipes/tvmapi/data/tvm.sql
new file mode 100644
index 0000000000..d5b88c8e98
--- /dev/null
+++ b/library/recipes/tvmapi/data/tvm.sql
@@ -0,0 +1,128 @@
+CREATE TABLE tvm_client_attributes (id int(11), type smallint(6), value varbinary(65523), PRIMARY KEY (id, type));
+CREATE TABLE tvm_secret_key_attributes (id int(11), type smallint(6), value varbinary(65523), PRIMARY KEY (id, type));
+
+INSERT INTO tvm_client_attributes(id, type, value) VALUES
+ (162, 6, '|11|'),
+ (164, 6, '|12|'),
+ (166, 6, '|13|'),
+ (168, 6, '|14|'),
+ (170, 6, '|15|'),
+ (172, 6, '|16|'),
+ (188, 6, '|522|'),
+ (1000001, 1, 'this is tvmid for tirole'),
+ (1000501, 5, '2:laWH0udZPd81EIZQ:w7aKyqEeqyc71Nqmg5xljYuy0azHu4qVzTHNnYNm:jWYDv6qx1cFusMinouxi7A'),
+ (1000502, 5, '2:E0isTVuM9IPMaqeh:zjzNLf_JlhzbvjjaXcMx3bsrWvxIudWi8Nl2Omvv:EiuxbzkUvJmxTee7XvpJGQ'),
+ (1000503, 5, '2:daHjG5dIqa0CEVbK:f26HIFO_Z0x0zM90yyUw-QijvnejXnWsSszuxlDx:X6H4hgc4dF9iWdz28FDYgA'),
+ (1000504, 5, '2:KG4538iTP3DfUGoT:ISaPcTE1a0bgLquoJ60LwD7W76VfKmAYbR0SYo75:ctwxUO1EiQSd_91ya7JGSQ'),
+ (1000505, 5, '2:geNDu3vFC5MOrKBR:Yrt5xx1ienXP4hQuCWQOV1GSq2ywUStcr-9q1H2b:Q-ynKWCuTW8EqbW0XbOKDA'),
+ (1000506, 5, '2:JMGQIOfpUEbUmWmV:Wqkd7iAchbw95vncNvRZMXhePB0tNcPxuLlEMIW-:ptC39VRBbDCkB6X-PKUPKQ'),
+ (1000507, 5, '2:V0DlGBiqRBheMQn2:svLTsP7B2l6HhHkjxTrknhbKQyJ2orBK4kcw7i_H:I3MPBdluZqWNU1deFnia-g'),
+ (1000508, 5, '2:ITYgZWQgkf9YPmlm:820OXSHj9Qi9QxGrDxmohZ0aLEY0-1fAJwG9cPA9:20AFBj9j0FG_eymUJ2ZZ_A'),
+ (1000509, 5, '2:7AYdZ7tu77hRcdGv:NNZTGGmzo5WLrUfSvH5G0NAEmgUBpS9s1p-7ZPjS:AZ1g3rFPyJ9r-wT65urhIQ'),
+ (1000510, 5, '2:XTgBklls03cWC7gO:sonF9bE4IPj1xH3Z74gpL4Gb8U5K2Z2w3U1obSs7:Y4h-REnInnkVmZt1Y9DzLg'),
+ (1000511, 5, '2:baMBAxbtMuE5elvF:WsR_jX6R-PKiJ-bpmrCM39Z0ioDbDv10Vz6TISRA:HmM02sHq_wR0NkbL0dDRKg'),
+ (1000512, 5, '2:u8lLL0JzC_GpRWt9:IvKNqfV8hplbVDJGQ_SbxIOTSJ5_5lWYMoKKlxJO:WDexVfKF4TKV2MhAd00-oA'),
+ (1000513, 5, '2:VhvNVO84E01lJWqB:eC-V7vhICPtCwT8FuR_o0Zq0SnLnTtXxpHXxDoMs:wPyeemLE3p_WvzK2Nkq7jg'),
+ (1000514, 5, '2:b4cVAihF0mVJEapw:CXw0cVSrOI3h_YrybYlhPWK6Y6MNjrHYwyUZrT2F:EJQ1qgNFdiPXgkBM5BfGaA'),
+ (1000515, 5, '2:G9YiYqYM6p_gRaFl:g9XEz17LnPJlA55RxLEQu3wKRgLhCDvq-ZCPlW3X:AoUQzlIiIIcR_PmpMjM8PA'),
+ (1000516, 5, '2:uHXi4fULgyFAVvfS:lF5VTes1wNstvZDkiWjCtBVI-ubZ_zvVR-lS6xyH:CfF2bZwW8o_1lB9RNxDrYw'),
+ (1000517, 5, '2:JELmdJ9aIJmIA9_j:qMl6TNhrHdFDUJOLn-4AxmBGy5xqrPApcwnaihIG:qYsYAXx6fPgyBxVkYykEig'),
+ (1000518, 5, '2:iOO4Gj3-E9ypSjdl:0nRDxDccoFFt_kTdRgo96q1lMYQr0LIeptFemu3a:AA14v5ixobCuCkQ-bPcZiA'),
+ (1000519, 5, '2:sdhZV8riyK8S_BQR:0RkLd9QSo9t7bFxkYqRzxRJJw-vY5J-x-P32i_Rq:YLIajFH70ZwDu4vDr9whCg'),
+ (1000520, 5, '2:djFYLoQDt0-L9T3l:p2STOUIZ2hgAnT05Llt5CZQSQkG-ocpjA83_Nnin:d99Y9k9IiXlrOMxmU8TyIA'),
+ (1000521, 5, '2:kek-1jXU2QGuB1jk:r-oOna--NrJ7wNTWZmV66mcG7BRef9BrCMhrqeV6:2-cWynuDw-jKlgG8VMTCJA'),
+ (1000522, 5, '2:u73pk7AhnBIYp6Vf:DPdQjFXyfiXlOqgYUSEBeBSvBq--B9wZBBEaGboP:y4akpriHob-1YZQW7CyT2g'),
+ (1000523, 5, '2:EJk-Z7ai-aghm4wn:i4-k8f3h92ypTK2hV_3n3rlRDVTyJWbsO0ZvlY5E:84cZN1pZs9jyh6MVjaZYUA'),
+ (1000524, 5, '2:gpjIdv65_MIkJSR_:S8-cz5-rKyPu_YpuWaCm6Cvd5216UJ462loKmtnh:7aXCAXudf0FoV9gsyrwqGQ'),
+ (1000525, 5, '2:RRyZY74THKpMF18T:rqmSy8yaFcshxd2m06JN6L70YzpkCtr7KWcQz-Ed:jYgJct7msl9mstsyejdBjg'),
+ (1000526, 5, '2:Wkdmx_Dp3zvUkWQO:Ai8XXqJbqCfRFw4vWV9yAvG1Xrv3LC_NZPYae6yG:uyXu5oK7E89FQrOJndurOw'),
+ (1000527, 5, '2:hW7izuInoBGuv8ax:SbfN8UaxvYT-GKaV9V2piFapYhRyygGUcwAfQHyk:ElccQQQFDTw8y1sh2O9MFw'),
+ (1000528, 5, '2:2j_ZvR4EwNucCxUk:9ThJ83pSzWx0OTlCvWUEVjx1eHG9O00oKhxuQxxj:NvUc2J1Ea0gs1aoqynIG2A'),
+ (1000529, 5, '2:cNn0u4R5kLuqPT84:M8Sw0Q44RVoFd0bn62mdCGexbfdPGLlTqvNkELog:KAuct7XjaWm-2LrVTYR0iA'),
+ (1000530, 5, '2:aMUqoKgJbrJoC0uu:kYQMpDqU12AwHKWFLEpkFjCy0tD-IQozt2ZxmYdt:IdCu84j8FDUNsyTnXSE7zw'),
+ (1000531, 5, '2:62jDZlhC79P-xPCZ:I4Oi8AX-aLE40LLb9x3oxw2ACfTlxkFQMSWXdS-N:X6s2glYGk4c1ONr-ebGWbQ'),
+ (1000532, 5, '2:vYAPMz7UDTVdU_ce:gKqb5Pa8TKI7U9nOgq_zd-oB02kBwd6kYB6eaOzN:Azk72M93oAfQ33hT-z9m3Q'),
+ (1000533, 5, '2:_aPMXhhguCLIuJU9:0r4YCPbqK_TJOiYBhZE9iC2SVxXkV9WQviN19-wc:6Sj5ejmrG4PrTITbF92qEQ'),
+ (1000534, 5, '2:2XpO3eoRJbcbmM4b:PoK87HPw2l907Ga4CUiQkUwyQT1zKahEHg04aQFE:ngco61-31xFxQFUYtRpfbw'),
+ (1000535, 5, '2:qqgnVolNSc50UBWp:hfK57xl7fWSHR9Ljw_ez01wPkdMSyCEKbmG8o5gW:SL7mvMEWy2oxxjxcJQnE6A'),
+ (1000536, 5, '2:e6r_D7kNcWiKcs2z:gMnmNNN0mj7uiFvrhufGBvHJYlc5fdusRZwd3jJm:V4TlrLvLt6bkrDuEEMXq8g'),
+ (1000537, 5, '2:ujR8rBs5jR_5MNn4:nUm6auDNJF6cRSN56FQAq4MrIMdq-MOvB5Xa34E-:emZode7gqJCsRwTcCI2trg'),
+ (1000538, 5, '2:1fU_nMnSiQh8IHpv:_7aZi-RpgHcV3-EXRqNKOH21e45npMqrRRQ_bc_K:DlwTjK1cRsnL2y-hT7XGHQ'),
+ (1000539, 5, '2:tJBRNwTVw21ib61g:F1oGEaVUIRO0NPi-QooujvKbQnBwF4WScgniONvJ:AR8Oa9DOZwYO4YBO27nUgw'),
+ (1000540, 5, '2:z9T3xQ-0SoZLR6iC:W1SHm4hWXh78_lU0l858JBF4J1GwNQtqOPrp4zAb:nT5eei25qpqz8Uy9ji1sLQ'),
+ (1000541, 5, '2:KKwDmhKe_NOqIy51:uhn2BF3urlKoSQ4Vi7aZJtCK_sub3AHc3SiSwzSM:W17foTbZ-J_dpZ4gijWleA'),
+ (1000542, 5, '2:ZSZCp8ECZJzYCAvR:sEpivxBxVoqtmlPB8k7GEaTwR71tT7bGHhbUWJMS:FclGKW7O5N08EnTQJBTUPQ'),
+ (1000543, 5, '2:czg_J9NmNcjCzGm0:FVHiWcgV7wrKN4vT_YykdFqfJWdWxrm1zed012Un:RAbFadB8j1RXRuD9gePClA'),
+ (1000544, 5, '2:2_2mZp5u7rZ_ndv2:7eza1NMFZcZxGEsl3OlF3xQOgEZ8tCII47tQb85O:oN_A6LeeCJTT45TmHK68yg'),
+ (1000545, 5, '2:q9fN9r_PS2mKgAkI:jzfLTENaOzTnIufwlE5jEZSP0uQusM_oXv61F3NA:49TSXY4x_i6wzTFQ_OADAQ'),
+ (1000546, 5, '2:TVuyfVinJ9H0tipz:U0Do2X6E_is9EJX8Q-e_n11igjdByHBJkjXWnH8_:XqajQM1iSyOWv99sdmcQcQ'),
+ (1000547, 5, '2:-SNDYmwCXLi82ETv:KS3Thgj67oqXbEVNmNGvfuc_qEFDkZoIabECnJh6:TAD_JyxigwHbXF2vcVPTvA'),
+ (1000548, 5, '2:JlnO7NKifeCuFNwY:pa-3J_7JG55h3IaEdnWlUwBvzB_nmfvLgnxjyeom:hnaYWVUYRdtSiNjhroLcaw'),
+ (1000549, 5, '2:ObQsSt8GLaTOEqBr:1TFSYFZYFw5fWvi_E8Xf4dw-xn0lv2L07_dF-3oO:nVAb8zj39MxCaVkQvP7vtg'),
+ (1000550, 5, '2:pwoySbETze67TDCO:-smk_WjFzjOuaCbbE1unT_jYmTtNoKeixKhM5j-6:SG1q1iIbppKm3iPvG1R3dw'),
+ (1000551, 5, '2:S25sbkoXx6oyx0aM:LpWcsr6zxsuip3stQiIFZIqOhGb1Klh-qInDVZOa:UE38JsRultaz9IR6TKjZ9w'),
+ (1000552, 5, '2:EQm1w2_RmBMZ81_D:zQslMNxzSUQXdMrng-JegFKGbCFkYGC1zlV9KxPM:dhrkxrAnyZvGhZz3IXjTLg'),
+ (1000553, 5, '2:SbOPVWNxVwX9OS-q:GcNxNLfdg3dcJB33Vuf3ejWuBUKfcYaLuaLEVs9J:D2HDbb8K7RWTq9nbkYWbRQ'),
+ (1000554, 5, '2:FyvKgueosQ26VB4i:Iz1pcJ7SXVQMDV7PnWFK4mskVcNVRXaPPdBh1MRF:JlLtXKnpA5VRLYwaZ78-Qg'),
+ (1000555, 5, '2:c2H9sb4ovM9Quaxa:DHvbnrht9_oELwJm3QUY9IvDAFaKht4RFSWMjacR:rCi_wXQ0e9juSs3o6YmnwQ'),
+ (1000556, 5, '2:1yywS_osfg4qlbKz:tnFkQGG_sYoBkKvXlrVfJvOhwaiIdo6oeS6Usg8b:qkWPlaqHPIF0qlRLfTaQSQ'),
+ (1000557, 5, '2:hU6iZqMcnGyM_R2U:rOoDpoAC1tqH80QC6gH14KygtPzcKrvhTvZZTB-N:rhdmtlLLceV-RLmmWUI5Ug'),
+ (1000558, 5, '2:mvqm5cTya_a9XJOH:Q8NhuTg5WVERmEZjxdx5aU00zwmTcaRVQPExPjCN:qumXyKXAlB7t4oLXGOA15Q'),
+ (1000559, 5, '2:gbfiET4Druz9PlYO:bryPvuhWijqK42EkTgPwWfQVjdf2JRVKqV-c8AEM:x_xQQ1tIjIKFOJA_6kiEVA'),
+ (1000560, 5, '2:Mz18kmSxOm1WSjUr:Q4aYvn8gU5tq_MQRyq94b3IOgCcXf2VdPoAzCI-E:mehRmrYXBXTCgEqy07sZZg'),
+ (1000561, 5, '2:PMoy2sv2GaNyzIxx:ITDIBcOpCVaaFLoTdGKAjQZVqPfOXdaEs8o44zKm:1cPm7JE6zDetfzlLABP5nw'),
+ (1000562, 5, '2:ODrjBVFyLvMHuqZX:yCynrW02YMxuBhwGTS3QDWTJM5GATgN4sIBPdHTL:uvVw_YAmxO74GQ97upHatQ'),
+ (1000563, 5, '2:58GZ5WTNKqNc8fv0:hroOmRWBRaAZaT8t1ojXU-ptgTUhlJq2jK3uIXzx:5WUvHTPm5OG269txkY2cNg'),
+ (1000564, 5, '2:TI5CY0euHMznIqUm:N5VXOCbQhP0qO2lO23P6k-FMtFJM53rfDlTJb2uu:bDra4A5S8himRapb-gVDgA'),
+ (1000565, 5, '2:mWPnAtxVbQg_k6xw:jny4EaKrmxg7EfQZ3BfP27zWte7KrTAQ4Sof_Ihi:Xc2J_S2XBAvM7v1f-WSBsw'),
+ (1000566, 5, '2:0i9GGU1zBGjXqLJL:VHt_4aHHdGXuI-RHSwz3rAn6gxh34976UxNSCs4S:b_7K51YlIQPAqNo2njsdnQ'),
+ (1000567, 5, '2:cnwe5H5wjI6GOnvI:-zKRGIhQJMs-9-F6YCzwYZJDc3fejCVIbpLJyApz:ZS_ts4ddp9xx1OAgjZQTtg'),
+ (1000568, 5, '2:upsEzkjfV81oGumE:qu-NbQLPbx6RW3DFdPiTp-T7T1IGpbIIWl_Wybb0:Lytchszwmc8rZ3xPBQaVPQ'),
+ (1000569, 5, '2:iHLTtiqcvoVrma5U:SDKu0-lTsaz78N9p94z2rhvjsy9e4WpE8kZA30E-:aF88ehqAXBhHIXQoZT_Wbg'),
+ (1000570, 5, '2:pnzon4T9d0NZYf2W:RK6clDtCy5E3dyb2LDkuhuHJ3SLhxfRdoKjojen9:y9hJtRuH_b4nQ64THBoKUA'),
+ (1000571, 5, '2:M20myHYFXTb362rz:ehtbs1cDLNeIPPi-X1OjK6Tb9BiTFBTodrI1eU3E:C9POT-fnacN4GZY6WvIi3w'),
+ (1000572, 5, '2:oOW_CzLdbAwuqx_S:5-8pSGU5GO-efgN3WNoR9tX4l8ot6omHoz-88Us5:vT8hNKA4d51mTjLJSejlgA'),
+ (1000573, 5, '2:Tfhxe-GNpb4UjPrP:rzM1rS24FVd4JLWunx099UHwugnxaYrGkkO147J9:68fAzhQ5UR_2SpPC22rjdQ'),
+ (1000574, 5, '2:oCjAmD0sftLTWX5b:c03BruTzS8FDWLHjNsoCLPUwRIMUcn63DKCzc8TW:NsCn2DKGTqN8gunzI64Lqg'),
+ (1000575, 5, '2:FgbbYF-jfGZq7EpU:Nz4g-17KbNgUsGC7VdHpXMZ5L2olmQgLcfCChU-l:fdG8EOaaLXQ6awia4zTcZA'),
+ (1000576, 5, '2:iVIDEqDPDscFE34P:yIPREH7hlGf1kCI1g60FUYsnoIRce0KJ3JyYyjXl:vsdsZkbXQ7vVk1JuPd97XA'),
+ (1000577, 5, '2:8-IflTPf_XJYqu9A:Do9-zfjw_-eWET0hdCtQwzIR1w6stQ5eKeWf5-1c:whV2rBkFnOhONO2tuIrZ1A'),
+ (1000578, 5, '2:OJySLr4ms8pqM747:sSJkOkeFljJGvVGXSrxempZG90_ousZ9BcBnARpl:1TjRxj-yZqB6-T7HGIALxQ'),
+ (1000579, 5, '2:11dtUtwAPsnMrmzJ:6UmNOHvfmRmqCY5aUp3zI489p6w8pP2Cmq_Nu7vr:oO8CgStzxRWHJ64sZJ-_rg'),
+ (1000580, 5, '2:f2VPZy3oJhGBgCnI:daPkPzLkMVAgPC6x2JdCy6SktocQsdwtiJuvCR7K:B4e_dSIUGH5pMrF_KUATzQ'),
+ (1000581, 5, '2:cLDvN4Mh2__Zikkp:RCCnCl5aCrNbXw7zrw3yGtgxck7XCBcQ5SyJDH5O:h3WaSR6G6iR7Smlgf4fgMw'),
+ (1000582, 5, '2:Pzh0wHFdvmMR-FnU:eZzpZj9pLE8aqNJUicm9wA48-MRQlnN13xXcJ5ig:RoTHBdEuGrBo_joxFc3kyw'),
+ (1000583, 5, '2:D9R3I0HXYnq2Naej:vtfRDxIw8p9ExxMT5Iup2Kf3N2wLGVExEPrcOmBs:FnnZjLCxqGMLkC3opiH3_Q'),
+ (1000584, 5, '2:OCWZ9drBaeqj9ooQ:8sr1AOIwMcGmZhYu9LREVXpH_PCLZrqAz4BQAfM_:jniYjGkw3H7JlWttPI7hQw'),
+ (1000585, 5, '2:JIUgGHAlB4BTnAHv:_3XNmLqNImDkymlUMHJtZn37ZzBMj9FC_owMvGO6:rhkWpR3weqBcNC9CvxYOxA'),
+ (1000586, 5, '2:HE_cwYaqcEq_X5uM:GOIW12INz_wWtaFlFnnDb0CciCq-puF6pTJSnsSa:Y6xr_CHCStUq4D6jOy5kLg'),
+ (1000587, 5, '2:py2gtY93QUHidY5j:ojHqgBCkV0yfJpz4OSxTILGCXZj8DbAykl6n0vvk:Ha17OwU0kNdpNZQp7EqmTg'),
+ (1000588, 5, '2:Yz05_d4-drOJkjYR:CzV7qIeil2C25tF1aj0iF3EXM1SC7Fk6C7HNOPHP:sSoAtX0ofIdeJWJrXrsV4g'),
+ (1000589, 5, '2:uj_u8zprvxX9zD_Y:-_uS0YHs5IwnSyVV3Co6M4kTNle9SGc4XSKbaim6:uvNGS7Ovh-isWV487CasIg'),
+ (1000590, 5, '2:qOufgoMFDHoHztU2:U8X0QspTt8p6UHmOXW26z8D4sB0vyb59WLcjY_YI:dj_TuYW1_vPA555y1whMVw'),
+ (1000591, 5, '2:aLcHZKefZkT-5mA6:BCEKm5rNhfYg0rLSiCFIg8jjw39mo6Gzw0cIpVEf:TrUGLgLQ6woZL2wFssHNNA'),
+ (1000592, 5, '2:MBDmDtmjIBY2vW3Z:1-XdLeya2OdQbqPedPURrJELx7qK2mFxcI4SO4VA:cZ3Q14_qtiVWddVB8lpDKw'),
+ (1000593, 5, '2:W_scRZo5XFuRJSf1:VyNDW49oxE9h5sVeem9J89ZzlzF6W8Cs1h2SII4v:ThCrNzZAils18Y68PzQaEw'),
+ (1000594, 5, '2:3DE0dsrQpti5LTFo:0ix_f4Aj_CkMgwG8zKvA9EszLaFkFlZ54TbakS8l:kLEIyGMwk0LCsdP2IW7o9Q'),
+ (1000595, 5, '2:1gd9hqbgI0E4W28I:KyiFnT0b9JJq7ZP3lBdVK6pRtRjZ0YdHDrBFIs4J:J6oA_zs5J6HrXxZffzVYbw'),
+ (1000596, 5, '2:Pb0BZ1n_7xhVSZYK:6ojkjL2EgBsu90qljNWdyGulJu47dBvNwigS6WYw:V4QBWtxvGg96pH0wPu9C9w'),
+ (1000597, 5, '2:bLPpTCi2b2R5dUxt:Ozhd-7AVqCIJzCL6iNv5UmhpMx6WeqBoAvba3Ot5:3UWX39H8MWJpWT_7YYqmNg'),
+ (1000598, 5, '2:xQyAWsoDqjR_POH6:bZwxht5YpZjf0qZk6J1rCBJQXjOkkJSkiKMt4xYE:m-Hzqvs_pckIV9PdhKqc0g'),
+ (1000599, 5, '2:tRtGweoTGw4wyl_R:0ygW8d8S7j97etG85Z2jjpp2hwWwaEdkA9ZLQGmn:3NreHDFl6chaq6yhQv0f2Q'),
+ (1000600, 5, '2:nbCgg2CdIIQBEmQE:CB-XvIY_HxZwqQ7bWLlp3QFde6xj1O90tCTfbvhm:GVBpQealINSR2Hi9c1Ou-A');
+
+INSERT INTO tvm_secret_key_attributes(id, type, value) VALUES
+ (11, 1, '2:7YbhlHl0nIsaZagY:_MaLvZ0ZsYKdZ6CqiwI5xbRnZUIvivBR6Ir6n4D6vR9sNDdpgj5DwSjCYYcZUcnEGwoG1COQCVIpvXKAc-w9v2bsP-J57S711kiNqT4qbyJ7WnPB10wTB8yEbAZKBv7MVh7TKr-zJcxvfhLYr95-TTtfYcwn0y0N2oWwz4URdByphjn3-Zy-HXPK1bkaBZzelIjeOkN4AKsrHToBZM2jjnFqnCAFCYL9x2CZxPErHWayeJBXtMnbPblbRA:5Cd81ytYslGSlQVTn4gDvQ'),
+ (11, 2, '2:r6uCZDsDpvQG18QZ:lJICo0pfD_04aNSzBSWf6FZC0yvL1TA7R9mZ5RHzCbj3CQLNRri2gTniWyv-w5ClN-957GIU8zeYoqT9iZnlhciju2jdKxKuPAMn0-C12Vo-tpRcmywyNRa2E38Dt7NVv7pXTOMB_xcesiH8__HjVDceDcQ-qkWTVo0szSEEVwlH6f-l7hlNOA-bE2Y0dqE2UNB6KpmXAwdS6vFi0BlcPpJT_zA-iMPKHdVjkMVWgEWq6__9S2Br3KY2emu0Et5dOH8rbpVfDYWywnriUJ6UfW1kFMSVrPTcD_vJgxDw9uG-cL41FX9PPSGs0coH04wLsw0UyvGflrUA0PpN-SKSXx-U5jnKa3LsPX9q7FOSQxytD2xaBDWzhHb3QCHIXTTmDohyswJLvMV_BYsajHm1MnajcAI98yp_I2n6Llj0O02fBE2q14HbpJTYqWRIuSO2wLq6eSOrQjsy4YKv0qkr37hGYShY27vMrX2Quy0GwITA0d-vsiE-GPvhh445V2mmfWdG2gHPz3VTzqSbwlk9w2dUKOmmZVt4Il76F4fsVw6BcY1lG-TeOXzXm-Vh_R1dw6siis-4bysqXp0o3eoHo-2ntBsNNKmTcwFcMb1kpVpV6XgqFL0I1rZM1OoUY-w6OHCioyAcUd5Ou7GA2LhivdafFEwOqdQzAcyw4dNaafG1-sWvLbWl4PpXvgMw8pPJ-2VC1V9hxk2gQRTiNe0ShTZVhsqOgbQgqYMl26I4c5uwYqXwz2WisJ6KPRlAIY9LhIFlTBSwZc4RYH_NVpDlpYm5YsKjO_cfNSrwv11MB7wIAzQat0ASDtYmBvKpXS-_xfV_mzfU1MR3qyJqEBjniKI9MJRn_cQMH7f0rFVLmjBnIHE0hT2edpYS9XYcnV8MT6yB7DUQi8ihL3iFGsqbIl5Q-YBsc2NwQKBxb_ZK0LwNCj0NMDeojgSy_TEE90t0ew6BFZiQcy2g8s9clgs__ERTfAutzcvQ3JSAVJ63ZSpbkJOMhc-8P_geZOmevKqb4mALGJs4IHAHFYqKcYJfaoa--xTJxtIdBtl3Kh8wxJq9j6dwODvk:yIUUn4YWuGO7ZX55vPQYRg'),
+ (12, 1, '2:Df8zob2vAPhTXMTw:TxGEMFi1zsQgu7QJpehsjEJQduuclrS5DpjLuI7sZDBaH6W9P6-cqejXrYud61WH39xI9rzOnAJP1xL5VPQiOCzOeB54Hmkd7pSSeQv-7i40MPplqC8YQC5Ff_ywUlWhgXUEzmk-137Fhm_VujhCa58LAAywBWr_er_haa10qMXdfto_IGmWMl01QsQ1KhE6CHVpIGEyEaMLNS7_x3dNk8nbZj_pwpyAcYTfQxxlnoEzp0umS6PKjsT0GJ8:zFGTFDMOl36l5hPH50rrWQ'),
+ (12, 2, '2:0n9FshEW6Pg5wDDl:6XBHnGdCm-1XIHh8c9WbodhmnAQq2gc9dNmBUxsqWTag0Zoi6c02zOkPUTi-WZQYnOeIcELkZyHeNqwIqa5rBSET_dBAaDpnN68L21aMGaykLU935hANgCNt7jcLueAkMkKoBOQg4ix7U6H_qgOR0UIvRourF4BHa72Rl5-6x__FnUhyUthP64pywjEgEpMR_DMTMXUc_QqFAtu99__TdDDJU_SnsCfi2fin2LYULxtES2MNgJ-meBp1i7T1mlMTmqchRl8kVnkpKwWXOBcZ9JerSzUGpLtA_Sa_XsBYNIsEhiafwBHO_7a2G25A4bJhG63xUVJawgXJK3xBAPFNz7mSlG1MiVD5gv5YsloT-2732JPsBrQ9GSS0_KtEUdMSzHP-gLDd2KA9hpPlSzDd1x5qT4xf7YoN3Vv5SaB49kdHwMlDQTcue6BXnfC-7mlVYR9HwECX232PTQAjGdOw3i0NUpI2qVCmPJt275s80gl85jo2C77B06ngnMHDmy4CUYxr3Z5AxN1veCkUF6ViI4RcuihhaUg6DIZmcTDMEF5nCPmm1i2_-qRcORrp3h_aJaG4dWPw28VEojws-GLYrOjZ67YwSerOuMhg8vKIpP2yTT7m3ioGZFlMubQyvB6KLRdf6u-_ZshZXj5xvMNraiyerXVI9RUI9sg2hWrcnhO7fHZrWbSCNpg2RGeXsqDcu3mEfEa4ETK6mJ_EF4WJPctkiHkERhjrfF8B8bOIdpnPqoT5dQ7Z0B0TFWI6a_iBVFq3eXIYAr-Vpei7lWATqjjmMzVmIlVmovQvWQTXRcOSuK9IdRdlZIh_kJiwzCWGSx5tglgX0GpOUrED1aWvYETeoCo6D6SqeLVFjPND8PKOf5Tic0khJXFXSqb1lh63JNG4ch6K6B0eEyG10MJ8MFNS7LwYsmDcaSe9pvfZtxmsPFZa-0W7cfA7C7vsWKwmNY3pTx1Mf-NLQxs2CpcvYljwjj3XKua1okHSxVp3jXVObrNVRyuw-iyJfXsRw7fMcIJQIWy-oLLlbOFw_Nn2X5Vm6f2TXjST1OpDxmbvSUYh2IBsOBZ0Hw:8PAxRdI_H5FehVHQJt_2rw'),
+ (13, 1, '2:WiHYcsoSi-6CVuuE:jY83J3929Hi3i2CgRUtS1fs_Tf2AnGcW7TnG05ht9RvjbdBgPTYtShsQgXUnWWOV2fh6-IlVpOwnE3v9FqGT8rEhy6V4QOqa300YS13hknms19Lt6UKEHsJKrYemK5EGqkjFTijnyC-AMqOtSeDwmGW_2hoNYOmQgaJD93DFiPEFU2KYt0TTfr5avXjkH4TCzpGUGRfPz2WB422Msh3dc0_hI1COkbGaAUGLuNpVcAohLOvu_fAJw7tgXNI:CDdhvDyzAz8cTgjsfw-dIQ'),
+ (13, 2, '2:h715IWhxexGa6LJl:iAz3GelexXYNegx9UuiCWMdxOA5RouRD7cZY5xOuTLyab9G5mhwzNjDlhNx1mxcmp7GukeqViZusBzZ8yOrcgA2NjPwgWp8s41sb0z0PXZYJGqqTteKV7o_ALy7qRmeSb07x3g7v2NX4ezciWJfPuJtC6Z5AibJVt6_YgFBvGrbJwqQLnDslKNUSDexaMpqWOglwCNHTS9akXS_Wgs6n_bzm-3qB8peY8pMipJMsd_XofNTRBp8MH2Q_0PsPgfpRdtY_heSSjpIsVmCbT_kNP7zAXotKlXA70oAn4MAd72Wkt3pL-UjMlNY972H2jw7TNTn0207wwZ-37ZVHlRCx2kCqLkMIL1s_U_vEyGlnR_QQQM9dNA6ONe0mLW5lhEeZOTamWjvYwTKRma1NbyBk5EpCJMMbbovJdItHsJgic94u0r9KGBgREyp_MbEZcXbkd28U7eF2m1wY7TrpRsEc4ZLTRUgbqW5F9rqee0Zp_v7MNX8Q4JpexYJ3ok8U5nWBqqJQaYKj43A0OtuasQDkjmrgAEVEVU6IlY1dqBR1DRU7ZDeZk2yWErtE7ePGept1savAB7aUdZSw3PkTRHxKJqGZQJtXzF8Hrt4WUB9S2QOE9Hm4OWvjqHfM9IUF2lhDF82M0oaUcpVMTLW3ytjsFMKOkZgzxpp4GbQXsexL_WOIkURPlBHww1WYHJudazPqnszxIrsRtI1coRc6HiVJ925hlBKY8g3bwzTLM2cfXMkZZwmjajLKBx-926LiCJ2M-JOfEMnFfpFpOeLYbTJ_dddxxd5beT-eNRhvOVxiHvinw3n06CxyUqh4oHyY2dOQlNHTh1G7QRVBcUXHgRaYxPc-Jum3OD3Yxpt9rso_6saSmbT15LeF3EhyXZVkSPkAcWK4MKLUH77qxchYr6hKIg6SeZ2CeXByRYvd1k-XbwOrqFWJNdaf1eBSa6mgHgy5NKCMbQUlunKcO1pWAD_watKQbfW6bJ-R80_4bqwSCfFMBcJETNxf_Lef8Xg22HvBRdcYPxNa9TQjoOy0VU0mYOeq_NQrw2pXZpm7teZZrIqSkETKn_oc4A:gSyNyreLOTB2YSbM1ZOTfw'),
+ (14, 1, '2:IrGSkY3MxWglnFsN:wbgibmmeJPMAaeJl3__OQP-i4WUqyWgUFDtZOZgk6z7TApmNbTDoNq59y-HAWWiSWckVOhZI25MwjQu8nTJyEC8r04l8vUCEvwP85VWUQWJaw_OvpWDHdytm1Uy4jTwdxdXPxIzSEWOxQgK18ZKl-gJhoH6kFOpjvxIEJYhaCSFxWoqqYUNz7oFvuLjUMFSecCtUbce7GXPzzE9sZzxH4Crn5GRKipd63izJUmnYxaLYm0zg9A1h9jPMYA:fUK2Vw79Vs_0knIyF5S3HQ'),
+ (14, 2, '2:jNYZ-e5P4JTLlbQP:QeyMk0DB2ThiCV7en5hhwZZhOxWw0R-z_sWJlKNh7esKm5ONuvkx_NjGFq428qBuc1KoQVdwh4tvT2Be64DMIwL2Pk4BXY8xc06XETqYnMWmc4T2vyBLYNbqsnE4wwoqM4swFl9hUVxLdynJn30H4c9n021Hyzcjb2OsCsGBSs8jUz-OysdFdS59CnI3su26foSSXw2s5VTDNKfjX7cZdm1s6EYMwjl6Dah9q8LLwmWlxKORhE4VXOwljyTVHB-HqFIsxVD1MitrOBXXiwWETkWJFpBcXs5g0bLUChYOJx-W66EwKveWd4q3ntpBrVKRURKC-GuHaeXHMventnplUiJHa2vilQJqc8radcxmwLPm-8IsOk_3BGCrM7NbDisqzPq1EWEEgJAx-kr8B3I1o0BA-XiA6CkvwORzjpb4nZR9R13R8q6_VFl1-_Xd8WP2rn3bJDQ0LnBHeBjPr9zxTPsel6OxH2hohv-u25fhT1lO3wF_Y7un6ha0a9RgJLAG7Hi1IKHmDv5igFUv_8NfYgmIF29WD2iYS9M46vojkI1d3uxJVoK27to4CQfWepk29iYsWpp6mUzy8mMbhPt7NFp3HuHN7xBeUlB6Gxq1-UNQEbC61bgN7c-lbDzSZJNFv-NT0phTmnm24kkAJEiP2beuvVV5akDkeABXtfqf4hrHJOYazjBaTgqu-EnxvuRf6AA-EvQjst7y6olcqS0pkrjhldwkXN0m8W9aj_aruerBGIEz6_oRbf_SzAtjDJgsDIvMObm9GdxN40oTzZzspB7YUkiH1irFmb38GionpHUwCoA1bLa6_wvW8OYwBFJ393CAmio9pr-WrSI-L9ztvEBjXfiG1WKy0jqKE_3QvDw05DmN57WXJawHrmGTI576FYaxC3QO679KJ56A8se2Psfo89yvDqoHHn_R9SK-Dtg0g2m6ron66Yd3qJ8seiO5higQaNu9ZCLBqV-5uBqT63MELQztv-chN8-snXPa1C4nJHz03Un4_cSZtasEBifApPEu3aM-o0ske6AM4LcSzcpp2w597NNDPVxJZYS7DMP64tpPkjU1:1vzoNnD-6colsWPAJFi-fg'),
+ (15, 1, '2:c_ETCkusuxVnpSEo:Bz75HmMt-ZISKVcjGh1E3TR1bBbXXKcLmdOvv9z-89MzVRK4kTahouH-s9DoJNvJD6qv-mvElWHvKN6-WU987c21oUjxLlGI6WFMvp0tmUUJAUWeEpjhnb4xqV7qKIcoWRkD8-ws3BW0iMGI8ksC6-AeFX3zzQ9bPQms6KvNKlRibuE8eSJaBaF3Cb0gXh-51Up_LglRp8PDuf2uP8GRIM5Xui6QULM4vv28FEpIIyn_mRC8gWG1I1Fc5A:H3udl-uIufUzaDJG576ZVw'),
+ (15, 2, '2:tnjjNmVDQIh2cfFe:y0fSCdoOVulR2KMHBV90O1y52r7hTSFZ39_f6JS6i1baQveQZ7rXd-DLuNLPHh18iz7Cx0GJjev8YVGe4FxU7c3-AEZC999NDT-vqRj8735VI6G1FG4O0qiiVA7EpyURxsFvw9xq2vojCnirw9yY4pZd4HNQnb9hCymKqPUdE6_GzYKC0ESK9ZYtbnLfdH0P3r35IRZm8gx7E99mGR3xWbxLUAJV20OZ6I7ZAsPutAx8VYeXiiKXpTbHrxJsfnLgPiPKQlwBZqrhDw6jj9UdVB0jwOvUUSJRSDBZIY_POvgMNebqHDSYXvmpTqMc9wckRuJTAMHRxawM36gjupVDGUhDtfKEh7-ERNhS1sqZwHfvlptswQj4WrB09E3i67phxUH9GO142m6hZsVpJFf0F-BGer2WljTMN_NqaWEvTjp1SQxSDl288SD4KQkUUovc9z078knIDNmqnmvcSt9lTZ7vaAcwrPJ1a72gKaPLe-olRga6lnGsTXgpohgQjYXpi_G08i4AibzJrlrhIodYczuQ4O8c52aGHUoQFV254PPi3tHwd2f7L3j-PMv6eC4t-7972Rxrmt9BGrbfyvZ-4qH4KWslzCKzcLCqYcdVSANIn3fMZ2RZCMFiE3WWyWSH1zEbGkE-DdDuFEGpybFQwswSRXSk95HLe-oNAQYl_33iQTxYLplpyrAwmiFd-kLRh9FMvNDiU9XvOYPrnAMmeOxzcCdcFi8NSjXFGgWe458urNOiB7fNLNJPMUnaRwYTlWrQBhMKLB_-xsAn9qEg1GkmxApR5s3pVB0giMwBFePgXrCK1fU7gXghrz31UR504y97anvV4Q0REJo0wNXrLDSZwkb8Tz21XKNEOPAo13wWCM9d2n4EtfNRhTNLOgGtMJGAYr1CH2xI7XSlG3Ji2Vp6krheBzy4mzEKkT219yQ1_ELpX8ejXIbWIiyGx4UarOEhFFl7PYgv0UKhMTax0Oqa8H5RB874bPq_2fCMLWeCShlopOdqbt95Prek3glUyjTN50rx1-vGNBXGRIeUbjbfgneDq6rV-G9oKjwe5j-2rLnkAgra:kbxMH81ZBYt-GTJQMDAUSw'),
+ (16, 1, '2:a46VR6JExNtreCmX:bF9bxIEj63fSI_PNOH36UBoTw587X5OdYEl4K33JhGBs4DH84VKTARcZ6LiBzwPwN2Tf__PWy9fAt4V4V5eAKKOjS_erpv8FCB5LC8dJuDaHOZOuZCTDhRom9gLbGxotDwB39LOaH8eBOEf6AkwtxzRJrXyZBQFtb8KlvnlnqetfgBLaf6111MyYO6P4SiA0LXrE9MjS1WY_R76K6kGF9_8j9qbCke-EF0ougcqWXsuaz8mEjpHG3O8M2SM:F4SLvUdC-07ISrovDWChDg'),
+ (16, 2, '2:v063VzSOGooDsKyA:ZQEhJIZS6WcabCE0YjE1Q_R6pO9xBeXIlzlHNAlipv4pzZ2b9HKi8fFahNoHJ8709dtxvi0WWnrhxdkCMKe764fPx8vuHtMuTUHderctwynuawb8gZ_9OUQWD9nD8mvJv7sY61g6KrrzD6RZDkSXtcgJp3G8duN_Hmk2zhZHcWjbeDo1SmfC1lPHIB9QiBM_OCr3JL3dhOQK_3cGeDTBbHmEDsTTUlco5cPIE7UlsdwrJ46S1d1nvCT3B3nondfn40p9MdZ0-1FGNYb-d-QGrlvZMZpdIfgBgneUGHc3N9s1Yqp6ZLi-TgDWHi73t88n-BbSTYJnLUgYrMd_UZmvudRZ-RYye94bdShoO6yF4v2hfUvxQvsk0l9fayXiP0cAx8EcZ85Ndo442X9bBjwRr5FEcDDWc0MehJ4pW0d_5fDlcVHeQcrdMDHGssPpbpwWEv3gveoaf2S8AYXf3bu4A_RnaUN922T0Cg79pyRfhnsxKVHdezc96B3si7b-wrFqSNxJxYXj4y25licxLIVDnva8OVCLB4HGKnx5XEeSB-ocjtYmqeCcTG49NuEey-3jRgUkzDwNVYfFfIdHCn5I3Rg77KwpYijnNo88F0kUzFui3DGHxshT72E0ZBt6ieolMaghept398KBSlJ6UnWp6P83rrznmZjVhyXMaiCBrnwnS271AP618ypLjh8rKM0h6zjj1Sop-PVtdkV7Z1oFPyLGGJLOaOFO1OXooVIXgyLMT_FLnzulQ5Las6SvfL_44fT0zPPigyNTM3PHmca5ZjOBo9RM_CYcDXdZ-IADkkzfBiGgzZiRRWCdFP43oZjP86wQBOhoIqYqmVXrwU--9JAGElBvYnyFcmmXaVRdYldx8fF0KXFPZVx-O0ydonJJ0PxR5B3XzUv3B_TU15Xvnc-uEatO5JFynhF8Gombw9_jMhmm3Nog7JDDO0kHPybUKYbLMB02nXBSFddYrF8SjJUknYsxII79YNFepnl1jUKi_eFj4EwHfBq0sLKj1b1tBKUjrMSBBZw-7t6DzegfCzSCqsXJsyyE-hb4vjfZBgqUrswJRE5JmQAv:sCeBbbtxCVsU3uZj6Ud6dQ'),
+ (522, 1, '2:asXyM0G-XlIBTfmx:miPgnyrt3q5l0VzPPrrMITi_pIDksbmVtrATJx7io06EAN4xHb2nNusQahdg7X5mdBE-BJPOViBAsT4IJ6ADAzbT_ZNYstxV6ll6E_4eimtTNFe4UTM4dXsvpVDB3tBoyvnkK73pwqbgKVHK-3b8LDpfqlAr6Ptrdz5glZggykTCE7sCNzOF9jWEnI7vp2e7r7DUoxHZzh4bsbzPZzdd_7nZ24YEhcPF9O8oioV4RtmARkdkQHmj4olM2To:W5Qmtz39HUKTM_KUHpoBBw'),
+ (522, 2, '2:RHjTGvuuioRH4g_e:GJLw8xu-qk0Tu_SFhbAAsZ149BSwKhimGBgIzYQbWtA_4xAXMwkD5-aGsPBcKnze4PMPYgRPKpEYO2NHfKF2EVfTHRWvnzDnLTbkjamB6oLt-f0_EvaF6brKVME9vYqqYx3CHFGRC5Ytj1z14Cc9yxbXFuWh59GmlqvddyzlLtcbDjlV7PAIzPz_shjiZxl5FpR0ZNkranhHP45tINkyZsZDA-V-ix_I6UZGuUlDcBl4HMcOusxgouqQNCw4Z5W2fNdjvHpa8MGdkCDf4pDfVaxw0Len7dVfARehBrVehPDvp4b5JPuCu7Zo4QgLIE_GX0fw4rGhFrCHxy_YbtiHIHz-3mjThxwzHL6F3JLbwbzA_bQXX7Ryk_MBsRFzSEHXidJZpnPGN-SYykWlqxl8rXhEYOtt1rX6NDYLuj94tPN33c7ND7fZ1ZsThiHyGOzqQEJSEPLO_1UfoBvYp3QuZjWReLF8T4ZutouAnOTE2Ff3alucKItlcATNGU4L8P65-nd9-lij9Sitqi8z2IH4tgEUDguzEE4liyPqjePwiav02IR0bCziDaBZAbzu83LHC9Wn0VKDVULHesNRDLnSlCxXkQrykDY3yV_AngW-uISof_lnJFPCQSlelNoswqY2SdqMVABvmQ_5cYMUuJyIaiM1Q_9AhE9ZoDkiSsjMT8sf_MaZ3MDF9_kMN12wowCTID0cWNC3rFw-T94G4Pv71s-ufdKVJDL_y6NFG2kzeAz6xy-UeprXPnCNFXKHzF69qcgD9cazICZllTYRisYa-oqedlHvABtbNtnbSOuK07RBJLio2gQATkwkGgIribzp-JtnsgqmFE0StPctf0rSLl4OGxP6393SvdopsuFSJyuWkS3we_Pbm2Jh2ckhETEnfVSovmDh5rsBkbXi39XAtGfdHW09ZAt9p9wkzRhTp6MCyJLRpo85t14ElLTwJjKTo_5oPRiWU_ZYxdbsgO6FiQFsCmmHeIX3i_lECqHYrJXdlZnlzjNj6exdiO7e87ljt6UNlDgWd4fRGsOK2YuwK4jh_85sBuQV5rCg2VDruxF6-XYPxdTzkMXq9A:Q1adWaSGK1LOLFsq0bKGIg');
diff --git a/library/recipes/tvmapi/data/tvmdb.credentials b/library/recipes/tvmapi/data/tvmdb.credentials
new file mode 100644
index 0000000000..e3a2f0e121
--- /dev/null
+++ b/library/recipes/tvmapi/data/tvmdb.credentials
@@ -0,0 +1,4 @@
+{
+ "db_user": "unused_value",
+ "db_pass": "unused_value"
+}
diff --git a/library/recipes/tvmapi/recipe.inc b/library/recipes/tvmapi/recipe.inc
new file mode 100644
index 0000000000..b59cc2da2b
--- /dev/null
+++ b/library/recipes/tvmapi/recipe.inc
@@ -0,0 +1,12 @@
+DEPENDS(
+ contrib/tools/sqlite3
+ library/recipes/tvmapi
+ passport/infra/daemons/tvmapi/daemon
+)
+
+DATA(
+ arcadia/library/recipes/tvmapi/clients
+ arcadia/library/recipes/tvmapi/data
+)
+
+USE_RECIPE(library/recipes/tvmapi/tvmapi)
diff --git a/library/recipes/tvmtool/README.md b/library/recipes/tvmtool/README.md
new file mode 100644
index 0000000000..672748269d
--- /dev/null
+++ b/library/recipes/tvmtool/README.md
@@ -0,0 +1,81 @@
+tvmtool recipe
+---
+
+Этот рецепт позволяет в тестах поднять [tvmtool](https://wiki.yandex-team.ru/passport/tvm2/tvm-daemon/), который в проде разворачивается на localhost.
+
+Демон слушает на порте из файла `tvmtool.port`. Для запросов к нему следует использовать AUTHTOKEN из `tvmtool.authtoken`. См. [пример](https://a.yandex-team.ru/arc/trunk/arcadia/library/recipes/tvmtool/ut/test.py).
+
+Варианты подключения:
+ 1) `recipe_with_default_cfg.inc` - для запуска демона с дефолтным [конфигом](https://a.yandex-team.ru/arc/trunk/arcadia/library/recipes/tvmtool/tvmtool.default.conf). Например:
+ ```
+ INCLUDE(${ARCADIA_ROOT}/library/recipes/tvmtool/recipe_with_default_cfg.inc)
+ ```
+ [Пример](https://a.yandex-team.ru/arc_vcs/library/recipes/tvmtool/examples/ut_simple)
+2) `recipe.inc` - для запуска демона со своим конфигом. Например
+ ```
+ INCLUDE(${ARCADIA_ROOT}/library/recipes/tvmtool/recipe.inc)
+
+ USE_RECIPE(
+ library/recipes/tvmtool/tvmtool
+ foo/tvmtool.conf
+ )
+ ```
+ [Пример](https://a.yandex-team.ru/arc_vcs/library/recipes/tvmtool/examples/ut_with_custom_config)
+3) `recipe.inc` + `--with-roles-dir` - запуск со своим конфигом и с поддержкой ролей
+ ```
+ INCLUDE(${ARCADIA_ROOT}/library/recipes/tvmtool/recipe.inc)
+
+ USE_RECIPE(
+ library/recipes/tvmtool/tvmtool
+ foo/tvmtool.conf
+ --with_roles_dir foo/roles
+ )
+ ```
+ В каталоге `foo/` ожидается наличие файлов с именами вида `{slug}.json` - для всех slug из tvmtool.conf.
+ [Пример](https://a.yandex-team.ru/arc_vcs/library/recipes/tvmtool/examples/ut_with_roles)
+4) `recipe.inc` + `--with-tvmapi` - для запуска демона, который будет ходить в tvm-api (тоже рецепт). Например:
+ ```
+ # start tvm-api
+ INCLUDE(${ARCADIA_ROOT}/library/recipes/tvmapi/recipe.inc)
+
+ # start tvmtool
+ INCLUDE(${ARCADIA_ROOT}/library/recipes/tvmtool/recipe.inc)
+ USE_RECIPE(
+ library/recipes/tvmtool/tvmtool
+ foo/tvmtool.conf
+ --with-tvmapi
+ )
+ ```
+ [Пример](https://a.yandex-team.ru/arc_vcs/library/recipes/tvmtool/examples/ut_with_tvmapi)
+5) `recipe.inc` + `--with-tvmapi` + `--with-tirole` - для запуска демона, который будет ходить в tvm-api и tirole (тоже рецепты). Например:
+ ```
+ # start tvm-api
+ INCLUDE(${ARCADIA_ROOT}/library/recipes/tvmapi/recipe.inc)
+
+ # start tirole
+ INCLUDE(${ARCADIA_ROOT}/library/recipes/tirole/recipe.inc)
+ USE_RECIPE(
+ library/recipes/tirole/tirole
+ --roles-dir library/recipes/tirole/ut_simple/roles_dir
+ )
+
+ # start tvmtool
+ INCLUDE(${ARCADIA_ROOT}/library/recipes/tvmtool/recipe.inc)
+ USE_RECIPE(
+ library/recipes/tvmtool/tvmtool
+ foo/tvmtool.conf
+ --with-tvmapi
+ --with-tirole
+ )
+ ```
+ [Пример](https://a.yandex-team.ru/arc_vcs/library/recipes/tvmtool/examples/ut_with_tvmapi_and_tirole)
+
+Варианты 1, 2 и 3 запустят tvmtool с флагом `--unittest`. Это значит, что:
+ * в конфиге можно указывать какие угодно tvm_id
+ * в конфиге секрет может быть пустым или равен строке "fake_secret"
+
+Вариант 4 и 5 запустит tvmtool, который будет ходить в tvm-api. Это значит, он сможет работать только с теми приложениями и их секретами, которые есть в [базе](https://a.yandex-team.ru/arc/trunk/arcadia/library/recipes/tvmapi/clients/clients.json) tvm-api. В этом варианте можно получать ServiceTicket в tvm-api и проверять в tvmtool.
+
+Любой из этих вариантов позволяет проверять ServiceTicket'ы/UserTicket'ы, сгенерированные через `tvmknife unittest`.
+
+Вопросы можно писать в [PASSPORTDUTY](https://st.yandex-team.ru/createTicket?queue=PASSPORTDUTY&_form=77618)
diff --git a/library/recipes/tvmtool/__main__.py b/library/recipes/tvmtool/__main__.py
new file mode 100644
index 0000000000..9fb70253b2
--- /dev/null
+++ b/library/recipes/tvmtool/__main__.py
@@ -0,0 +1,107 @@
+import argparse
+import datetime
+import binascii
+import os
+import requests
+import sys
+
+from library.python.testing.recipe import declare_recipe
+from library.recipes.common import start_daemon, stop_daemon
+import yatest.common
+import yatest.common.network
+
+TVMTOOL_PORT_FILE = "tvmtool.port"
+TVMTOOL_AUTHTOKEN_FILE = "tvmtool.authtoken"
+
+TIROLE_PORT_FILE = "tirole.port"
+TVMAPI_PORT_FILE = "tvmapi.port"
+TVMTOOL_PID_FILE = "tvmtool.pid"
+
+
+def start(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('cfgfile', type=str)
+ parser.add_argument('--with-roles-dir', dest='with_roles_dir', type=str)
+ parser.add_argument('--with-tirole', dest='with_tirole', action='store_true')
+ parser.add_argument('--with-tvmapi', dest='with_tvmapi', action='store_true')
+ input_args = parser.parse_args(argv)
+
+ _log("cfgfile: %s" % input_args.cfgfile)
+ _log("with-roles-dir: %s" % input_args.with_roles_dir)
+ _log("with-tirole: %s" % input_args.with_tirole)
+ _log("with-tvmapi: %s" % input_args.with_tvmapi)
+
+ pm = yatest.common.network.PortManager()
+ port = pm.get_tcp_port(80)
+
+ with open(TVMTOOL_PORT_FILE, "w") as f:
+ f.write(str(port))
+ _log("port: %d" % port)
+
+ authtoken = binascii.hexlify(os.urandom(16))
+ with open(TVMTOOL_AUTHTOKEN_FILE, "wb") as f:
+ f.write(authtoken)
+ _log("authtoken: %s" % authtoken)
+
+ args = [
+ yatest.common.build_path('passport/infra/daemons/tvmtool/cmd/tvmtool'),
+ '--port',
+ str(port),
+ '-c',
+ yatest.common.source_path(input_args.cfgfile),
+ '-v',
+ '--cache-dir',
+ './',
+ ]
+ env = {
+ 'QLOUD_TVM_TOKEN': authtoken,
+ }
+
+ if input_args.with_tvmapi:
+ with open(TVMAPI_PORT_FILE) as f:
+ env['__TEST_TVM_API_URL'] = "http://localhost:%s" % f.read()
+ else:
+ args.append('--unittest')
+
+ if input_args.with_tirole:
+ with open(TIROLE_PORT_FILE) as f:
+ env['__TEST_TIROLE_URL'] = "http://localhost:%s" % f.read()
+
+ if input_args.with_roles_dir:
+ assert not input_args.with_tirole, "--with-roles-dir and --with-tirole conflicts with each other"
+ args += [
+ '--unittest-roles-dir',
+ yatest.common.source_path(input_args.with_roles_dir),
+ ]
+
+ def check():
+ try:
+ r = requests.get("http://localhost:%d/tvm/ping" % port)
+ if r.status_code == 200:
+ _log("ping: 200!")
+ return True
+ else:
+ _log("ping: %d : %s" % (r.status_code, r.text))
+ except Exception as e:
+ _log("ping: %s" % e)
+ return False
+
+ start_daemon(command=args, environment=env, is_alive_check=check, pid_file_name=TVMTOOL_PID_FILE)
+
+
+def stop(argv):
+ with open(TVMTOOL_PID_FILE) as f:
+ pid = f.read()
+ if not stop_daemon(pid):
+ _log("pid is dead: %s" % pid)
+
+
+def _log(msg):
+ print("%s : tvmtool-recipe : %s" % (datetime.datetime.now(), msg), file=sys.stdout)
+
+
+if __name__ == "__main__":
+ try:
+ declare_recipe(start, stop)
+ except Exception as e:
+ _log("exception: %s" % e)
diff --git a/library/recipes/tvmtool/a.yaml b/library/recipes/tvmtool/a.yaml
new file mode 100644
index 0000000000..1a46b3547f
--- /dev/null
+++ b/library/recipes/tvmtool/a.yaml
@@ -0,0 +1,23 @@
+service: passport_infra
+title: tvmtool recipe
+
+arcanum:
+ review:
+ auto_assign: true
+
+ groups:
+ - name: backend-developers
+ roles: developer
+
+ rules:
+ - reviewers:
+ name: backend-developers
+ ship: 2
+ assign: 2
+
+ci:
+ release-title-source: flow
+ autocheck:
+ fast-targets:
+ - library/recipes/tvmtool
+ strong: true
diff --git a/library/recipes/tvmtool/examples/ut_simple/test.py b/library/recipes/tvmtool/examples/ut_simple/test.py
new file mode 100644
index 0000000000..32b44ad564
--- /dev/null
+++ b/library/recipes/tvmtool/examples/ut_simple/test.py
@@ -0,0 +1,26 @@
+import os
+import os.path
+import requests
+
+TVMTOOL_PORT_FILE = "tvmtool.port"
+TVMTOOL_AUTHTOKEN_FILE = "tvmtool.authtoken"
+
+
+def _get_tvmtool_params():
+ port = int(open(TVMTOOL_PORT_FILE).read())
+ authtoken = open(TVMTOOL_AUTHTOKEN_FILE).read()
+ return port, authtoken
+
+
+def test_tvmtool():
+ assert os.path.isfile(TVMTOOL_PORT_FILE)
+ assert os.path.isfile(TVMTOOL_AUTHTOKEN_FILE)
+
+ port, authtoken = _get_tvmtool_params()
+
+ r = requests.get("http://localhost:%d/tvm/ping" % port)
+ assert r.text == 'OK'
+ assert r.status_code == 200
+
+ r = requests.get("http://localhost:%d/tvm/keys" % port, headers={'Authorization': authtoken})
+ assert r.status_code == 200
diff --git a/library/recipes/tvmtool/examples/ut_with_custom_config/custom.cfg b/library/recipes/tvmtool/examples/ut_with_custom_config/custom.cfg
new file mode 100644
index 0000000000..e412046c74
--- /dev/null
+++ b/library/recipes/tvmtool/examples/ut_with_custom_config/custom.cfg
@@ -0,0 +1,8 @@
+{
+ "BbEnvType": 1,
+ "clients": {
+ "me": {
+ "self_tvm_id": 42
+ }
+ }
+}
diff --git a/library/recipes/tvmtool/examples/ut_with_custom_config/test.py b/library/recipes/tvmtool/examples/ut_with_custom_config/test.py
new file mode 100644
index 0000000000..9cbf48dd85
--- /dev/null
+++ b/library/recipes/tvmtool/examples/ut_with_custom_config/test.py
@@ -0,0 +1,23 @@
+import os
+import os.path
+import requests
+
+TVMTOOL_PORT_FILE = "tvmtool.port"
+TVMTOOL_AUTHTOKEN_FILE = "tvmtool.authtoken"
+
+
+def _get_tvmtool_params():
+ port = int(open(TVMTOOL_PORT_FILE).read())
+ authtoken = open(TVMTOOL_AUTHTOKEN_FILE).read()
+ return port, authtoken
+
+
+def test_tvmtool():
+ assert os.path.isfile(TVMTOOL_PORT_FILE)
+ assert os.path.isfile(TVMTOOL_AUTHTOKEN_FILE)
+
+ port, authtoken = _get_tvmtool_params()
+
+ r = requests.get("http://localhost:%d/tvm/ping" % port)
+ assert r.text == 'OK'
+ assert r.status_code == 200
diff --git a/library/recipes/tvmtool/examples/ut_with_roles/custom.cfg b/library/recipes/tvmtool/examples/ut_with_roles/custom.cfg
new file mode 100644
index 0000000000..8c90b8f62e
--- /dev/null
+++ b/library/recipes/tvmtool/examples/ut_with_roles/custom.cfg
@@ -0,0 +1,10 @@
+{
+ "BbEnvType": 1,
+ "clients": {
+ "me": {
+ "secret": "fake_secret",
+ "self_tvm_id": 42,
+ "roles_for_idm_slug": "some_slug"
+ }
+ }
+}
diff --git a/library/recipes/tvmtool/examples/ut_with_roles/roles/some_slug.json b/library/recipes/tvmtool/examples/ut_with_roles/roles/some_slug.json
new file mode 100644
index 0000000000..15d6ff7e13
--- /dev/null
+++ b/library/recipes/tvmtool/examples/ut_with_roles/roles/some_slug.json
@@ -0,0 +1,19 @@
+{
+ "revision": "foobar",
+ "born_date": 1642160000,
+ "tvm": {
+ "101": {
+ "/role/service/auth_type/with_user/access_type/write/handlers/routes/": [{}],
+ "/role/service/auth_type/without_user/access_type/read/handlers/blockedphones/": [{}]
+ },
+ "104": {
+ "/role/service/auth_type/without_user/access_type/read/handlers/routes/": [{}]
+ }
+ },
+ "user": {
+ "1120000000000001": {
+ "/role/user/access_type/read/handlers/all/": [{}],
+ "/role/user/access_type/write/handlers/all/": [{}]
+ }
+ }
+}
diff --git a/library/recipes/tvmtool/examples/ut_with_roles/test.py b/library/recipes/tvmtool/examples/ut_with_roles/test.py
new file mode 100644
index 0000000000..4a976bc228
--- /dev/null
+++ b/library/recipes/tvmtool/examples/ut_with_roles/test.py
@@ -0,0 +1,26 @@
+import os
+import os.path
+import requests
+
+TVMTOOL_PORT_FILE = "tvmtool.port"
+TVMTOOL_AUTHTOKEN_FILE = "tvmtool.authtoken"
+
+
+def _get_tvmtool_params():
+ port = int(open(TVMTOOL_PORT_FILE).read())
+ authtoken = open(TVMTOOL_AUTHTOKEN_FILE).read()
+ return port, authtoken
+
+
+def test_tvmtool():
+ assert os.path.isfile(TVMTOOL_PORT_FILE)
+ assert os.path.isfile(TVMTOOL_AUTHTOKEN_FILE)
+
+ port, authtoken = _get_tvmtool_params()
+
+ r = requests.get("http://localhost:%d/tvm/ping" % port)
+ assert r.text == 'OK'
+ assert r.status_code == 200
+
+ r = requests.get("http://localhost:%d/v2/roles?self=me" % port, headers={'Authorization': authtoken})
+ assert r.status_code == 200, r.text
diff --git a/library/recipes/tvmtool/examples/ut_with_tvmapi/test.py b/library/recipes/tvmtool/examples/ut_with_tvmapi/test.py
new file mode 100644
index 0000000000..f1c8a3fc35
--- /dev/null
+++ b/library/recipes/tvmtool/examples/ut_with_tvmapi/test.py
@@ -0,0 +1,49 @@
+import os
+import os.path
+
+import ticket_parser2 as tp2
+
+
+TVMAPI_PORT_FILE = "tvmapi.port"
+TVMTOOL_PORT_FILE = "tvmtool.port"
+TVMTOOL_AUTHTOKEN_FILE = "tvmtool.authtoken"
+
+
+def _get_tvmapi_port():
+ with open(TVMAPI_PORT_FILE) as f:
+ return int(f.read())
+
+
+def _get_tvmtool_params():
+ port = int(open(TVMTOOL_PORT_FILE).read())
+ authtoken = open(TVMTOOL_AUTHTOKEN_FILE).read()
+ return port, authtoken
+
+
+def test_tvmapi():
+ assert os.path.isfile(TVMAPI_PORT_FILE)
+ assert os.path.isfile(TVMTOOL_PORT_FILE)
+ assert os.path.isfile(TVMTOOL_AUTHTOKEN_FILE)
+
+ port = _get_tvmapi_port()
+
+ cs = tp2.TvmApiClientSettings(
+ self_client_id=1000501,
+ self_secret='bAicxJVa5uVY7MjDlapthw',
+ dsts={'my backend': 1000502},
+ enable_service_ticket_checking=True,
+ )
+ cs.__set_localhost(port)
+
+ ca = tp2.TvmClient(cs)
+ assert ca.status == tp2.TvmClientStatus.Ok
+
+ port, authtoken = _get_tvmtool_params()
+ ct = tp2.TvmClient(tp2.TvmToolClientSettings("me", auth_token=authtoken, port=port))
+ assert ct.status == tp2.TvmClientStatus.Ok
+
+ st = ca.check_service_ticket(ct.get_service_ticket_for(client_id=1000501))
+ assert st.src == 1000503
+
+ ct.stop()
+ ca.stop()
diff --git a/library/recipes/tvmtool/examples/ut_with_tvmapi/tvmtool.conf b/library/recipes/tvmtool/examples/ut_with_tvmapi/tvmtool.conf
new file mode 100644
index 0000000000..18332548ac
--- /dev/null
+++ b/library/recipes/tvmtool/examples/ut_with_tvmapi/tvmtool.conf
@@ -0,0 +1,17 @@
+{
+ "BbEnvType": 1,
+ "clients": {
+ "me": {
+ "secret": "S3TyTYVqjlbsflVEwxj33w",
+ "self_tvm_id": 1000503,
+ "dsts": {
+ "he": {
+ "dst_id": 1000504
+ },
+ "she": {
+ "dst_id": 1000501
+ }
+ }
+ }
+ }
+}
diff --git a/library/recipes/tvmtool/examples/ut_with_tvmapi_and_tirole/roles_dir/mapping.yaml b/library/recipes/tvmtool/examples/ut_with_tvmapi_and_tirole/roles_dir/mapping.yaml
new file mode 100644
index 0000000000..d2fcaead59
--- /dev/null
+++ b/library/recipes/tvmtool/examples/ut_with_tvmapi_and_tirole/roles_dir/mapping.yaml
@@ -0,0 +1,5 @@
+slugs:
+ some_slug_2:
+ tvmid:
+ - 1000502
+ - 1000503
diff --git a/library/recipes/tvmtool/examples/ut_with_tvmapi_and_tirole/roles_dir/some_slug_2.json b/library/recipes/tvmtool/examples/ut_with_tvmapi_and_tirole/roles_dir/some_slug_2.json
new file mode 100644
index 0000000000..27e38c5bc1
--- /dev/null
+++ b/library/recipes/tvmtool/examples/ut_with_tvmapi_and_tirole/roles_dir/some_slug_2.json
@@ -0,0 +1,14 @@
+{
+ "revision": "some_revision_2",
+ "born_date": 1642160002,
+ "tvm": {
+ "1000501": {
+ "/role/service/auth_type/without_user/access_type/read/handlers/routes/": [{}]
+ }
+ },
+ "user": {
+ "1120000000000001": {
+ "/role/user/access_type/write/handlers/all/": [{}]
+ }
+ }
+}
diff --git a/library/recipes/tvmtool/examples/ut_with_tvmapi_and_tirole/test.py b/library/recipes/tvmtool/examples/ut_with_tvmapi_and_tirole/test.py
new file mode 100644
index 0000000000..7700a45160
--- /dev/null
+++ b/library/recipes/tvmtool/examples/ut_with_tvmapi_and_tirole/test.py
@@ -0,0 +1,50 @@
+import os
+import os.path
+
+import tvmauth
+
+
+TVMAPI_PORT_FILE = "tvmapi.port"
+TVMTOOL_PORT_FILE = "tvmtool.port"
+TVMTOOL_AUTHTOKEN_FILE = "tvmtool.authtoken"
+
+
+def _get_tvmapi_port():
+ with open(TVMAPI_PORT_FILE) as f:
+ return int(f.read())
+
+
+def _get_tvmtool_params():
+ tvmtool_port = int(open(TVMTOOL_PORT_FILE).read())
+ authtoken = open(TVMTOOL_AUTHTOKEN_FILE).read()
+ return tvmtool_port, authtoken
+
+
+def test_tvmapi():
+ assert os.path.isfile(TVMAPI_PORT_FILE)
+ assert os.path.isfile(TVMTOOL_PORT_FILE)
+ assert os.path.isfile(TVMTOOL_AUTHTOKEN_FILE)
+
+ ca = tvmauth.TvmClient(
+ tvmauth.TvmApiClientSettings(
+ self_tvm_id=1000501,
+ self_secret='bAicxJVa5uVY7MjDlapthw',
+ disk_cache_dir="./",
+ dsts={'my backend': 1000502},
+ localhost_port=_get_tvmapi_port(),
+ )
+ )
+ assert ca.status == tvmauth.TvmClientStatus.Ok
+
+ tvmtool_port, authtoken = _get_tvmtool_params()
+ ct = tvmauth.TvmClient(tvmauth.TvmToolClientSettings("me", auth_token=authtoken, port=tvmtool_port))
+ assert ct.status == tvmauth.TvmClientStatus.Ok
+
+ st = ct.check_service_ticket(ca.get_service_ticket_for('my backend'))
+ assert st.src == 1000501
+
+ expected_role = '/role/service/auth_type/without_user/access_type/read/handlers/routes/'
+ assert expected_role in ct.get_roles().get_service_roles(st)
+
+ ct.stop()
+ ca.stop()
diff --git a/library/recipes/tvmtool/examples/ut_with_tvmapi_and_tirole/tvmtool.conf b/library/recipes/tvmtool/examples/ut_with_tvmapi_and_tirole/tvmtool.conf
new file mode 100644
index 0000000000..bb2827199b
--- /dev/null
+++ b/library/recipes/tvmtool/examples/ut_with_tvmapi_and_tirole/tvmtool.conf
@@ -0,0 +1,10 @@
+{
+ "BbEnvType": 1,
+ "clients": {
+ "me": {
+ "secret": "e5kL0vM3nP-nPf-388Hi6Q",
+ "roles_for_idm_slug": "some_slug_2",
+ "self_tvm_id": 1000502
+ }
+ }
+}
diff --git a/library/recipes/tvmtool/recipe.inc b/library/recipes/tvmtool/recipe.inc
new file mode 100644
index 0000000000..2e648e109d
--- /dev/null
+++ b/library/recipes/tvmtool/recipe.inc
@@ -0,0 +1,8 @@
+DEPENDS(
+ library/recipes/tvmtool
+ passport/infra/daemons/tvmtool/cmd
+)
+
+DATA(
+ arcadia/library/recipes/tvmtool
+)
diff --git a/library/recipes/tvmtool/recipe_with_default_cfg.inc b/library/recipes/tvmtool/recipe_with_default_cfg.inc
new file mode 100644
index 0000000000..dd979322b6
--- /dev/null
+++ b/library/recipes/tvmtool/recipe_with_default_cfg.inc
@@ -0,0 +1,5 @@
+INCLUDE(${ARCADIA_ROOT}/library/recipes/tvmtool/recipe.inc)
+
+USE_RECIPE(
+ library/recipes/tvmtool/tvmtool library/recipes/tvmtool/tvmtool.default.conf
+)
diff --git a/library/recipes/tvmtool/tvmtool.default.conf b/library/recipes/tvmtool/tvmtool.default.conf
new file mode 100644
index 0000000000..1de49f9d1c
--- /dev/null
+++ b/library/recipes/tvmtool/tvmtool.default.conf
@@ -0,0 +1,17 @@
+{
+ "BbEnvType": 1,
+ "clients": {
+ "me": {
+ "secret": "fake_secret",
+ "self_tvm_id": 42,
+ "dsts": {
+ "he": {
+ "dst_id": 100500
+ },
+ "she": {
+ "dst_id": 100501
+ }
+ }
+ }
+ }
+}