oidc_env.py 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. """Read the single OIDC provider defined by BAMBUDDY_OIDC_* env vars (#2593).
  2. A declarative deployment (compose, Helm, GitOps) has no way to click through
  3. the settings UI, so one provider can be configured entirely from the
  4. environment. This module only reads and defaults; validity is decided by the
  5. same OIDCProviderCreate schema the API uses, so env config cannot bypass a
  6. check the UI enforces.
  7. """
  8. from __future__ import annotations
  9. import os
  10. # All four or nothing: a provider missing its secret would be written to the
  11. # database and then fail at authorize time, long after the operator could
  12. # connect the failure to a typo in their compose file.
  13. _REQUIRED = (
  14. "BAMBUDDY_OIDC_NAME",
  15. "BAMBUDDY_OIDC_ISSUER_URL",
  16. "BAMBUDDY_OIDC_CLIENT_ID",
  17. "BAMBUDDY_OIDC_CLIENT_SECRET",
  18. )
  19. _TRUTHY = {"true", "1", "yes"}
  20. def _env_bool(key: str, default: bool) -> bool:
  21. value = os.environ.get(key)
  22. return default if value is None else value.strip().lower() in _TRUTHY
  23. def read_env_oidc_config() -> dict | None:
  24. """The provider's fields from the environment, or None if it isn't configured.
  25. An empty required var counts as unset -- `BAMBUDDY_OIDC_CLIENT_SECRET=` in
  26. a compose file is a forgotten value, not an intentional empty secret.
  27. """
  28. if not all(os.environ.get(key) for key in _REQUIRED):
  29. return None
  30. return {
  31. "name": os.environ["BAMBUDDY_OIDC_NAME"],
  32. "issuer_url": os.environ["BAMBUDDY_OIDC_ISSUER_URL"],
  33. "client_id": os.environ["BAMBUDDY_OIDC_CLIENT_ID"],
  34. "client_secret": os.environ["BAMBUDDY_OIDC_CLIENT_SECRET"],
  35. "scopes": os.environ.get("BAMBUDDY_OIDC_SCOPES", "openid email profile"),
  36. "is_enabled": _env_bool("BAMBUDDY_OIDC_ENABLED", True),
  37. "auto_create_users": _env_bool("BAMBUDDY_OIDC_AUTO_CREATE_USERS", False),
  38. "auto_link_existing_accounts": _env_bool("BAMBUDDY_OIDC_AUTO_LINK_EXISTING", False),
  39. "email_claim": os.environ.get("BAMBUDDY_OIDC_EMAIL_CLAIM", "email"),
  40. "require_email_verified": _env_bool("BAMBUDDY_OIDC_REQUIRE_EMAIL_VERIFIED", True),
  41. "icon_url": os.environ.get("BAMBUDDY_OIDC_ICON_URL"),
  42. "is_autologin": _env_bool("BAMBUDDY_OIDC_AUTOLOGIN", False),
  43. }