fix: unseal secret function

This commit is contained in:
fxiang21
2024-04-10 20:08:53 +08:00
parent 42c82ff790
commit 676b326fc6
4 changed files with 65 additions and 5 deletions

View File

@@ -368,8 +368,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 not valid_address(address): if not valid_address(address):
# return 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,

View File

@@ -16,6 +16,7 @@ from cryptography.hazmat.primitives.ciphers import algorithms
from cryptography.hazmat.primitives.ciphers import modes 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
global_iv_length = 16 global_iv_length = 16
@@ -56,12 +57,19 @@ class Backend:
def update(self, key, value): def update(self, key, value):
return self.backend.update(key, value) return self.backend.update(key, value)
def get_shares(self, key):
return self.backend.get_shares(key)
def set_shares(self, key, value):
return self.backend.set_shares(key, value)
class KeyManage: class KeyManage:
def __init__(self, trigger=None, backend=None): def __init__(self, trigger=None, backend=None):
self.trigger = trigger self.trigger = trigger
self.backend = backend self.backend = backend
self.share_key = "cmdb::secret::secrets_share"
if backend: if backend:
self.backend = Backend(backend) self.backend = Backend(backend)
@@ -126,6 +134,8 @@ class KeyManage:
return new_shares return new_shares
def is_valid_root_key(self, root_key): def is_valid_root_key(self, root_key):
if not root_key:
return False
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 root_key_hash, ok return root_key_hash, ok
@@ -158,7 +168,8 @@ class KeyManage:
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"] = []
self.backend.set_shares(self.share_key, [])
return {"message": success, "status": success} return {"message": success, "status": success}
return {"message": msg, "status": "failed"} return {"message": msg, "status": "failed"}
else: else:
@@ -177,10 +188,12 @@ class KeyManage:
try: try:
t = [i for i in b64decode(key)] t = [i for i in b64decode(key)]
v = (int("".join([chr(i) for i in t[-2:]])), bytes(t[:-2])) v = (int("".join([chr(i) for i in t[-2:]])), bytes(t[:-2]))
shares = current_app.config.get("secrets_shares", []) # shares = current_app.config.get("secrets_shares", [])
shares = self.backend.get_shares(self.share_key)
if v not in shares: if v not in shares:
shares.append(v) shares.append(v)
current_app.config["secrets_shares"] = shares # current_app.config["secrets_shares"] = shares
self.backend.set_shares(self.share_key, shares)
if len(shares) >= global_key_threshold: if len(shares) >= global_key_threshold:
recovered_secret = Shamir.combine(shares[:global_key_threshold], False) recovered_secret = Shamir.combine(shares[:global_key_threshold], False)
@@ -313,6 +326,8 @@ class KeyManage:
:return: :return:
""" """
secrets_root_key = current_app.config.get("secrets_root_key") secrets_root_key = current_app.config.get("secrets_root_key")
if not secrets_root_key:
return True
msg, ok = self.is_valid_root_key(secrets_root_key) msg, ok = self.is_valid_root_key(secrets_root_key)
if not ok: if not ok:
return True return True

View File

@@ -1,4 +1,9 @@
import base64
import json
from api.models.cmdb import InnerKV from api.models.cmdb import InnerKV
from api.extensions import rd
class InnerKVManger(object): class InnerKVManger(object):
@@ -33,3 +38,26 @@ class InnerKVManger(object):
return "success", True return "success", True
return "update failed", True return "update failed", True
@classmethod
def get_shares(cls, key):
new_value = list()
v = rd.get_str(key)
if not v:
return new_value
try:
value = json.loads(v.decode("utf-8"))
for v in value:
new_value.append((v[0], base64.b64decode(v[1])))
except Exception as e:
return []
return new_value
@classmethod
def set_shares(cls, key, value):
new_value = list()
for v in value:
new_value.append((v[0], base64.b64encode(v[1]).decode("utf-8")))
rd.set_str(key, json.dumps(new_value))

View File

@@ -119,6 +119,23 @@ class RedisHandler(object):
except Exception as e: except Exception as e:
current_app.logger.error("delete redis key error, {0}".format(str(e))) current_app.logger.error("delete redis key error, {0}".format(str(e)))
def set_str(self, key, value, expired=None):
try:
if expired:
self.r.setex(key, expired, value)
else:
self.r.set(key, value)
except Exception as e:
current_app.logger.error("set redis error, {0}".format(str(e)))
def get_str(self, key):
try:
value = self.r.get(key)
except Exception as e:
current_app.logger.error("get redis error, {0}".format(str(e)))
return
return value
class ESHandler(object): class ESHandler(object):
def __init__(self, flask_app=None): def __init__(self, flask_app=None):