mirror of
				https://github.com/veops/cmdb.git
				synced 2025-10-31 02:56:27 +08:00 
			
		
		
		
	feat: add inner password storage and optimize flask command about inner cmdb (#248)
Co-authored-by: fxiang21 <fxiang21@126.com>
This commit is contained in:
		| @@ -318,6 +318,17 @@ def cmdb_index_table_upgrade(): | |||||||
|     db.session.commit() |     db.session.commit() | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def valid_address(address): | ||||||
|  |     if not address.startswith(("http://127.0.0.1", "https://127.0.0.1")): | ||||||
|  |         response = { | ||||||
|  |             "message": "Address should start with http://127.0.0.1 or https://127.0.0.1", | ||||||
|  |             "status": "failed" | ||||||
|  |         } | ||||||
|  |         KeyManage.print_response(response) | ||||||
|  |         return False | ||||||
|  |     return True | ||||||
|  |  | ||||||
|  |  | ||||||
| @click.command() | @click.command() | ||||||
| @click.option( | @click.option( | ||||||
|     '-a', |     '-a', | ||||||
| @@ -329,15 +340,26 @@ def cmdb_inner_secrets_init(address): | |||||||
|     """ |     """ | ||||||
|     init inner secrets for password feature |     init inner secrets for password feature | ||||||
|     """ |     """ | ||||||
|     KeyManage(backend=InnerKVManger).init() |     res, ok = KeyManage(backend=InnerKVManger).init() | ||||||
|  |     if not ok: | ||||||
|  |         if res.get("status") == "failed": | ||||||
|  |             KeyManage.print_response(res) | ||||||
|  |             return | ||||||
|  |  | ||||||
|     if address and address.startswith("http") and current_app.config.get("INNER_TRIGGER_TOKEN", "") != "": |     token = res.get("details", {}).get("root_token", "") | ||||||
|  |     if valid_address(address): | ||||||
|  |         token = current_app.config.get("INNER_TRIGGER_TOKEN", "") if not token else token | ||||||
|  |         if not token: | ||||||
|  |             token = click.prompt(f'Enter root token', hide_input=True, confirmation_prompt=False) | ||||||
|  |         assert token is not None | ||||||
|         resp = requests.post("{}/api/v0.1/secrets/auto_seal".format(address.strip("/")), |         resp = requests.post("{}/api/v0.1/secrets/auto_seal".format(address.strip("/")), | ||||||
|                              headers={"Inner-Token": current_app.config.get("INNER_TRIGGER_TOKEN", "")}) |                              headers={"Inner-Token": token}) | ||||||
|         if resp.status_code == 200: |         if resp.status_code == 200: | ||||||
|             KeyManage.print_response(resp.json()) |             KeyManage.print_response(resp.json()) | ||||||
|         else: |         else: | ||||||
|             KeyManage.print_response({"message": resp.text, "status": "failed"}) |             KeyManage.print_response({"message": resp.text or resp.status_code, "status": "failed"}) | ||||||
|  |     else: | ||||||
|  |         KeyManage.print_response(res) | ||||||
|  |  | ||||||
|  |  | ||||||
| @click.command() | @click.command() | ||||||
| @@ -352,18 +374,19 @@ def cmdb_inner_secrets_unseal(address): | |||||||
|     """ |     """ | ||||||
|     unseal the secrets feature |     unseal the secrets feature | ||||||
|     """ |     """ | ||||||
|     address = "{}/api/v0.1/secrets/unseal".format(address.strip("/")) |     if not valid_address(address): | ||||||
|     if not address.startswith("http"): |  | ||||||
|         KeyManage.print_response({"message": "invalid address, should start with http", "status": "failed"}) |  | ||||||
|         return |         return | ||||||
|  |     address = "{}/api/v0.1/secrets/unseal".format(address.strip("/")) | ||||||
|     for i in range(global_key_threshold): |     for i in range(global_key_threshold): | ||||||
|         token = click.prompt(f'Enter unseal token {i + 1}', hide_input=True, confirmation_prompt=False) |         token = click.prompt(f'Enter unseal token {i + 1}', hide_input=True, confirmation_prompt=False) | ||||||
|         assert token is not None |         assert token is not None | ||||||
|         resp = requests.post(address, headers={"Unseal-Token": token}) |         resp = requests.post(address, headers={"Unseal-Token": token}) | ||||||
|         if resp.status_code == 200: |         if resp.status_code == 200: | ||||||
|             KeyManage.print_response(resp.json()) |             KeyManage.print_response(resp.json()) | ||||||
|  |             if resp.json().get("status") in ["success", "skip"]: | ||||||
|  |                 return | ||||||
|         else: |         else: | ||||||
|             KeyManage.print_response({"message": resp.text, "status": "failed"}) |             KeyManage.print_response({"message": resp.status_code, "status": "failed"}) | ||||||
|             return |             return | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -388,7 +411,8 @@ def cmdb_inner_secrets_seal(address, token): | |||||||
|     """ |     """ | ||||||
|     assert address is not None |     assert address is not None | ||||||
|     assert token is not None |     assert token is not None | ||||||
|     if address.startswith("http"): |     if not valid_address(address): | ||||||
|  |         return | ||||||
|     address = "{}/api/v0.1/secrets/seal".format(address.strip("/")) |     address = "{}/api/v0.1/secrets/seal".format(address.strip("/")) | ||||||
|     resp = requests.post(address, headers={ |     resp = requests.post(address, headers={ | ||||||
|         "Inner-Token": token, |         "Inner-Token": token, | ||||||
| @@ -396,7 +420,7 @@ def cmdb_inner_secrets_seal(address, token): | |||||||
|     if resp.status_code == 200: |     if resp.status_code == 200: | ||||||
|         KeyManage.print_response(resp.json()) |         KeyManage.print_response(resp.json()) | ||||||
|     else: |     else: | ||||||
|             KeyManage.print_response({"message": resp.text, "status": "failed"}) |         KeyManage.print_response({"message": resp.status_code, "status": "failed"}) | ||||||
|  |  | ||||||
|  |  | ||||||
| @click.command() | @click.command() | ||||||
|   | |||||||
| @@ -9,12 +9,10 @@ from flask_login import LoginManager | |||||||
| from flask_migrate import Migrate | from flask_migrate import Migrate | ||||||
| from flask_sqlalchemy import SQLAlchemy | from flask_sqlalchemy import SQLAlchemy | ||||||
|  |  | ||||||
|  | from api.lib.secrets.inner import KeyManage | ||||||
| from api.lib.utils import ESHandler | from api.lib.utils import ESHandler | ||||||
| from api.lib.utils import RedisHandler | from api.lib.utils import RedisHandler | ||||||
|  |  | ||||||
| from api.lib.secrets.inner import KeyManage |  | ||||||
|  |  | ||||||
|  |  | ||||||
| bcrypt = Bcrypt() | bcrypt = Bcrypt() | ||||||
| login_manager = LoginManager() | login_manager = LoginManager() | ||||||
| db = SQLAlchemy(session_options={"autoflush": False}) | db = SQLAlchemy(session_options={"autoflush": False}) | ||||||
|   | |||||||
| @@ -1,8 +1,4 @@ | |||||||
| import os |  | ||||||
| import secrets |  | ||||||
| import sys |  | ||||||
| from base64 import b64decode, b64encode | from base64 import b64decode, b64encode | ||||||
|  |  | ||||||
| from colorama import Back | from colorama import Back | ||||||
| from colorama import Fore | from colorama import Fore | ||||||
| from colorama import init as colorama_init | from colorama import init as colorama_init | ||||||
| @@ -17,6 +13,9 @@ from cryptography.hazmat.primitives.ciphers import modes | |||||||
| from cryptography.hazmat.primitives.ciphers.aead import AESGCM | from cryptography.hazmat.primitives.ciphers.aead import AESGCM | ||||||
| from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC | from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC | ||||||
| from flask import current_app | from flask import current_app | ||||||
|  | import os | ||||||
|  | import secrets | ||||||
|  | import sys | ||||||
|  |  | ||||||
| global_iv_length = 16 | global_iv_length = 16 | ||||||
| global_key_shares = 5  # Number of generated key shares | global_key_shares = 5  # Number of generated key shares | ||||||
| @@ -26,6 +25,7 @@ backend_root_key_name = "root_key" | |||||||
| backend_encrypt_key_name = "encrypt_key" | backend_encrypt_key_name = "encrypt_key" | ||||||
| backend_root_key_salt_name = "root_key_salt" | backend_root_key_salt_name = "root_key_salt" | ||||||
| backend_encrypt_key_salt_name = "encrypt_key_salt" | backend_encrypt_key_salt_name = "encrypt_key_salt" | ||||||
|  | backend_seal_key = "seal_status" | ||||||
| success = "success" | success = "success" | ||||||
| seal_status = True | seal_status = True | ||||||
|  |  | ||||||
| @@ -51,6 +51,9 @@ class Backend: | |||||||
|     def add(self, key, value): |     def add(self, key, value): | ||||||
|         return self.backend.add(key, value) |         return self.backend.add(key, value) | ||||||
|  |  | ||||||
|  |     def update(self, key, value): | ||||||
|  |         return self.backend.update(key, value) | ||||||
|  |  | ||||||
|  |  | ||||||
| class KeyManage: | class KeyManage: | ||||||
|  |  | ||||||
| @@ -61,11 +64,11 @@ class KeyManage: | |||||||
|             self.backend = Backend(backend) |             self.backend = Backend(backend) | ||||||
|  |  | ||||||
|     def init_app(self, app, backend=None): |     def init_app(self, app, backend=None): | ||||||
|  |         if sys.argv[0].endswith("gunicorn") or sys.argv[1] == "run": | ||||||
|             self.trigger = app.config.get("INNER_TRIGGER_TOKEN") |             self.trigger = app.config.get("INNER_TRIGGER_TOKEN") | ||||||
|             if not self.trigger: |             if not self.trigger: | ||||||
|                 return |                 return | ||||||
|             self.backend = backend |             self.backend = backend | ||||||
|  |  | ||||||
|             resp = self.auto_unseal() |             resp = self.auto_unseal() | ||||||
|             self.print_response(resp) |             self.print_response(resp) | ||||||
|  |  | ||||||
| @@ -118,23 +121,23 @@ class KeyManage: | |||||||
|  |  | ||||||
|         return new_shares |         return new_shares | ||||||
|  |  | ||||||
|     def auth_root_secret(self, root_key): |     def is_valid_root_key(self, root_key): | ||||||
|         root_key_hash, ok = self.hash_root_key(root_key) |         root_key_hash, ok = self.hash_root_key(root_key) | ||||||
|         if not ok: |         if not ok: | ||||||
|             return { |             return root_key_hash, ok | ||||||
|                 "message": root_key_hash, |  | ||||||
|                 "status": "failed" |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|         backend_root_key_hash = self.backend.get(backend_root_key_name) |         backend_root_key_hash = self.backend.get(backend_root_key_name) | ||||||
|         if not backend_root_key_hash: |         if not backend_root_key_hash: | ||||||
|             return { |             return "should init firstly", False | ||||||
|                 "message": "should init firstly", |  | ||||||
|                 "status": "failed" |  | ||||||
|             } |  | ||||||
|         elif backend_root_key_hash != root_key_hash: |         elif backend_root_key_hash != root_key_hash: | ||||||
|  |             return "invalid root key", False | ||||||
|  |         else: | ||||||
|  |             return "", True | ||||||
|  |  | ||||||
|  |     def auth_root_secret(self, root_key): | ||||||
|  |         msg, ok = self.is_valid_root_key(root_key) | ||||||
|  |         if not ok: | ||||||
|             return { |             return { | ||||||
|                 "message": "invalid root key", |                 "message": msg, | ||||||
|                 "status": "failed" |                 "status": "failed" | ||||||
|             } |             } | ||||||
|  |  | ||||||
| @@ -146,11 +149,14 @@ class KeyManage: | |||||||
|             } |             } | ||||||
|  |  | ||||||
|         secrets_encrypt_key, ok = InnerCrypt.aes_decrypt(string_to_bytes(root_key), encrypt_key_aes) |         secrets_encrypt_key, ok = InnerCrypt.aes_decrypt(string_to_bytes(root_key), encrypt_key_aes) | ||||||
|  |         if ok: | ||||||
|  |             msg, ok = self.backend.update(backend_seal_key, "open") | ||||||
|             if ok: |             if ok: | ||||||
|                 current_app.config["secrets_encrypt_key"] = secrets_encrypt_key |                 current_app.config["secrets_encrypt_key"] = secrets_encrypt_key | ||||||
|                 current_app.config["secrets_root_key"] = root_key |                 current_app.config["secrets_root_key"] = root_key | ||||||
|                 current_app.config["secrets_shares"] = [] |                 current_app.config["secrets_shares"] = [] | ||||||
|                 return {"message": success, "status": success} |                 return {"message": success, "status": success} | ||||||
|  |             return {"message": msg, "status": "failed"} | ||||||
|         else: |         else: | ||||||
|             return { |             return { | ||||||
|                 "message": secrets_encrypt_key, |                 "message": secrets_encrypt_key, | ||||||
| @@ -204,34 +210,36 @@ class KeyManage: | |||||||
|         """ |         """ | ||||||
|         root_key = self.backend.get(backend_root_key_name) |         root_key = self.backend.get(backend_root_key_name) | ||||||
|         if root_key: |         if root_key: | ||||||
|             return {"message": "already init, skip"}, False |             return {"message": "already init, skip", "status": "skip"}, False | ||||||
|         else: |         else: | ||||||
|             root_key, shares, status = self.generate_unseal_keys() |             root_key, shares, status = self.generate_unseal_keys() | ||||||
|             if not status: |             if not status: | ||||||
|                 return {"message": root_key}, False |                 return {"message": root_key, "status": "failed"}, False | ||||||
|  |  | ||||||
|             # hash root key and store in backend |             # hash root key and store in backend | ||||||
|             root_key_hash, ok = self.hash_root_key(root_key) |             root_key_hash, ok = self.hash_root_key(root_key) | ||||||
|             if not ok: |             if not ok: | ||||||
|                 return {"message": root_key_hash}, False |                 return {"message": root_key_hash, "status": "failed"}, False | ||||||
|  |  | ||||||
|             msg, ok = self.backend.add(backend_root_key_name, root_key_hash) |             msg, ok = self.backend.add(backend_root_key_name, root_key_hash) | ||||||
|             if not ok: |             if not ok: | ||||||
|                 return {"message": msg}, False |                 return {"message": msg, "status": "failed"}, False | ||||||
|  |  | ||||||
|             # generate encrypt key from root_key and store in backend |             # generate encrypt key from root_key and store in backend | ||||||
|             encrypt_key, ok = self.generate_encrypt_key(root_key) |             encrypt_key, ok = self.generate_encrypt_key(root_key) | ||||||
|             if not ok: |             if not ok: | ||||||
|                 return {"message": encrypt_key} |                 return {"message": encrypt_key, "status": "failed"} | ||||||
|  |  | ||||||
|             encrypt_key_aes, status = InnerCrypt.aes_encrypt(root_key, encrypt_key) |             encrypt_key_aes, status = InnerCrypt.aes_encrypt(root_key, encrypt_key) | ||||||
|             if not status: |             if not status: | ||||||
|                 return {"message": encrypt_key_aes} |                 return {"message": encrypt_key_aes, "status": "failed"} | ||||||
|  |  | ||||||
|             msg, ok = self.backend.add(backend_encrypt_key_name, encrypt_key_aes) |             msg, ok = self.backend.add(backend_encrypt_key_name, encrypt_key_aes) | ||||||
|             if not ok: |             if not ok: | ||||||
|                 return {"message": msg}, False |                 return {"message": msg, "status": "failed"}, False | ||||||
|  |             msg, ok = self.backend.add(backend_seal_key, "open") | ||||||
|  |             if not ok: | ||||||
|  |                 return {"message": msg, "status": "failed"}, False | ||||||
|             current_app.config["secrets_root_key"] = root_key |             current_app.config["secrets_root_key"] = root_key | ||||||
|             current_app.config["secrets_encrypt_key"] = encrypt_key |             current_app.config["secrets_encrypt_key"] = encrypt_key | ||||||
|             self.print_token(shares, root_token=root_key) |             self.print_token(shares, root_token=root_key) | ||||||
| @@ -275,28 +283,21 @@ class KeyManage: | |||||||
|  |  | ||||||
|     def seal(self, root_key): |     def seal(self, root_key): | ||||||
|         root_key = root_key.encode() |         root_key = root_key.encode() | ||||||
|         root_key_hash, ok = self.hash_root_key(root_key) |         msg, ok = self.is_valid_root_key(root_key) | ||||||
|         if not ok: |         if not ok: | ||||||
|             return { |             return { | ||||||
|                 "message": root_key_hash, |                 "message": msg, | ||||||
|                 "status": "failed" |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|         backend_root_key_hash = self.backend.get(backend_root_key_name) |  | ||||||
|         if not backend_root_key_hash: |  | ||||||
|             return { |  | ||||||
|                 "message": "not init, seal skip", |  | ||||||
|                 "status": "skip" |  | ||||||
|             } |  | ||||||
|         elif root_key_hash != backend_root_key_hash: |  | ||||||
|             return { |  | ||||||
|                 "message": "invalid root key", |  | ||||||
|                 "status": "failed" |                 "status": "failed" | ||||||
|             } |             } | ||||||
|         else: |         else: | ||||||
|  |             msg, ok = self.backend.update(backend_seal_key, "block") | ||||||
|  |             if not ok: | ||||||
|  |                 return { | ||||||
|  |                     "message": msg, | ||||||
|  |                     "status": "failed", | ||||||
|  |                 } | ||||||
|             current_app.config["secrets_root_key"] = '' |             current_app.config["secrets_root_key"] = '' | ||||||
|             current_app.config["secrets_encrypt_key"] = '' |             current_app.config["secrets_encrypt_key"] = '' | ||||||
|  |  | ||||||
|             return { |             return { | ||||||
|                 "message": success, |                 "message": success, | ||||||
|                 "status": success |                 "status": success | ||||||
| @@ -308,11 +309,11 @@ class KeyManage: | |||||||
|         :return: |         :return: | ||||||
|         """ |         """ | ||||||
|         secrets_root_key = current_app.config.get("secrets_root_key") |         secrets_root_key = current_app.config.get("secrets_root_key") | ||||||
|         root_key = self.backend.get(backend_root_key_name) |         msg, ok = self.is_valid_root_key(secrets_root_key) | ||||||
|         if root_key == "" or root_key != secrets_root_key: |         if not ok: | ||||||
|             return "invalid root key", True |             return {"message": msg, "status": "failed"} | ||||||
|  |         status = self.backend.get(backend_seal_key) | ||||||
|         return "", False |         return status == "block" | ||||||
|  |  | ||||||
|     @classmethod |     @classmethod | ||||||
|     def print_token(cls, shares, root_token): |     def print_token(cls, shares, root_token): | ||||||
| @@ -330,7 +331,7 @@ class KeyManage: | |||||||
|  |  | ||||||
|         for i, v in enumerate(shares): |         for i, v in enumerate(shares): | ||||||
|             print( |             print( | ||||||
|                 "unseal token " + str(i + 1) + ": " + Fore.RED + Back.CYAN + v.decode("utf-8") + Style.RESET_ALL) |                 "unseal token " + str(i + 1) + ": " + Fore.RED + Back.BLACK + v.decode("utf-8") + Style.RESET_ALL) | ||||||
|             print() |             print() | ||||||
|  |  | ||||||
|         print(Fore.GREEN + "root token:  " + root_token.decode("utf-8") + Style.RESET_ALL) |         print(Fore.GREEN + "root token:  " + root_token.decode("utf-8") + Style.RESET_ALL) | ||||||
| @@ -339,14 +340,12 @@ class KeyManage: | |||||||
|     def print_response(cls, data): |     def print_response(cls, data): | ||||||
|         status = data.get("status", "") |         status = data.get("status", "") | ||||||
|         message = data.get("message", "") |         message = data.get("message", "") | ||||||
|         if status == "skip": |         status_colors = { | ||||||
|             print(Style.BRIGHT, message) |             "skip": Style.BRIGHT, | ||||||
|         elif status == "failed": |             "failed": Fore.RED, | ||||||
|             print(Fore.RED, message) |             "waiting": Fore.YELLOW, | ||||||
|         elif status == "waiting": |         } | ||||||
|             print(Fore.YELLOW, message) |         print(status_colors.get(status, Fore.GREEN), message, Style.RESET_ALL) | ||||||
|         else: |  | ||||||
|             print(Fore.GREEN, message) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class InnerCrypt: | class InnerCrypt: | ||||||
|   | |||||||
| @@ -11,7 +11,6 @@ class InnerKVManger(object): | |||||||
|         res = InnerKV.create(**data) |         res = InnerKV.create(**data) | ||||||
|         if res.key == key: |         if res.key == key: | ||||||
|             return "success", True |             return "success", True | ||||||
|  |  | ||||||
|         return "add failed", False |         return "add failed", False | ||||||
|  |  | ||||||
|     @classmethod |     @classmethod | ||||||
| @@ -21,3 +20,14 @@ class InnerKVManger(object): | |||||||
|             return None |             return None | ||||||
|  |  | ||||||
|         return res.value |         return res.value | ||||||
|  |  | ||||||
|  |     @classmethod | ||||||
|  |     def update(cls, key, value): | ||||||
|  |         res = InnerKV.get_by(first=True, to_dict=False, **{"key": key}) | ||||||
|  |         if not res: | ||||||
|  |             return None | ||||||
|  |         res.value = value | ||||||
|  |         t = res.update() | ||||||
|  |         if t.key == key: | ||||||
|  |             return "success", True | ||||||
|  |         return "update failed", True | ||||||
|   | |||||||
| @@ -1,38 +1,38 @@ | |||||||
|  | from api.lib.perm.auth import auth_abandoned | ||||||
| from api.resource import APIView | from api.resource import APIView | ||||||
| from api.lib.secrets.inner import KeyManage | from api.lib.secrets.inner import KeyManage | ||||||
| from api.lib.secrets.secrets import InnerKVManger | from api.lib.secrets.secrets import InnerKVManger | ||||||
|  |  | ||||||
| from flask import request, abort | from flask import current_app | ||||||
|  | from flask import request | ||||||
|  |  | ||||||
|  |  | ||||||
| class InnerSecretUnSealView(APIView): | class InnerSecretUnSealView(APIView): | ||||||
|     url_prefix = "/secrets/unseal" |     url_prefix = "/secrets/unseal" | ||||||
|  |  | ||||||
|  |     @auth_abandoned | ||||||
|     def post(self): |     def post(self): | ||||||
|         unseal_key = request.headers.get("Unseal-Token") |         unseal_key = request.headers.get("Unseal-Token") | ||||||
|         res = KeyManage(backend=InnerKVManger()).unseal(unseal_key) |         res = KeyManage(backend=InnerKVManger()).unseal(unseal_key) | ||||||
|         # if res.get("status") == "failed": |  | ||||||
|         #     return abort(400, res.get("message")) |  | ||||||
|         return self.jsonify(**res) |         return self.jsonify(**res) | ||||||
|  |  | ||||||
|  |  | ||||||
| class InnerSecretSealView(APIView): | class InnerSecretSealView(APIView): | ||||||
|     url_prefix = "/secrets/seal" |     url_prefix = "/secrets/seal" | ||||||
|  |  | ||||||
|  |     @auth_abandoned | ||||||
|     def post(self): |     def post(self): | ||||||
|         unseal_key = request.headers.get("Inner-Token") |         unseal_key = request.headers.get("Inner-Token") | ||||||
|         res = KeyManage(backend=InnerKVManger()).seal(unseal_key) |         res = KeyManage(backend=InnerKVManger()).seal(unseal_key) | ||||||
|         # if res.get("status") == "failed": |  | ||||||
|         #     return abort(400, res.get("message")) |  | ||||||
|         return self.jsonify(**res) |         return self.jsonify(**res) | ||||||
|  |  | ||||||
|  |  | ||||||
| class InnerSecretAutoSealView(APIView): | class InnerSecretAutoSealView(APIView): | ||||||
|     url_prefix = "/secrets/auto_seal" |     url_prefix = "/secrets/auto_seal" | ||||||
|  |  | ||||||
|  |     @auth_abandoned | ||||||
|     def post(self): |     def post(self): | ||||||
|         unseal_key = request.headers.get("Inner-Token") |         root_key = request.headers.get("Inner-Token") | ||||||
|         res = KeyManage(backend=InnerKVManger()).seal(unseal_key) |         res = KeyManage(trigger=root_key, | ||||||
|         # if res.get("status") == "failed": |                         backend=InnerKVManger()).auto_unseal() | ||||||
|         #     return abort(400, res.get("message")) |  | ||||||
|         return self.jsonify(**res) |         return self.jsonify(**res) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user