client.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. import os, sys, json
  2. from libfuncs import (
  3. split_line
  4. )
  5. from crypto_client import (
  6. create_keys,
  7. save_file,
  8. load_key_from_file,
  9. generate_sign,
  10. generate_sign_hex,
  11. verify_sign,
  12. encrypt,
  13. decrypt,
  14. make_md5
  15. )
  16. from azure_key_vault_client import (
  17. get_secret as azure_get_secret,
  18. set_secret as azure_set_secret,
  19. del_secret as azure_del_secret,
  20. get_secrets_keys as azure_get_secrets_keys,
  21. get_deleted_secret as azure_get_deleted_secret,
  22. purge_deleted_secret as azure_purge_deleted_secret,
  23. azure_environ_name as eaen
  24. )
  25. from functools import (
  26. wraps
  27. )
  28. from enum import (
  29. Enum,
  30. auto
  31. )
  32. class enumbase(Enum):
  33. @property
  34. def info(self):
  35. return f"{self.name}:{self.value}"
  36. class autoname(enumbase):
  37. def _generate_next_value_(name, start, count, last_values):
  38. return name.lower()
  39. class azure_key_vault(object):
  40. SPLIT_SYMBOL = ";"
  41. class secret(object):
  42. class ATTER_NAMES(autoname):
  43. NAME = auto()
  44. NAMES = auto()
  45. ITEMS = auto()
  46. KEY_VAULT_NAME = auto()
  47. KEY_NAME = auto()
  48. KEY_VALUE = auto()
  49. def __init__(self, name):
  50. [setattr(self, item.value, "") for item in self.ATTER_NAMES]
  51. self.name = name
  52. def __init__(self, names):
  53. if names and isinstance(names, str):
  54. names = names.split(self.SPLIT_SYMBOL)
  55. if not names:
  56. raise ValueError(f"input args({names}) is invalid.")
  57. setattr(self, self.secret.ATTER_NAMES.NAMES.value, set(names))
  58. for name in self.names:
  59. setattr(self, name, self.secret(name))
  60. def name_to_str(self, name):
  61. return name if isinstance(name, str) else name.value
  62. def add(self, name):
  63. name = self.name_to_str(name)
  64. setattr(self, name, self.secret(name))
  65. def get(self, name):
  66. name = self.name_to_str(name)
  67. return getattr(self, name)
  68. def set(self, name, key_vault_name, key_name, key_value=""):
  69. secret = self.get(name)
  70. assert secret, f"not found secret({name})"
  71. secret.key_vault_name = key_vault_name
  72. secret.key_name = key_name
  73. secret.key_value = key_value
  74. def is_exists(self, name):
  75. name = self.name_to_str(name)
  76. return name in self.names
  77. def __getatter__(self, name):
  78. if name == self.secret.ATTER_NAMES.ITEMS.value:
  79. return [getattr(self, name) for name in self.names]
  80. elif name == self.secret.ATTER_NAMES.NAMES.value:
  81. return self.names
  82. class safemsgclient(object):
  83. key_memory_id = "memory_id"
  84. key_head_flag = "memkey_"
  85. class azure_names(autoname):
  86. '''
  87. SIGN_KEY: private key
  88. VERIFY_KEY: SIGN_KEY's public key
  89. ENCRYPT_KEY: public key
  90. DECRYPT_KEY: ENCRYPT_KEY's public key
  91. '''
  92. SIGN_KEY = auto()
  93. VERIFY_KEY = auto()
  94. ENCRYPT_KEY = auto()
  95. DECRYPT_KEY = auto()
  96. class key_source(autoname):
  97. FILE = auto()
  98. KEY_VAULT = auto()
  99. MEMORY = auto()
  100. def __init__(self, key_source=key_source.FILE, azure_names=azure_names, use_mempool=True, *args, **kwargs):
  101. self.set_key_source(key_source)
  102. setattr(self, "use_mempool", use_mempool)
  103. self.__mempool_secrets = {}
  104. self.set_key_source(key_source)
  105. if key_source == key_source.KEY_VAULT:
  106. self.__init_azure_env_id()
  107. self.__init_azure_key_value_name(azure_names)
  108. pass
  109. def clear_mempool_secrets(self):
  110. self.__mempool_secrets = {}
  111. def use_mempool_secret(self):
  112. self.use_mempool = True
  113. def unuse_mempool_secret(self):
  114. self.use_mempool = False
  115. def __init_azure_env_id(self):
  116. for item in eaen:
  117. setattr(self, item.name, item)
  118. def __init_azure_key_value_name(self, azure_names=azure_names):
  119. setattr(self, "azure_key_vault", azure_key_vault([item.value for item in self.azure_names]))
  120. def create_keys(self, num=2048, **kwargs):
  121. return create_keys(num)
  122. def save(self, key, filename, **kwargs):
  123. if filename:
  124. return save_file(key, filename)
  125. return False
  126. def load_key(self, filename, **kwargs):
  127. secret = None
  128. if filename:
  129. if self.use_mempool:
  130. secret = self.get_memory_key_value(filename)
  131. if not secret:
  132. secret = load_key_from_file(filename)
  133. self.set_memory_key_value(filename, secret)
  134. return secret
  135. return None
  136. def pre_azure_key(f):
  137. def use_azure(*args, **kwargs):
  138. self = args[0]
  139. args = list(args[1:])
  140. key_source = getattr(self, "key_source", None)
  141. key = None
  142. if args[0] and len(args[0]) > 0:
  143. key = args[0]
  144. elif key_source == self.key_source.MEMORY:
  145. memory_id = kwargs.get(self.key_memory_id)
  146. key = self.get_memory_key_value(memory_id)
  147. elif key_source == self.key_source.FILE:
  148. filename = kwargs.get("filename")
  149. key = self.load_key(filename)
  150. elif key_source == self.key_source.KEY_VAULT:
  151. azure_name = kwargs.get("azure_name")
  152. key_vault = self.azure_key_vault.get(azure_name)
  153. key = self.get_azure_secret_value(key_vault.key_vault_name, key_vault.key_name)
  154. args[0] = key
  155. return f(self, *args, **kwargs)
  156. return use_azure
  157. def load_key_from_file(self, filename):
  158. return load_key_from_file(filename)
  159. @pre_azure_key
  160. def verify_sign(self, pubkey, message, sign, secret=None, **kwargs):
  161. return verify_sign(pubkey, message, sign, secret)
  162. @pre_azure_key
  163. def generate_sign(self, privkey, unsign_message, secret=None, **kwargs):
  164. return generate_sign(privkey, unsign_message, secret)
  165. @pre_azure_key
  166. def generate_sign_hex(self, privkey, unsign_message, secret=None, **kwargs):
  167. return generate_sign_hex(privkey, unsign_message, secret)
  168. @pre_azure_key
  169. def encrypt(self, pubkey, message, secret=None, **kwargs):
  170. return encrypt(pubkey, message, secret)
  171. @pre_azure_key
  172. def decrypt(self, privkey, encrypt_message, secret=None, sentinel=None, **kwargs):
  173. return decrypt(privkey, encrypt_message, secret, sentinel)
  174. @classmethod
  175. def make_md5(self, message):
  176. return make_md5(message)
  177. ''' set azure env value
  178. '''
  179. def set_azure_client_id(self, id):
  180. self.AZURE_CLIENT_ID.env = id
  181. def get_azure_client_id(self):
  182. return self.AZURE_CLIENT_ID.env
  183. def set_azure_tenant_id(self, id):
  184. self.AZURE_TENANT_ID.env = id
  185. def get_azure_tenant_id(self):
  186. return self.AZURE_TENANT_ID.env
  187. def set_azure_client_secret(self, secret):
  188. self.AZURE_CLIENT_SECRET.env = secret
  189. def get_azure_client_secret(self):
  190. return self.AZURE_CLIENT_SECRET.env
  191. def set_azure_secret_ids(self, client_id, tenant_id, secret):
  192. self.set_azure_client_id(client_id)
  193. self.set_azure_tenant_id(tenant_id)
  194. self.set_azure_client_secret(secret)
  195. def encode_azure_secret_ids(self, pub_key, client_id, tenant_id, secret, encode_secret=None):
  196. kwargs = {
  197. "AZURE_CLIENT_ID": client_id, \
  198. "AZURE_TENANT_ID": tenant_id, \
  199. "AZURE_CLIENT_SECRET": secret
  200. }
  201. datas = json.dumps(kwargs)
  202. ids_datas = self.encrypt(pub_key, datas, encode_secret)
  203. return ids_datas.encode().hex()
  204. def decode_azure_secret_ids(self, datas, pri_key, encode_secret=None):
  205. encrypt_datas = bytes.fromhex(datas).decode()
  206. decrypt_datas = self.decrypt(pri_key, encrypt_datas, encode_secret)
  207. ids = json.loads(decrypt_datas)
  208. return (ids.get("AZURE_CLIENT_ID"), \
  209. ids.get("AZURE_TENANT_ID"), \
  210. ids.get("AZURE_CLIENT_SECRET"))
  211. def save_azure_secret_ids_to_file(self, ids_filename, pub_key, client_id, tenant_id, secret, encode_secret=None):
  212. datas = self.encode_azure_secret_ids(pub_key, client_id, tenant_id, secret, encode_secret)
  213. with open(ids_filename, 'w') as pf:
  214. pf.write(datas)
  215. return True
  216. return False
  217. def load_azure_secret_ids_from_file(self, ids_filename, pri_key, encode_secret=None):
  218. encrypt_datas = None
  219. with open(ids_filename, 'r') as pf:
  220. encrypt_datas = pf.read()
  221. assert encrypt_datas, f"load ids file(ids_filename) failed."
  222. return self.decode_azure_secret_ids(encrypt_datas, pri_key, encode_secret)
  223. def set_azure_secret_ids_with_file(self, ids_filename, pri_key, encode_secret=None):
  224. key_source = getattr(self, "key_source", None)
  225. assert key_source == key_source.KEY_VAULT, f"client key source is not {key_source.KEY_VAULT.name}"
  226. client_id, tenant_id, secret = self.load_azure_secret_ids_from_file(ids_filename, pri_key, encode_secret)
  227. self.set_azure_secret_ids(client_id, tenant_id, secret)
  228. def get_azure_envs(self):
  229. '''
  230. @dev show all environ info of azure
  231. @return all environ info for azure
  232. '''
  233. return {item.name: getattr(self, item.name).env for item in eaen}
  234. '''
  235. azure key vault operate, must connect azure with azure cli or environ id
  236. connect to azure:
  237. case 1: az login -u USERNAME -p PASSWORD
  238. case 2: use set_azure_secret_ids to set environ id
  239. CRUD operate: get_azure_secret, set_azure_secret, del_azure_secret
  240. '''
  241. def get_azure_secret(self, vault_name, key_name, version=None, **kwargs):
  242. '''
  243. @dev get secret from azure key vault
  244. @param vault_name key vault name
  245. @param key_name sercrt's key
  246. @param version version of the secret to get. if unspecified, gets the latest version
  247. @return secret(KeyVaultSecret)
  248. '''
  249. update_mempool = True
  250. secret = None
  251. key = self.create_memory_key_with_args(vault_name, key_name, version)
  252. if self.use_mempool:
  253. secret = self.get_memory_key_value(key)
  254. if not secret:
  255. secret = azure_get_secret(vault_name, key_name, version, **kwargs)
  256. else:
  257. update_mempool = False
  258. else:
  259. secret = azure_get_secret(vault_name, key_name, version, **kwargs)
  260. if update_mempool:
  261. self.set_memory_key_value(key, secret)
  262. return secret
  263. def get_azure_secret_value(self, vault_name, key_name, version=None, **kwargs):
  264. '''
  265. @dev get secret from azure key vault
  266. @param vault_name name of key vault
  267. @param key_name the name of secret
  268. @param key_value the value of secret
  269. @return value of secret(KeyVaultSecret)
  270. '''
  271. secret = None
  272. update_mempool = True
  273. key = self.create_memory_key_with_args(vault_name, key_name, version, "value")
  274. if self.use_mempool:
  275. secret = self.get_memory_key_value(key)
  276. if not secret:
  277. secret = azure_get_secret(vault_name, key_name, version, **kwargs).value
  278. else:
  279. update_mempool = False
  280. else:
  281. secret = azure_get_secret(vault_name, key_name, version, **kwargs).value
  282. if update_mempool:
  283. self.set_memory_key_value(key, secret)
  284. return secret
  285. def set_azure_secret(self, vault_name, key_name, key_value, **kwargs):
  286. '''
  287. @def set a secret value. If name is in use, create a new version of the secret. If not, create a new secret.
  288. @param vault_name name of key vault
  289. @param key_name the name of secret
  290. @param key_value the value of secret
  291. @param kwargs
  292. enabled (bool) – Whether the secret is enabled for use.
  293. tags (dict[str, str]) – Application specific metadata in the form of key-value pairs.
  294. content_type (str) – An arbitrary string indicating the type of the secret, e.g. ‘password’
  295. not_before (datetime) – Not before date of the secret in UTC
  296. expires_on (datetime) – Expiry date of the secret in UTC
  297. @return KeyVaultSecret
  298. '''
  299. ret = azure_set_secret(vault_name, key_name, key_value, **kwargs)
  300. self.del_memory_value(self.create_memory_key_with_args(vault_name, key_name))
  301. return ret
  302. def del_azure_secret(self, vault_name, key_name, **kwargs):
  303. self.del_memory_value(self.create_memory_key_with_args(vault_name, key_name))
  304. return azure_del_secret(vault_name, key_name, **kwargs)
  305. def get_azure_deleted_secret(self, vault_name, key_name, **kwargs):
  306. '''
  307. @dev get secret from azure key vault
  308. @param vault_name key vault name
  309. @param key_name sercrt's key
  310. @return secret(DeletedSecret)
  311. '''
  312. return azure_get_deleted_secret(vault_name, key_name, **kwargs)
  313. def get_azure_deleted_secret_id(self, vault_name, key_name, **kwargs):
  314. '''
  315. @dev get secret from azure key vault
  316. @param vault_name key vault name
  317. @param key_name sercrt's key
  318. @return id of secret(DeletedSecret)
  319. '''
  320. return self.get_azure_deleted_secret(vault_name, key_name, **kwargs).id
  321. def purge_deleted_secret(self, vault_name, key_name, **kwargs):
  322. '''
  323. @dev purge deleted secret from azure key vault
  324. @param vault_name key vault name
  325. @param key_name sercrt's key
  326. '''
  327. return azure_purge_deleted_secret(self, vault_name, key_name, **kwargs)
  328. def set_azure_key_path(self, azure_name, key_vault_name, key_name):
  329. if not self.azure_key_vault.is_exists(azure_name):
  330. self.azure_key_vault.add(azure_name)
  331. return self.azure_key_vault.set(azure_name, key_vault_name, key_name)
  332. def get_azure_secrets_keys(self, vault_name):
  333. return azure_get_secrets_keys(vault_name)
  334. def create_memory_key(self, name):
  335. if name.startswith(self.key_head_flag):
  336. return name
  337. return self.make_md5(f"{self.key_head_flag}_{name}")
  338. def create_memory_key_with_args(self, *args):
  339. name = '_'.join([str(arg) for arg in args])
  340. return self.create_memory_key(name)
  341. def set_key_source(self, key_source=key_source.MEMORY):
  342. setattr(self, "key_source", key_source)
  343. def set_memory_key_value(self, name, value):
  344. return self.__mempool_secrets.update({self.create_memory_key(name): value})
  345. @split_line
  346. def get_memory_key_value(self, name):
  347. return self.__mempool_secrets.get(self.create_memory_key(name), None)
  348. @split_line
  349. def del_memory_value(self, key_start):
  350. for key in self.__mempool_secrets:
  351. if key.startswith(key_start):
  352. self.__mempool_secrets[key] = None
  353. def __getatter__(self, name):
  354. if getattr(self, name):
  355. return getattr(self, name)
  356. return safemsgclient()
  357. def __call__(self, *args, **kwargs):
  358. pass