env_config.py 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. import contextlib
  2. import os
  3. import logging
  4. logger = logging.getLogger("env_config")
  5. # List of environment variables prefixes that are allowed to be used for configuration.
  6. env_prefix_whitelist = [
  7. 'OPENAI',
  8. 'AZURE_OPENAI'
  9. ]
  10. def _obfuscate(secret):
  11. l = len(secret)
  12. return '.' * (l - 4) + secret[-4:]
  13. def _log_env(use_prefix: str, env: dict):
  14. """
  15. Logs each name value pair of the given environment. If the name indicates that it might store a secret such as an API key, then obfuscate the value.
  16. """
  17. log_prefix = f"'{use_prefix}'" if use_prefix else "no"
  18. logger.info(f"Resolved OpenAI env vars with {log_prefix} prefix:")
  19. for key, value in env.items():
  20. if any(prefix in key for prefix in ['KEY', 'SECRET', 'TOKEN']):
  21. value = _obfuscate(value)
  22. logger.info(f" - {key}={value}")
  23. def read_env_config(use_prefix: str, env: dict = os.environ) -> str:
  24. """
  25. Read whitelisted environment variables and return them in a dictionary.
  26. Overrides the whitelisted environment variable with ones prefixed with the given use_prefix if available.
  27. """
  28. config = {}
  29. for prefix in [None, use_prefix]:
  30. read_env_config_prefixed(prefix, config, env)
  31. _log_env(use_prefix, config)
  32. return config
  33. def read_env_config_prefixed(use_prefix: str, config: dict, env: dict = os.environ) -> str:
  34. """
  35. Read whitelisted environment variables prefixed with use_prefix and adds them to the dictionary
  36. with use_prefix stripped.
  37. """
  38. use_prefix = format_prefix(use_prefix)
  39. for key in env:
  40. for env_prefix in env_prefix_whitelist:
  41. key_prefix = f"{use_prefix}{format_prefix(env_prefix)}"
  42. if key.startswith(key_prefix):
  43. striped_key = key.removeprefix(use_prefix)
  44. config[striped_key] = env[key]
  45. def format_prefix(prefix: str) -> str:
  46. """
  47. Format the prefix to be used in the environment variable.
  48. """
  49. if prefix and len(prefix) > 0 and not prefix.endswith("_"):
  50. prefix = f"{prefix}_"
  51. if not prefix:
  52. prefix = ""
  53. return prefix
  54. @contextlib.contextmanager
  55. def set_env(**environ: dict[str, str]):
  56. """
  57. Temporarily set the process environment variables.
  58. Warning, this is not thread safe as the environment is updated for the whole process.
  59. >>> with set_env(PLUGINS_DIR='test/plugins'):
  60. ... "PLUGINS_DIR" in os.environ
  61. True
  62. >>> "PLUGINS_DIR" in os.environ
  63. False
  64. :type environ: dict[str, unicode]
  65. :param environ: Environment variables to set
  66. """
  67. old_environ = dict(os.environ)
  68. os.environ.update(environ)
  69. try:
  70. yield
  71. finally:
  72. os.environ.clear()
  73. os.environ.update(old_environ)