This commit is contained in:
Mimo 2023-10-21 11:38:24 +08:00 committed by GitHub
commit 81b9975ab7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 51 additions and 4 deletions

View File

@ -26,6 +26,7 @@ Flask-Bcrypt = "==1.0.1"
Flask-Cors = ">=3.0.8"
ldap3 = "==2.9.1"
pycryptodome = "==3.12.0"
hvac = "==1.2.1"
# Caching
Flask-Caching = ">=1.0.0"
# Environment variable parsing

View File

@ -6,6 +6,7 @@ import time
from typing import Set
import elasticsearch
import hvac
import redis
import six
from Crypto.Cipher import AES
@ -286,3 +287,35 @@ class AESCrypto(object):
text_decrypted = cipher.decrypt(encode_bytes)
return cls.unpad(text_decrypted).decode('utf8')
class VaultTransitCrypto:
TRANSIT_KEY_NAME = 'cmdb-hvac-key'
client = None
@classmethod
def init_client(cls):
if not cls.client or not cls.client.is_authenticated():
cls.client = hvac.Client(
url=current_app.config.get('VAULT_URL'),
token=current_app.config.get('VAULT_TOKEN'),
)
@classmethod
def encrypt(cls, text):
cls.init_client()
cls.client.secrets.transit.create_key(name=cls.TRANSIT_KEY_NAME)
encrypt_data_response = cls.client.secrets.transit.encrypt_data(
name=cls.TRANSIT_KEY_NAME,
plaintext=base64.b64encode(text.encode()).decode(),
)
return encrypt_data_response['data']['ciphertext']
@classmethod
def decrypt(cls, ciphertext):
cls.init_client()
decrypt_data_response = cls.client.secrets.transit.decrypt_data(
name=cls.TRANSIT_KEY_NAME,
ciphertext=ciphertext,
)
return base64.b64decode(decrypt_data_response['data']['plaintext']).decode()

View File

@ -16,6 +16,7 @@ from api.lib.database import Model
from api.lib.database import SoftDeleteMixin
from api.lib.perm.acl.const import ACL_QUEUE
from api.lib.perm.acl.const import OperateType
from api.lib.utils import AESCrypto, VaultTransitCrypto
class App(Model):
@ -126,7 +127,7 @@ class User(CRUDModel, SoftDeleteMixin):
catalog = db.Column(db.String(64))
email = db.Column(db.String(100), unique=True, nullable=False)
mobile = db.Column(db.String(14), unique=True)
_password = db.Column("password", db.String(80))
_password = db.Column("password", db.String(128))
key = db.Column(db.String(32), nullable=False)
secret = db.Column(db.String(32), nullable=False)
date_joined = db.Column(db.DateTime, default=datetime.utcnow)
@ -155,14 +156,21 @@ class User(CRUDModel, SoftDeleteMixin):
return self._password
def _set_password(self, password):
self._password = hashlib.md5(password.encode('utf-8')).hexdigest()
md5_password = hashlib.md5(password.encode('utf-8')).hexdigest()
if current_app.config.get("ENCRYPT_PASSWORD_TYPE") == 'VAULT':
self._password = VaultTransitCrypto.encrypt(md5_password)
else:
self._password = AESCrypto.encrypt(md5_password)
password = db.synonym("_password", descriptor=property(_get_password, _set_password))
def check_password(self, password):
def check_password(self, md5_password):
if self.password is None:
return False
return self.password == password or self.password == hashlib.md5(password.encode('utf-8')).hexdigest()
if current_app.config.get("ENCRYPT_PASSWORD_TYPE") == 'VAULT':
return VaultTransitCrypto.decrypt(self.password) == md5_password
else:
return AESCrypto.decrypt(self.password) == md5_password
class RoleQuery(BaseQuery):

View File

@ -18,6 +18,7 @@ Flask-RESTful==0.3.10
Flask-SQLAlchemy==2.5.0
future==0.18.3
gunicorn==21.0.1
hvac==1.2.1
itsdangerous==2.1.2
Jinja2==3.1.2
jinja2schema==0.1.4

View File

@ -97,3 +97,7 @@ BOOL_TRUE = ['true', 'TRUE', 'True', True, '1', 1, "Yes", "YES", "yes", 'Y', 'y'
# # messenger
USE_MESSENGER = True
ENCRYPT_PASSWORD_TYPE = "VAULT" # "VAULT" or "AES"
VAULT_URL = 'http://' # 当 ENCRYPT_PASSWORD_TYPE 为 VAULT 时,需要配置
VAULT_TOKEN = '' # 当 ENCRYPT_PASSWORD_TYPE 为 VAULT 时,需要配置