From 3a9fb2befeeae836971dc34464722c9fb0c9210d Mon Sep 17 00:00:00 2001 From: I519866 Date: Thu, 16 Oct 2025 15:03:07 +0800 Subject: [PATCH 01/20] DIARCHERS-610: generate batch token to connect vault --- src/api/handlers/job_api.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/api/handlers/job_api.py b/src/api/handlers/job_api.py index b07ab7f4..21cb1ea9 100644 --- a/src/api/handlers/job_api.py +++ b/src/api/handlers/job_api.py @@ -58,6 +58,38 @@ def get_token_by_app_role(app_role_url, role_id, secret_id): abort(400, err_msg) +def generate_batch_token(url, temp_token, policies=None, ttl="1h"): + """ + Generate a batch token using AppRole credentials. + :param url: The Vault endpoint to create the batch token. + :param temp_token: A service token generated when logging in with AppRole. + :param policies: List of policies to attach to the batch token. + :param ttl: Time-to-live for the batch token. + :return: The generated batch token. + """ + + if policies is None: + policies = ["default"] + + batch_payload = { + "type": "batch", + "policies": policies, + "ttl": ttl + } + + for i in range(0, 10): + res = requests.post(url=url, data=batch_payload, headers={"X-Vault-Token": temp_token}, verify=False) + if res.status_code == 200: + json_res = json.loads(res.content) + token = json_res['auth']['client_token'] + return token + time.sleep(5) + msg = "Getting batch token from Vault error even tried 10 times, url is {}, API response is {}:{}".format( + url, res.status_code, res.text) + logger.info(msg) + return None + + def get_value_from_vault(url, token, secret_key, verify): for i in range(0, 10): response = requests.get(url=url, headers={'X-Vault-Token': token}, verify=verify) @@ -327,6 +359,10 @@ def get_secret(name): elif validate_res == 'appRole': app_role_url = result[0] + '/v1/' + namespace + '/auth/approle/login' if namespace else result[0] + '/v1/auth/approle/login' token = get_token_by_app_role(app_role_url, role_id, secret_id) + batch_token_url = result[0] + '/v1/' + namespace + '/auth/token/create' if namespace else result[0] + '/v1/auth/token/create' + batch_token = generate_batch_token(batch_token_url, token) + if batch_token: + token = batch_token else: abort(400, "Validate way is '%s' ! result is '%s' " % (validate_res, result)) From e0c0aef00027bd4ad533bacdf4ba946fa0f23781 Mon Sep 17 00:00:00 2001 From: I519866 Date: Thu, 16 Oct 2025 16:48:38 +0800 Subject: [PATCH 02/20] add exception handle --- src/api/handlers/job_api.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/api/handlers/job_api.py b/src/api/handlers/job_api.py index 21cb1ea9..e1396fdf 100644 --- a/src/api/handlers/job_api.py +++ b/src/api/handlers/job_api.py @@ -76,18 +76,22 @@ def generate_batch_token(url, temp_token, policies=None, ttl="1h"): "policies": policies, "ttl": ttl } + try: + for i in range(0, 10): + res = requests.post(url=url, data=batch_payload, headers={"X-Vault-Token": temp_token}, verify=False) + if res.status_code == 200: + json_res = json.loads(res.content) + token = json_res['auth']['client_token'] + return token + time.sleep(5) + msg = "Getting batch token from Vault failed even tried 10 times, url is {}, API response is {}:{}".format( + url, res.status_code, res.text) + logger.info(msg) + return None + except Exception as e: + logger.info("Exception when getting batch token from Vault: {}".format(e)) + return None - for i in range(0, 10): - res = requests.post(url=url, data=batch_payload, headers={"X-Vault-Token": temp_token}, verify=False) - if res.status_code == 200: - json_res = json.loads(res.content) - token = json_res['auth']['client_token'] - return token - time.sleep(5) - msg = "Getting batch token from Vault error even tried 10 times, url is {}, API response is {}:{}".format( - url, res.status_code, res.text) - logger.info(msg) - return None def get_value_from_vault(url, token, secret_key, verify): From 6380fe3a8250561700a89e40c74371db6d368fe6 Mon Sep 17 00:00:00 2001 From: Wei Liu <51599940+liuwei08@users.noreply.github.com> Date: Wed, 29 Oct 2025 15:37:10 +0800 Subject: [PATCH 03/20] Fix pylint disable comments formatting --- src/api/handlers/job_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/handlers/job_api.py b/src/api/handlers/job_api.py index e1396fdf..71abbed5 100644 --- a/src/api/handlers/job_api.py +++ b/src/api/handlers/job_api.py @@ -1,4 +1,4 @@ -#pylint: disable=too-many-lines,too-few-public-methods,too-many-locals,too-many-statements,too-many-branches +#pylint: disable=too-many-lines,too-few-public-methods,too-many-locals,too-many-statements,too-many-branches import os import json import time From 41dcd2f0da4e63b4da2b78b136e0e8cb41468ba2 Mon Sep 17 00:00:00 2001 From: Wei Liu <51599940+liuwei08@users.noreply.github.com> Date: Wed, 29 Oct 2025 15:37:30 +0800 Subject: [PATCH 04/20] Remove duplicate pylint disable comment --- src/api/handlers/job_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/handlers/job_api.py b/src/api/handlers/job_api.py index 71abbed5..e1396fdf 100644 --- a/src/api/handlers/job_api.py +++ b/src/api/handlers/job_api.py @@ -1,4 +1,4 @@ -#pylint: disable=too-many-lines,too-few-public-methods,too-many-locals,too-many-statements,too-many-branches +#pylint: disable=too-many-lines,too-few-public-methods,too-many-locals,too-many-statements,too-many-branches import os import json import time From 435c9e11134a38de846699f3c793d740e0c2f2ea Mon Sep 17 00:00:00 2001 From: Wei Liu <51599940+liuwei08@users.noreply.github.com> Date: Fri, 31 Oct 2025 10:56:56 +0800 Subject: [PATCH 05/20] Update job_api.py --- src/api/handlers/job_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/handlers/job_api.py b/src/api/handlers/job_api.py index e1396fdf..71abbed5 100644 --- a/src/api/handlers/job_api.py +++ b/src/api/handlers/job_api.py @@ -1,4 +1,4 @@ -#pylint: disable=too-many-lines,too-few-public-methods,too-many-locals,too-many-statements,too-many-branches +#pylint: disable=too-many-lines,too-few-public-methods,too-many-locals,too-many-statements,too-many-branches import os import json import time From a47b8cd04ba96f0dddf4073b53d78af10f64fbd4 Mon Sep 17 00:00:00 2001 From: I519866 Date: Thu, 6 Nov 2025 11:38:49 +0800 Subject: [PATCH 06/20] chore: update --- src/api/handlers/job_api.py | 146 ++++++++++++++++++++---------------- 1 file changed, 83 insertions(+), 63 deletions(-) diff --git a/src/api/handlers/job_api.py b/src/api/handlers/job_api.py index 71abbed5..fd0e4651 100644 --- a/src/api/handlers/job_api.py +++ b/src/api/handlers/job_api.py @@ -43,70 +43,91 @@ def delete_file(path): except Exception as error: logger.warning("Failed to delete file: %s", error) - -def get_token_by_app_role(app_role_url, role_id, secret_id): - app_role = {'role_id': role_id, 'secret_id': secret_id} - json_data = json.dumps(app_role) - for i in range(0, 10): - res = requests.post(url=app_role_url, data=json_data, verify=False) +class Vault(): + def __init__(self, base_url, namespace, role_id, secret_id): + self.base_url = base_url + self.namespace = namespace + self.role_id = role_id + self.secret_id = secret_id + self.token = None + + def get_token_by_app_role(self): + if self.token and self.is_token_valid(self.token): + return self.token + app_role = {'role_id': self.role_id, 'secret_id': self.secret_id} + app_role_url = self.base_url + '/v1/' + self.namespace + '/auth/approle/login' if self.namespace else self.base_url + '/v1/auth/approle/login' + json_data = json.dumps(app_role) + for i in range(0, 10): + res = requests.post(url=app_role_url, data=json_data, verify=False) if res.status_code == 200: json_res = json.loads(res.content) - token = json_res['auth']['client_token'] - return token + self.token = json_res['auth']['client_token'] + return self.token time.sleep(5) - err_msg = "Getting token from Vault error even tried 10 times, url is {}, API response is {}:{}".format(app_role_url, res.status_code, res.text) - abort(400, err_msg) - - -def generate_batch_token(url, temp_token, policies=None, ttl="1h"): - """ - Generate a batch token using AppRole credentials. - :param url: The Vault endpoint to create the batch token. - :param temp_token: A service token generated when logging in with AppRole. - :param policies: List of policies to attach to the batch token. - :param ttl: Time-to-live for the batch token. - :return: The generated batch token. - """ - - if policies is None: - policies = ["default"] - - batch_payload = { - "type": "batch", - "policies": policies, - "ttl": ttl - } - try: - for i in range(0, 10): - res = requests.post(url=url, data=batch_payload, headers={"X-Vault-Token": temp_token}, verify=False) - if res.status_code == 200: - json_res = json.loads(res.content) - token = json_res['auth']['client_token'] - return token - time.sleep(5) - msg = "Getting batch token from Vault failed even tried 10 times, url is {}, API response is {}:{}".format( - url, res.status_code, res.text) - logger.info(msg) - return None - except Exception as e: - logger.info("Exception when getting batch token from Vault: {}".format(e)) - return None - + err_msg = "Getting token from Vault error even tried 10 times, url is {}, API response is {}:{}".format(app_role_url, res.status_code, res.text) + abort(400, err_msg) + def is_token_valid(self, token): + """Return True if the provided token is valid according to Vault's lookup-self endpoint.""" + if not token: + return False + try: + lookup_url = self.base_url + 'v1/' + self.namespace + '/auth/token/lookup-self' + res = requests.get(url=lookup_url, headers={"X-Vault-Token": token}, verify=False) + if res.status_code == 200: + return True + return False + except Exception as e: + self.logger.debug("Token validation failed: %s", str(e)) + return False + + def generate_batch_token(self, service_token, policies=None, ttl="1h"): + """ + Generate a batch token using AppRole credentials. + :param service_token: A service token generated when logging in with AppRole. + :param policies: List of policies to attach to the batch token. + :param ttl: Time-to-live for the batch token. + :return: The generated batch token. + """ + + if policies is None: + policies = ["default"] + + batch_payload = { + "type": "batch", + "policies": policies, + "ttl": ttl + } + url = self.base_url + '/v1/' + self.namespace + '/auth/token/create' if self.namespace else self.base_url + '/v1/auth/token/create' + try: + for i in range(0, 10): + res = requests.post(url=url, data=batch_payload, headers={"X-Vault-Token": service_token}, verify=False) + if res.status_code == 200: + json_res = json.loads(res.content) + token = json_res['auth']['client_token'] + return token + time.sleep(5) + msg = "Getting batch token from Vault failed even tried 10 times, url is {}, API response is {}:{}".format( + url, res.status_code, res.text) + logger.info(msg) + return None + except Exception as e: + logger.info("Exception when getting batch token from Vault: {}".format(e)) + return None -def get_value_from_vault(url, token, secret_key, verify): - for i in range(0, 10): - response = requests.get(url=url, headers={'X-Vault-Token': token}, verify=verify) - if response.status_code == 200: - json_res = json.loads(response.content) - if json_res['data'].get('data') and isinstance(json_res['data'].get('data'), dict): - value = json_res['data'].get('data').get(secret_key) - else: - value = json_res['data'].get(secret_key) - return value - time.sleep(5) - err_msg = "Getting value from Vault error even tried 10 times, url is {}, API response is {}:{}".format(url, response.status_code, response.text) - abort(400, err_msg) + def get_value_from_vault(url, token, secret_key, verify): + for i in range(0, 10): + response = requests.get(url=url, headers={'X-Vault-Token': token}, verify=verify) + if response.status_code == 200: + json_res = json.loads(response.content) + if json_res['data'].get('data') and isinstance(json_res['data'].get('data'), dict): + value = json_res['data'].get('data').get(secret_key) + else: + value = json_res['data'].get(secret_key) + return value + time.sleep(5) + err_msg = "Getting value from Vault error even tried 10 times, url is {}, API response is {}:{}".format(url, response.status_code, response.text) + abort(400, err_msg) @api.route("/api/job/job", doc=False) @@ -361,10 +382,9 @@ def get_secret(name): if validate_res == 'token': logger.info('validate way is token') elif validate_res == 'appRole': - app_role_url = result[0] + '/v1/' + namespace + '/auth/approle/login' if namespace else result[0] + '/v1/auth/approle/login' - token = get_token_by_app_role(app_role_url, role_id, secret_id) - batch_token_url = result[0] + '/v1/' + namespace + '/auth/token/create' if namespace else result[0] + '/v1/auth/token/create' - batch_token = generate_batch_token(batch_token_url, token) + vault = Vault(url, namespace, role_id, secret_id) + token = vault.get_token_by_app_role() + batch_token = vault.generate_batch_token(token) if batch_token: token = batch_token else: From a4ed2a396b65858cdf55d544a4d8d455baf9f168 Mon Sep 17 00:00:00 2001 From: I519866 Date: Thu, 6 Nov 2025 15:53:48 +0800 Subject: [PATCH 07/20] update --- src/api/handlers/job_api.py | 58 ++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/src/api/handlers/job_api.py b/src/api/handlers/job_api.py index fd0e4651..5b02879e 100644 --- a/src/api/handlers/job_api.py +++ b/src/api/handlers/job_api.py @@ -50,9 +50,11 @@ def __init__(self, base_url, namespace, role_id, secret_id): self.role_id = role_id self.secret_id = secret_id self.token = None + self.policies = None def get_token_by_app_role(self): - if self.token and self.is_token_valid(self.token): + self.policies = self.get_policies(self.token) + if self.token and self.policies: return self.token app_role = {'role_id': self.role_id, 'secret_id': self.secret_id} app_role_url = self.base_url + '/v1/' + self.namespace + '/auth/approle/login' if self.namespace else self.base_url + '/v1/auth/approle/login' @@ -62,26 +64,29 @@ def get_token_by_app_role(self): if res.status_code == 200: json_res = json.loads(res.content) self.token = json_res['auth']['client_token'] + self.policies = self.get_policies(self.token) return self.token time.sleep(5) err_msg = "Getting token from Vault error even tried 10 times, url is {}, API response is {}:{}".format(app_role_url, res.status_code, res.text) abort(400, err_msg) - def is_token_valid(self, token): - """Return True if the provided token is valid according to Vault's lookup-self endpoint.""" + def get_policies(self, token): + """Return the policies associated with the provided token.""" if not token: - return False + return None try: - lookup_url = self.base_url + 'v1/' + self.namespace + '/auth/token/lookup-self' + lookup_url = self.base_url + 'v1/' + self.namespace + '/auth/token/lookup-self' if self.namespace else self.base_url + 'v1/auth/token/lookup-self' res = requests.get(url=lookup_url, headers={"X-Vault-Token": token}, verify=False) if res.status_code == 200: - return True - return False + json_res = json.loads(res.content) + policies = json_res['data']['policies'] + return policies + return None except Exception as e: self.logger.debug("Token validation failed: %s", str(e)) - return False + return None - def generate_batch_token(self, service_token, policies=None, ttl="1h"): + def generate_batch_token(self, service_token, ttl="1h"): """ Generate a batch token using AppRole credentials. :param service_token: A service token generated when logging in with AppRole. @@ -89,13 +94,12 @@ def generate_batch_token(self, service_token, policies=None, ttl="1h"): :param ttl: Time-to-live for the batch token. :return: The generated batch token. """ - - if policies is None: - policies = ["default"] + if self.policies is None: + self.policies = self.get_policies(service_token) batch_payload = { "type": "batch", - "policies": policies, + "policies": self.policies or ['default'], "ttl": ttl } url = self.base_url + '/v1/' + self.namespace + '/auth/token/create' if self.namespace else self.base_url + '/v1/auth/token/create' @@ -115,7 +119,19 @@ def generate_batch_token(self, service_token, policies=None, ttl="1h"): logger.info("Exception when getting batch token from Vault: {}".format(e)) return None - def get_value_from_vault(url, token, secret_key, verify): + def _get_api_url(self): + url = self.base_url + if not self.namespace: + self.namespace = '' + if self.version == 'v1': + url += '/v1/' + self.namespace + '/' + self.secret_path if self.namespace else '/v1/' + self.secret_path + elif self.version == 'v2': + paths = self.secret_path.split('/') + url += '/v1/' + self.namespace + '/' + paths[0] + '/data/' + '/'.join(paths[1:]) if self.namespace else '/v1/' + paths[0] + '/data/' + '/'.join(paths[1:]) + return url + + def get_value_from_vault(self, token, secret_key, verify): + url = self._get_api_url() for i in range(0, 10): response = requests.get(url=url, headers={'X-Vault-Token': token}, verify=verify) if response.status_code == 200: @@ -370,19 +386,13 @@ def get_secret(name): abort(400, "Cannot get Vault '%s' in project '%s' " % (vault_name, data['project']['id'])) url, version, token, ca, namespace, role_id, secret_id = result[0], result[1], result[2], result[3], result[4], result[5], result[6] - if not namespace: - namespace = '' - if version == 'v1': - url += '/v1/' + namespace + '/' + secret_path if namespace else '/v1/' + secret_path - elif version == 'v2': - paths = secret_path.split('/') - url += '/v1/' + namespace + '/' + paths[0] + '/data/' + '/'.join(paths[1:]) if namespace else '/v1/' + paths[0] + '/data/' + '/'.join(paths[1:]) # choose validate way validate_res = get_auth_type(result) + vault = Vault(url, namespace, role_id, secret_id) if validate_res == 'token': logger.info('validate way is token') elif validate_res == 'appRole': - vault = Vault(url, namespace, role_id, secret_id) + logger.info('validate way is appRole') token = vault.get_token_by_app_role() batch_token = vault.generate_batch_token(token) if batch_token: @@ -391,12 +401,12 @@ def get_secret(name): abort(400, "Validate way is '%s' ! result is '%s' " % (validate_res, result)) if not ca: - return get_value_from_vault(url, token, secret_key, False) + return vault.get_value_from_vault(token, secret_key, False) else: with tempfile.NamedTemporaryFile(delete=False) as f: f.write(ca) f.flush() # ensure all data written - return get_value_from_vault(url, token, secret_key, f.name) + return vault.get_value_from_vault(token, secret_key, f.name) else: if is_fork: abort(400, 'Access to secret %s is not allowed from a fork' % name) From 79ef7193771dfee2b04a6dd3f5e54aaf9f5ab35d Mon Sep 17 00:00:00 2001 From: I519866 Date: Fri, 14 Nov 2025 09:47:22 +0800 Subject: [PATCH 08/20] update --- src/api/handlers/job_api.py | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/api/handlers/job_api.py b/src/api/handlers/job_api.py index 5b02879e..e9ebc18b 100644 --- a/src/api/handlers/job_api.py +++ b/src/api/handlers/job_api.py @@ -44,9 +44,10 @@ def delete_file(path): logger.warning("Failed to delete file: %s", error) class Vault(): - def __init__(self, base_url, namespace, role_id, secret_id): + def __init__(self, base_url, namespace, version, role_id, secret_id): self.base_url = base_url self.namespace = namespace + self.version = version self.role_id = role_id self.secret_id = secret_id self.token = None @@ -61,12 +62,12 @@ def get_token_by_app_role(self): json_data = json.dumps(app_role) for i in range(0, 10): res = requests.post(url=app_role_url, data=json_data, verify=False) - if res.status_code == 200: - json_res = json.loads(res.content) - self.token = json_res['auth']['client_token'] - self.policies = self.get_policies(self.token) - return self.token - time.sleep(5) + if res.status_code == 200: + json_res = json.loads(res.content) + self.token = json_res['auth']['client_token'] + self.policies = self.get_policies(self.token) + return self.token + time.sleep(5) err_msg = "Getting token from Vault error even tried 10 times, url is {}, API response is {}:{}".format(app_role_url, res.status_code, res.text) abort(400, err_msg) @@ -83,7 +84,7 @@ def get_policies(self, token): return policies return None except Exception as e: - self.logger.debug("Token validation failed: %s", str(e)) + logger.debug("Token validation failed: %s", str(e)) return None def generate_batch_token(self, service_token, ttl="1h"): @@ -119,19 +120,19 @@ def generate_batch_token(self, service_token, ttl="1h"): logger.info("Exception when getting batch token from Vault: {}".format(e)) return None - def _get_api_url(self): + def _get_api_url(self, secret_path): url = self.base_url if not self.namespace: self.namespace = '' if self.version == 'v1': - url += '/v1/' + self.namespace + '/' + self.secret_path if self.namespace else '/v1/' + self.secret_path + url += '/v1/' + self.namespace + '/' + secret_path if self.namespace else '/v1/' + secret_path elif self.version == 'v2': - paths = self.secret_path.split('/') + paths = secret_path.split('/') url += '/v1/' + self.namespace + '/' + paths[0] + '/data/' + '/'.join(paths[1:]) if self.namespace else '/v1/' + paths[0] + '/data/' + '/'.join(paths[1:]) return url - def get_value_from_vault(self, token, secret_key, verify): - url = self._get_api_url() + def get_value_from_vault(self, token, secret_path, secret_key, verify): + url = self._get_api_url(secret_path) for i in range(0, 10): response = requests.get(url=url, headers={'X-Vault-Token': token}, verify=verify) if response.status_code == 200: @@ -388,7 +389,7 @@ def get_secret(name): url, version, token, ca, namespace, role_id, secret_id = result[0], result[1], result[2], result[3], result[4], result[5], result[6] # choose validate way validate_res = get_auth_type(result) - vault = Vault(url, namespace, role_id, secret_id) + vault = Vault(url, namespace, version, role_id, secret_id) if validate_res == 'token': logger.info('validate way is token') elif validate_res == 'appRole': @@ -401,12 +402,12 @@ def get_secret(name): abort(400, "Validate way is '%s' ! result is '%s' " % (validate_res, result)) if not ca: - return vault.get_value_from_vault(token, secret_key, False) + return vault.get_value_from_vault(token, secret_path, secret_key, False) else: with tempfile.NamedTemporaryFile(delete=False) as f: f.write(ca) f.flush() # ensure all data written - return vault.get_value_from_vault(token, secret_key, f.name) + return vault.get_value_from_vault(token, secret_path, secret_key, f.name) else: if is_fork: abort(400, 'Access to secret %s is not allowed from a fork' % name) From b509499674a8178e1467ea0c1fee0496a4a4c723 Mon Sep 17 00:00:00 2001 From: I519866 Date: Fri, 14 Nov 2025 11:46:59 +0800 Subject: [PATCH 09/20] update --- src/api/handlers/job_api.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/api/handlers/job_api.py b/src/api/handlers/job_api.py index e9ebc18b..fe80f8b2 100644 --- a/src/api/handlers/job_api.py +++ b/src/api/handlers/job_api.py @@ -52,7 +52,7 @@ def __init__(self, base_url, namespace, version, role_id, secret_id): self.secret_id = secret_id self.token = None self.policies = None - + def get_token_by_app_role(self): self.policies = self.get_policies(self.token) if self.token and self.policies: @@ -76,7 +76,7 @@ def get_policies(self, token): if not token: return None try: - lookup_url = self.base_url + 'v1/' + self.namespace + '/auth/token/lookup-self' if self.namespace else self.base_url + 'v1/auth/token/lookup-self' + lookup_url = self.base_url + '/v1/' + self.namespace + '/auth/token/lookup-self' if self.namespace else self.base_url + 'v1/auth/token/lookup-self' res = requests.get(url=lookup_url, headers={"X-Vault-Token": token}, verify=False) if res.status_code == 200: json_res = json.loads(res.content) @@ -91,12 +91,13 @@ def generate_batch_token(self, service_token, ttl="1h"): """ Generate a batch token using AppRole credentials. :param service_token: A service token generated when logging in with AppRole. - :param policies: List of policies to attach to the batch token. :param ttl: Time-to-live for the batch token. :return: The generated batch token. """ if self.policies is None: self.policies = self.get_policies(service_token) + if 'token-creator' in self.policies: + self.policies.remove('token-creator') batch_payload = { "type": "batch", @@ -106,7 +107,7 @@ def generate_batch_token(self, service_token, ttl="1h"): url = self.base_url + '/v1/' + self.namespace + '/auth/token/create' if self.namespace else self.base_url + '/v1/auth/token/create' try: for i in range(0, 10): - res = requests.post(url=url, data=batch_payload, headers={"X-Vault-Token": service_token}, verify=False) + res = requests.post(url=url, json=batch_payload, headers={"X-Vault-Token": service_token}, verify=False) if res.status_code == 200: json_res = json.loads(res.content) token = json_res['auth']['client_token'] From 55f2dbb5b0ea40d82deafb8bab0ea5ae32cdfeae Mon Sep 17 00:00:00 2001 From: I519866 Date: Fri, 14 Nov 2025 13:22:05 +0800 Subject: [PATCH 10/20] add logs to debug --- src/api/handlers/job_api.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/api/handlers/job_api.py b/src/api/handlers/job_api.py index fe80f8b2..d84d325b 100644 --- a/src/api/handlers/job_api.py +++ b/src/api/handlers/job_api.py @@ -69,7 +69,8 @@ def get_token_by_app_role(self): return self.token time.sleep(5) err_msg = "Getting token from Vault error even tried 10 times, url is {}, API response is {}:{}".format(app_role_url, res.status_code, res.text) - abort(400, err_msg) + raise Exception(err_msg) + # abort(400, err_msg) def get_policies(self, token): """Return the policies associated with the provided token.""" @@ -116,9 +117,11 @@ def generate_batch_token(self, service_token, ttl="1h"): msg = "Getting batch token from Vault failed even tried 10 times, url is {}, API response is {}:{}".format( url, res.status_code, res.text) logger.info(msg) + raise Exception(msg) return None except Exception as e: logger.info("Exception when getting batch token from Vault: {}".format(e)) + raise e return None def _get_api_url(self, secret_path): @@ -145,7 +148,8 @@ def get_value_from_vault(self, token, secret_path, secret_key, verify): return value time.sleep(5) err_msg = "Getting value from Vault error even tried 10 times, url is {}, API response is {}:{}".format(url, response.status_code, response.text) - abort(400, err_msg) + # abort(400, err_msg) + raise Exception(err_msg) @api.route("/api/job/job", doc=False) @@ -390,19 +394,24 @@ def get_secret(name): url, version, token, ca, namespace, role_id, secret_id = result[0], result[1], result[2], result[3], result[4], result[5], result[6] # choose validate way validate_res = get_auth_type(result) + logger.info("start to get secret from vault") vault = Vault(url, namespace, version, role_id, secret_id) if validate_res == 'token': logger.info('validate way is token') elif validate_res == 'appRole': logger.info('validate way is appRole') token = vault.get_token_by_app_role() + logger.info('get_token_by_app_role %s' % token) batch_token = vault.generate_batch_token(token) + logger.info('generate_batch_token %s' % batch_token) if batch_token: token = batch_token else: abort(400, "Validate way is '%s' ! result is '%s' " % (validate_res, result)) if not ca: + logger.info('get_value_from_vault %s %s %s' % (token, secret_path, secret_key)) + logger.info('get_value_from_vault %s' % vault.get_value_from_vault) return vault.get_value_from_vault(token, secret_path, secret_key, False) else: with tempfile.NamedTemporaryFile(delete=False) as f: From 532b6f2fa1dab45d59df0706e67d580fee36db78 Mon Sep 17 00:00:00 2001 From: I519866 Date: Fri, 14 Nov 2025 13:24:05 +0800 Subject: [PATCH 11/20] update --- src/api/handlers/job_api.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/api/handlers/job_api.py b/src/api/handlers/job_api.py index d84d325b..169c826c 100644 --- a/src/api/handlers/job_api.py +++ b/src/api/handlers/job_api.py @@ -389,7 +389,8 @@ def get_secret(name): """, [vault_name, data['project']['id']]) if not result: - abort(400, "Cannot get Vault '%s' in project '%s' " % (vault_name, data['project']['id'])) + raise Exception("Cannot get Vault '%s' in project '%s' " % (vault_name, data['project']['id'])) + # abort(400, "Cannot get Vault '%s' in project '%s' " % (vault_name, data['project']['id'])) url, version, token, ca, namespace, role_id, secret_id = result[0], result[1], result[2], result[3], result[4], result[5], result[6] # choose validate way From f79ffcd607f57902115f6b1def6eaf4ff9429ead Mon Sep 17 00:00:00 2001 From: I519866 Date: Fri, 14 Nov 2025 17:28:09 +0800 Subject: [PATCH 12/20] update --- src/api/handlers/job_api.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/api/handlers/job_api.py b/src/api/handlers/job_api.py index 169c826c..2168c2d4 100644 --- a/src/api/handlers/job_api.py +++ b/src/api/handlers/job_api.py @@ -61,7 +61,7 @@ def get_token_by_app_role(self): app_role_url = self.base_url + '/v1/' + self.namespace + '/auth/approle/login' if self.namespace else self.base_url + '/v1/auth/approle/login' json_data = json.dumps(app_role) for i in range(0, 10): - res = requests.post(url=app_role_url, data=json_data, verify=False) + res = requests.post(url=app_role_url, data=json_data, verify=False, timeout=30) if res.status_code == 200: json_res = json.loads(res.content) self.token = json_res['auth']['client_token'] @@ -77,8 +77,8 @@ def get_policies(self, token): if not token: return None try: - lookup_url = self.base_url + '/v1/' + self.namespace + '/auth/token/lookup-self' if self.namespace else self.base_url + 'v1/auth/token/lookup-self' - res = requests.get(url=lookup_url, headers={"X-Vault-Token": token}, verify=False) + lookup_url = self.base_url + '/v1/' + self.namespace + '/auth/token/lookup-self' if self.namespace else self.base_url + '/v1/auth/token/lookup-self' + res = requests.get(url=lookup_url, headers={"X-Vault-Token": token}, verify=False, timeout=30) if res.status_code == 200: json_res = json.loads(res.content) policies = json_res['data']['policies'] @@ -108,7 +108,7 @@ def generate_batch_token(self, service_token, ttl="1h"): url = self.base_url + '/v1/' + self.namespace + '/auth/token/create' if self.namespace else self.base_url + '/v1/auth/token/create' try: for i in range(0, 10): - res = requests.post(url=url, json=batch_payload, headers={"X-Vault-Token": service_token}, verify=False) + res = requests.post(url=url, json=batch_payload, headers={"X-Vault-Token": service_token}, verify=False, timeout=30) if res.status_code == 200: json_res = json.loads(res.content) token = json_res['auth']['client_token'] @@ -138,7 +138,7 @@ def _get_api_url(self, secret_path): def get_value_from_vault(self, token, secret_path, secret_key, verify): url = self._get_api_url(secret_path) for i in range(0, 10): - response = requests.get(url=url, headers={'X-Vault-Token': token}, verify=verify) + response = requests.get(url=url, headers={'X-Vault-Token': token}, verify=verify, timeout=30) if response.status_code == 200: json_res = json.loads(response.content) if json_res['data'].get('data') and isinstance(json_res['data'].get('data'), dict): From 9e56475e9338b25d66f8c8e11710aebd78343962 Mon Sep 17 00:00:00 2001 From: I519866 Date: Fri, 14 Nov 2025 17:51:57 +0800 Subject: [PATCH 13/20] update --- src/api/handlers/job_api.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/api/handlers/job_api.py b/src/api/handlers/job_api.py index 2168c2d4..b3d34d99 100644 --- a/src/api/handlers/job_api.py +++ b/src/api/handlers/job_api.py @@ -117,11 +117,9 @@ def generate_batch_token(self, service_token, ttl="1h"): msg = "Getting batch token from Vault failed even tried 10 times, url is {}, API response is {}:{}".format( url, res.status_code, res.text) logger.info(msg) - raise Exception(msg) return None except Exception as e: logger.info("Exception when getting batch token from Vault: {}".format(e)) - raise e return None def _get_api_url(self, secret_path): @@ -412,7 +410,7 @@ def get_secret(name): if not ca: logger.info('get_value_from_vault %s %s %s' % (token, secret_path, secret_key)) - logger.info('get_value_from_vault %s' % vault.get_value_from_vault) + logger.info('get_value_from_vault %s' % vault.get_value_from_vault(token, secret_path, secret_key, False)) return vault.get_value_from_vault(token, secret_path, secret_key, False) else: with tempfile.NamedTemporaryFile(delete=False) as f: From 33a53e1019a5f1622f5cba559c86cbe1d83ec468 Mon Sep 17 00:00:00 2001 From: I519866 Date: Mon, 17 Nov 2025 10:36:01 +0800 Subject: [PATCH 14/20] update --- src/api/handlers/job_api.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/api/handlers/job_api.py b/src/api/handlers/job_api.py index b3d34d99..20411dea 100644 --- a/src/api/handlers/job_api.py +++ b/src/api/handlers/job_api.py @@ -61,7 +61,7 @@ def get_token_by_app_role(self): app_role_url = self.base_url + '/v1/' + self.namespace + '/auth/approle/login' if self.namespace else self.base_url + '/v1/auth/approle/login' json_data = json.dumps(app_role) for i in range(0, 10): - res = requests.post(url=app_role_url, data=json_data, verify=False, timeout=30) + res = requests.post(url=app_role_url, data=json_data, verify=False) if res.status_code == 200: json_res = json.loads(res.content) self.token = json_res['auth']['client_token'] @@ -77,8 +77,8 @@ def get_policies(self, token): if not token: return None try: - lookup_url = self.base_url + '/v1/' + self.namespace + '/auth/token/lookup-self' if self.namespace else self.base_url + '/v1/auth/token/lookup-self' - res = requests.get(url=lookup_url, headers={"X-Vault-Token": token}, verify=False, timeout=30) + lookup_url = self.base_url + '/v1/' + self.namespace + '/auth/token/lookup-self' if self.namespace else self.base_url + 'v1/auth/token/lookup-self' + res = requests.get(url=lookup_url, headers={"X-Vault-Token": token}, verify=False) if res.status_code == 200: json_res = json.loads(res.content) policies = json_res['data']['policies'] @@ -108,7 +108,7 @@ def generate_batch_token(self, service_token, ttl="1h"): url = self.base_url + '/v1/' + self.namespace + '/auth/token/create' if self.namespace else self.base_url + '/v1/auth/token/create' try: for i in range(0, 10): - res = requests.post(url=url, json=batch_payload, headers={"X-Vault-Token": service_token}, verify=False, timeout=30) + res = requests.post(url=url, json=batch_payload, headers={"X-Vault-Token": service_token}, verify=False) if res.status_code == 200: json_res = json.loads(res.content) token = json_res['auth']['client_token'] @@ -136,7 +136,7 @@ def _get_api_url(self, secret_path): def get_value_from_vault(self, token, secret_path, secret_key, verify): url = self._get_api_url(secret_path) for i in range(0, 10): - response = requests.get(url=url, headers={'X-Vault-Token': token}, verify=verify, timeout=30) + response = requests.get(url=url, headers={'X-Vault-Token': token}, verify=verify) if response.status_code == 200: json_res = json.loads(response.content) if json_res['data'].get('data') and isinstance(json_res['data'].get('data'), dict): @@ -410,7 +410,6 @@ def get_secret(name): if not ca: logger.info('get_value_from_vault %s %s %s' % (token, secret_path, secret_key)) - logger.info('get_value_from_vault %s' % vault.get_value_from_vault(token, secret_path, secret_key, False)) return vault.get_value_from_vault(token, secret_path, secret_key, False) else: with tempfile.NamedTemporaryFile(delete=False) as f: From 75288bc378f27927b86275190c79b001b20ebb54 Mon Sep 17 00:00:00 2001 From: I519866 Date: Mon, 17 Nov 2025 16:54:29 +0800 Subject: [PATCH 15/20] update --- src/api/handlers/job_api.py | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/api/handlers/job_api.py b/src/api/handlers/job_api.py index 20411dea..72d1bb9c 100644 --- a/src/api/handlers/job_api.py +++ b/src/api/handlers/job_api.py @@ -113,6 +113,9 @@ def generate_batch_token(self, service_token, ttl="1h"): json_res = json.loads(res.content) token = json_res['auth']['client_token'] return token + elif res.status_code == 403: + logger.info("Getting batch token from Vault forbidden: {}".format(res.text)) + return None time.sleep(5) msg = "Getting batch token from Vault failed even tried 10 times, url is {}, API response is {}:{}".format( url, res.status_code, res.text) @@ -136,17 +139,31 @@ def _get_api_url(self, secret_path): def get_value_from_vault(self, token, secret_path, secret_key, verify): url = self._get_api_url(secret_path) for i in range(0, 10): - response = requests.get(url=url, headers={'X-Vault-Token': token}, verify=verify) + response = requests.get(url=url, headers={'X-Vault-Token': token}, verify=verify, timeout=30) if response.status_code == 200: - json_res = json.loads(response.content) - if json_res['data'].get('data') and isinstance(json_res['data'].get('data'), dict): - value = json_res['data'].get('data').get(secret_key) + body = response.content + if not body: + logger.debug('Empty body from Vault for url %s (attempt %d)', url, i) + time.sleep(5) + continue + try: + json_res = json.loads(body) + except Exception: + logger.info('Non-JSON response from Vault at %s (attempt %d): %s', url, i, body) + time.sleep(5) + continue + + data_field = json_res.get('data', {}) + if isinstance(data_field, dict) and data_field.get('data') and isinstance(data_field.get('data'), dict): + value = data_field.get('data').get(secret_key) else: - value = json_res['data'].get(secret_key) + value = data_field.get(secret_key) return value + + logger.debug('Vault returned status %s for %s (attempt %d)', response.status_code, url, i) time.sleep(5) - err_msg = "Getting value from Vault error even tried 10 times, url is {}, API response is {}:{}".format(url, response.status_code, response.text) - # abort(400, err_msg) + + err_msg = "Getting value from Vault error even tried 10 times, url is {}, API response is {}:{}".format(url, getattr(response, 'status_code', None), getattr(response, 'text', None)) raise Exception(err_msg) From 5f6c84429d3b8e636edc49c67c06aa338b55f74e Mon Sep 17 00:00:00 2001 From: I519866 Date: Tue, 18 Nov 2025 09:47:52 +0800 Subject: [PATCH 16/20] update --- src/api/handlers/job_api.py | 48 ++++++++++++++----------------------- 1 file changed, 18 insertions(+), 30 deletions(-) diff --git a/src/api/handlers/job_api.py b/src/api/handlers/job_api.py index 72d1bb9c..a80a75dd 100644 --- a/src/api/handlers/job_api.py +++ b/src/api/handlers/job_api.py @@ -69,8 +69,7 @@ def get_token_by_app_role(self): return self.token time.sleep(5) err_msg = "Getting token from Vault error even tried 10 times, url is {}, API response is {}:{}".format(app_role_url, res.status_code, res.text) - raise Exception(err_msg) - # abort(400, err_msg) + abort(400, err_msg) def get_policies(self, token): """Return the policies associated with the provided token.""" @@ -137,34 +136,23 @@ def _get_api_url(self, secret_path): return url def get_value_from_vault(self, token, secret_path, secret_key, verify): - url = self._get_api_url(secret_path) - for i in range(0, 10): - response = requests.get(url=url, headers={'X-Vault-Token': token}, verify=verify, timeout=30) - if response.status_code == 200: - body = response.content - if not body: - logger.debug('Empty body from Vault for url %s (attempt %d)', url, i) - time.sleep(5) - continue - try: - json_res = json.loads(body) - except Exception: - logger.info('Non-JSON response from Vault at %s (attempt %d): %s', url, i, body) - time.sleep(5) - continue - - data_field = json_res.get('data', {}) - if isinstance(data_field, dict) and data_field.get('data') and isinstance(data_field.get('data'), dict): - value = data_field.get('data').get(secret_key) - else: - value = data_field.get(secret_key) - return value - - logger.debug('Vault returned status %s for %s (attempt %d)', response.status_code, url, i) - time.sleep(5) - - err_msg = "Getting value from Vault error even tried 10 times, url is {}, API response is {}:{}".format(url, getattr(response, 'status_code', None), getattr(response, 'text', None)) - raise Exception(err_msg) + try: + url = self._get_api_url(secret_path) + for i in range(0, 10): + response = requests.get(url=url, headers={'X-Vault-Token': token}, verify=verify, timeout=30) + if response.status_code == 200: + json_res = json.loads(response.content) + if json_res['data'].get('data') and isinstance(json_res['data'].get('data'), dict): + value = json_res['data'].get('data').get(secret_key) + else: + value = json_res['data'].get(secret_key) + return value + time.sleep(5) + err_msg = "Getting value from Vault error even tried 10 times, url is {}, API response is {}:{}".format(url, response.status_code, response.text) + abort(400, err_msg) + except Exception as e: + err_msg = "Getting value from Vault exception: {}, url is {}".format(str(e), url) + abort(400, err_msg) @api.route("/api/job/job", doc=False) From 418f81aa857d67160d48c4808177881668141c87 Mon Sep 17 00:00:00 2001 From: I519866 Date: Wed, 19 Nov 2025 09:48:55 +0800 Subject: [PATCH 17/20] remove log --- src/api/handlers/job_api.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/api/handlers/job_api.py b/src/api/handlers/job_api.py index a80a75dd..f5e211fb 100644 --- a/src/api/handlers/job_api.py +++ b/src/api/handlers/job_api.py @@ -392,22 +392,18 @@ def get_secret(name): """, [vault_name, data['project']['id']]) if not result: - raise Exception("Cannot get Vault '%s' in project '%s' " % (vault_name, data['project']['id'])) - # abort(400, "Cannot get Vault '%s' in project '%s' " % (vault_name, data['project']['id'])) + abort(400, "Cannot get Vault '%s' in project '%s' " % (vault_name, data['project']['id'])) url, version, token, ca, namespace, role_id, secret_id = result[0], result[1], result[2], result[3], result[4], result[5], result[6] # choose validate way validate_res = get_auth_type(result) - logger.info("start to get secret from vault") vault = Vault(url, namespace, version, role_id, secret_id) if validate_res == 'token': logger.info('validate way is token') elif validate_res == 'appRole': logger.info('validate way is appRole') token = vault.get_token_by_app_role() - logger.info('get_token_by_app_role %s' % token) batch_token = vault.generate_batch_token(token) - logger.info('generate_batch_token %s' % batch_token) if batch_token: token = batch_token else: From fb599e9809516d80bd4c276187c19f3408460a9b Mon Sep 17 00:00:00 2001 From: I519866 Date: Wed, 19 Nov 2025 10:08:16 +0800 Subject: [PATCH 18/20] update log --- src/api/handlers/job_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/handlers/job_api.py b/src/api/handlers/job_api.py index f5e211fb..256d2e3f 100644 --- a/src/api/handlers/job_api.py +++ b/src/api/handlers/job_api.py @@ -410,7 +410,7 @@ def get_secret(name): abort(400, "Validate way is '%s' ! result is '%s' " % (validate_res, result)) if not ca: - logger.info('get_value_from_vault %s %s %s' % (token, secret_path, secret_key)) + logger.info('Start to get value fron vault %s %s %s' % (token, secret_path, secret_key)) return vault.get_value_from_vault(token, secret_path, secret_key, False) else: with tempfile.NamedTemporaryFile(delete=False) as f: From 05eb4ea1b921326d3dc6095f8847e68fd2bd53ce Mon Sep 17 00:00:00 2001 From: I519866 Date: Wed, 19 Nov 2025 14:20:43 +0800 Subject: [PATCH 19/20] refactor --- src/api/handlers/job_api.py | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/api/handlers/job_api.py b/src/api/handlers/job_api.py index 256d2e3f..e048823e 100644 --- a/src/api/handlers/job_api.py +++ b/src/api/handlers/job_api.py @@ -360,6 +360,8 @@ def get(self): ''', [data['project']['id']]) is_fork = data['job'].get('fork', False) + # Cache Vault instances per vault name+project so we create them only once + vault_cache = {} def get_secret_type(name): try: @@ -382,10 +384,10 @@ def get_auth_type(res): def get_secret(name): secret_type = get_secret_type(name) if secret_type == 'vault': - vault = json.loads(name) - vault_name = vault['$vault'] - secret_path = vault['$vault_secret_path'] - secret_key = vault['$vault_secret_key'] + vault_cfg = json.loads(name) + vault_name = vault_cfg['$vault'] + secret_path = vault_cfg['$vault_secret_path'] + secret_key = vault_cfg['$vault_secret_key'] result = g.db.execute_one(""" SELECT url, version, token, ca, namespace, role_id, secret_id FROM vault WHERE name = %s and project_id = %s @@ -397,26 +399,34 @@ def get_secret(name): url, version, token, ca, namespace, role_id, secret_id = result[0], result[1], result[2], result[3], result[4], result[5], result[6] # choose validate way validate_res = get_auth_type(result) - vault = Vault(url, namespace, version, role_id, secret_id) + + # key vault per project to avoid collisions + vault_key = f"{vault_name}-{data['project']['id']}" + vault_client = vault_cache.get(vault_key) + if not vault_client: + vault_client = Vault(url, namespace, version, role_id, secret_id) + vault_cache[vault_key] = vault_client + if validate_res == 'token': logger.info('validate way is token') + token_to_use = token elif validate_res == 'appRole': - logger.info('validate way is appRole') - token = vault.get_token_by_app_role() - batch_token = vault.generate_batch_token(token) + logger.info('validate way is appRole') + token_to_use = vault_client.get_token_by_app_role() + batch_token = vault_client.generate_batch_token(token_to_use) if batch_token: - token = batch_token + token_to_use = batch_token else: abort(400, "Validate way is '%s' ! result is '%s' " % (validate_res, result)) if not ca: - logger.info('Start to get value fron vault %s %s %s' % (token, secret_path, secret_key)) - return vault.get_value_from_vault(token, secret_path, secret_key, False) + logger.info('Start to get value fron vault %s %s %s' % (token_to_use, secret_path, secret_key)) + return vault_client.get_value_from_vault(token_to_use, secret_path, secret_key, False) else: with tempfile.NamedTemporaryFile(delete=False) as f: f.write(ca) f.flush() # ensure all data written - return vault.get_value_from_vault(token, secret_path, secret_key, f.name) + return vault_client.get_value_from_vault(token_to_use, secret_path, secret_key, f.name) else: if is_fork: abort(400, 'Access to secret %s is not allowed from a fork' % name) From c0c982fa26082c167a47588f5c5aa6b6c59183cd Mon Sep 17 00:00:00 2001 From: I519866 Date: Fri, 21 Nov 2025 14:33:27 +0800 Subject: [PATCH 20/20] fix no policy issue --- src/api/handlers/job_api.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/api/handlers/job_api.py b/src/api/handlers/job_api.py index e048823e..b4b482fd 100644 --- a/src/api/handlers/job_api.py +++ b/src/api/handlers/job_api.py @@ -94,18 +94,19 @@ def generate_batch_token(self, service_token, ttl="1h"): :param ttl: Time-to-live for the batch token. :return: The generated batch token. """ - if self.policies is None: - self.policies = self.get_policies(service_token) - if 'token-creator' in self.policies: - self.policies.remove('token-creator') - - batch_payload = { - "type": "batch", - "policies": self.policies or ['default'], - "ttl": ttl - } - url = self.base_url + '/v1/' + self.namespace + '/auth/token/create' if self.namespace else self.base_url + '/v1/auth/token/create' try: + if self.policies is None: + self.policies = self.get_policies(service_token) or ['default'] + if self.policies and 'token-creator' in self.policies: + self.policies.remove('token-creator') + + batch_payload = { + "type": "batch", + "policies": self.policies or ['default'], + "ttl": ttl + } + url = self.base_url + '/v1/' + self.namespace + '/auth/token/create' if self.namespace else self.base_url + '/v1/auth/token/create' + for i in range(0, 10): res = requests.post(url=url, json=batch_payload, headers={"X-Vault-Token": service_token}, verify=False) if res.status_code == 200: