mirror of
https://github.com/agentrhq/authsome.git
synced 2026-09-19 01:34:19 +08:00
fix: require production backend URLs
This commit is contained in:
@@ -49,6 +49,7 @@ services:
|
|||||||
AUTHSOME_HOST: 0.0.0.0
|
AUTHSOME_HOST: 0.0.0.0
|
||||||
AUTHSOME_PORT: "7998"
|
AUTHSOME_PORT: "7998"
|
||||||
AUTHSOME_HOME: /data/authsome
|
AUTHSOME_HOME: /data/authsome
|
||||||
|
AUTHSOME_ENV: prod
|
||||||
AUTHSOME_BASE_URL: ${AUTHSOME_BASE_URL:-http://localhost:7998}
|
AUTHSOME_BASE_URL: ${AUTHSOME_BASE_URL:-http://localhost:7998}
|
||||||
AUTHSOME_DATABASE_URL: postgresql://${AUTHSOME_POSTGRES_USER:-authsome}:${AUTHSOME_POSTGRES_PASSWORD:?set AUTHSOME_POSTGRES_PASSWORD}@postgres:5432/${AUTHSOME_POSTGRES_DB:-authsome}
|
AUTHSOME_DATABASE_URL: postgresql://${AUTHSOME_POSTGRES_USER:-authsome}:${AUTHSOME_POSTGRES_PASSWORD:?set AUTHSOME_POSTGRES_PASSWORD}@postgres:5432/${AUTHSOME_POSTGRES_DB:-authsome}
|
||||||
AUTHSOME_REDIS_URL: redis://redis:6379/0
|
AUTHSOME_REDIS_URL: redis://redis:6379/0
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ Do not commit production secrets. Use your platform secret store or Docker secre
|
|||||||
|
|
||||||
| Variable | Default | Description |
|
| Variable | Default | Description |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
|
| `AUTHSOME_ENV` | `dev` | Runtime mode. Set to `prod` for production deployments; in `prod`, `AUTHSOME_DATABASE_URL` and `AUTHSOME_REDIS_URL` are required. |
|
||||||
| `AUTHSOME_DATABASE_URL` | none | Postgres DSN for the daemon-owned registries. The compose file points this at the bundled Postgres service. |
|
| `AUTHSOME_DATABASE_URL` | none | Postgres DSN for the daemon-owned registries. The compose file points this at the bundled Postgres service. |
|
||||||
| `AUTHSOME_REDIS_URL` | none | Redis URL for shared runtime state and the encrypted vault raw KV backend. |
|
| `AUTHSOME_REDIS_URL` | none | Redis URL for shared runtime state and the encrypted vault raw KV backend. |
|
||||||
| `AUTHSOME_POSTGRES_PASSWORD` | none | Required password used by the bundled Postgres service and the daemon's database URL. |
|
| `AUTHSOME_POSTGRES_PASSWORD` | none | Required password used by the bundled Postgres service and the daemon's database URL. |
|
||||||
@@ -54,7 +55,7 @@ Do not commit production secrets. Use your platform secret store or Docker secre
|
|||||||
| `AUTHSOME_POSTHOG_API_KEY` | none | Enables PostHog analytics when present and telemetry is not opted out. |
|
| `AUTHSOME_POSTHOG_API_KEY` | none | Enables PostHog analytics when present and telemetry is not opted out. |
|
||||||
| `AUTHSOME_POSTHOG_HOST` | `https://us.i.posthog.com` | Override the PostHog ingestion host if needed. |
|
| `AUTHSOME_POSTHOG_HOST` | `https://us.i.posthog.com` | Override the PostHog ingestion host if needed. |
|
||||||
|
|
||||||
The daemon still accepts the legacy `DATABASE_URL` alias, but production deployments should set `AUTHSOME_DATABASE_URL`.
|
The daemon still accepts the legacy `DATABASE_URL` alias, but production deployments should set `AUTHSOME_DATABASE_URL`. The included compose file sets `AUTHSOME_ENV=prod`, which makes the Postgres and Redis URLs mandatory at startup.
|
||||||
The included compose file hard-requires `AUTHSOME_MASTER_KEY` and `AUTHSOME_UI_SESSION_KEY` from the host environment; it does not mount secret files or pass `_FILE` paths for you.
|
The included compose file hard-requires `AUTHSOME_MASTER_KEY` and `AUTHSOME_UI_SESSION_KEY` from the host environment; it does not mount secret files or pass `_FILE` paths for you.
|
||||||
|
|
||||||
## Secret resolution
|
## Secret resolution
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class AuthsomeConfig(BaseSettings):
|
|||||||
model_config = SettingsConfigDict(env_prefix="AUTHSOME_")
|
model_config = SettingsConfigDict(env_prefix="AUTHSOME_")
|
||||||
|
|
||||||
version: str = __version__
|
version: str = __version__
|
||||||
env: Literal["prod", "dev", "test"] = "prod"
|
env: Literal["prod", "dev", "test"] = "dev"
|
||||||
home: Path = Field(default=Path.home() / ".authsome")
|
home: Path = Field(default=Path.home() / ".authsome")
|
||||||
base_url: str = Field(default="http://127.0.0.1:7998")
|
base_url: str = Field(default="http://127.0.0.1:7998")
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,13 @@ class ServerConfig(AuthsomeConfig):
|
|||||||
def validate_postgres_pool_sizes(self) -> "ServerConfig":
|
def validate_postgres_pool_sizes(self) -> "ServerConfig":
|
||||||
if self.postgres_pool_min_size > self.postgres_pool_max_size:
|
if self.postgres_pool_min_size > self.postgres_pool_max_size:
|
||||||
raise ValueError("postgres_pool_min_size must be less than or equal to postgres_pool_max_size")
|
raise ValueError("postgres_pool_min_size must be less than or equal to postgres_pool_max_size")
|
||||||
|
if self.env == "prod":
|
||||||
|
if not self.database_url:
|
||||||
|
raise ValueError("AUTHSOME_DATABASE_URL is required when AUTHSOME_ENV=prod")
|
||||||
|
if not self.database_url.startswith(("postgresql://", "postgres://")):
|
||||||
|
raise ValueError("AUTHSOME_DATABASE_URL must be a Postgres URL when AUTHSOME_ENV=prod")
|
||||||
|
if not self.redis_url:
|
||||||
|
raise ValueError("AUTHSOME_REDIS_URL is required when AUTHSOME_ENV=prod")
|
||||||
return self
|
return self
|
||||||
|
|
||||||
# Lifetimes, in seconds
|
# Lifetimes, in seconds
|
||||||
|
|||||||
@@ -117,13 +117,16 @@ class StoreDatabase:
|
|||||||
|
|
||||||
async def execute_rowcount(self, sql: str, params: Sequence[Any] = ()) -> int:
|
async def execute_rowcount(self, sql: str, params: Sequence[Any] = ()) -> int:
|
||||||
if self.backend == "sqlite":
|
if self.backend == "sqlite":
|
||||||
cursor = await self._connection.execute(sql, params)
|
connection = self._connection
|
||||||
await self._connection.commit()
|
assert connection is not None
|
||||||
|
cursor = await connection.execute(sql, params)
|
||||||
|
await connection.commit()
|
||||||
rowcount = cursor.rowcount
|
rowcount = cursor.rowcount
|
||||||
await cursor.close()
|
await cursor.close()
|
||||||
return rowcount
|
return rowcount
|
||||||
|
|
||||||
status = await self._connection.execute(self._sql(sql), *params)
|
async with self._postgres_connection() as connection:
|
||||||
|
status = await connection.execute(self._sql(sql), *params)
|
||||||
_, _, count = status.partition(" ")
|
_, _, count = status.partition(" ")
|
||||||
return int(count) if count else 0
|
return int(count) if count else 0
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,14 @@ def test_server_config_reads_redis_url(monkeypatch) -> None:
|
|||||||
assert config.redis_url == "redis://localhost:6379/0"
|
assert config.redis_url == "redis://localhost:6379/0"
|
||||||
|
|
||||||
|
|
||||||
|
def test_server_config_defaults_to_dev_env(monkeypatch) -> None:
|
||||||
|
monkeypatch.delenv("AUTHSOME_ENV", raising=False)
|
||||||
|
|
||||||
|
config = ServerConfig()
|
||||||
|
|
||||||
|
assert config.env == "dev"
|
||||||
|
|
||||||
|
|
||||||
def test_server_config_reads_authsome_database_url(monkeypatch) -> None:
|
def test_server_config_reads_authsome_database_url(monkeypatch) -> None:
|
||||||
monkeypatch.setenv("AUTHSOME_DATABASE_URL", "postgresql://authsome:secret@localhost/authsome")
|
monkeypatch.setenv("AUTHSOME_DATABASE_URL", "postgresql://authsome:secret@localhost/authsome")
|
||||||
monkeypatch.delenv("DATABASE_URL", raising=False)
|
monkeypatch.delenv("DATABASE_URL", raising=False)
|
||||||
@@ -52,6 +60,47 @@ def test_server_config_defaults_preserve_local_paths(tmp_path: Path) -> None:
|
|||||||
assert config.kv_store_dir == tmp_path / "server" / "kv_store"
|
assert config.kv_store_dir == tmp_path / "server" / "kv_store"
|
||||||
|
|
||||||
|
|
||||||
|
def test_server_config_requires_database_url_in_prod(monkeypatch) -> None:
|
||||||
|
monkeypatch.setenv("AUTHSOME_ENV", "prod")
|
||||||
|
monkeypatch.delenv("AUTHSOME_DATABASE_URL", raising=False)
|
||||||
|
monkeypatch.delenv("DATABASE_URL", raising=False)
|
||||||
|
monkeypatch.setenv("AUTHSOME_REDIS_URL", "redis://localhost:6379/0")
|
||||||
|
|
||||||
|
with pytest.raises(ValueError, match="AUTHSOME_DATABASE_URL is required when AUTHSOME_ENV=prod"):
|
||||||
|
ServerConfig()
|
||||||
|
|
||||||
|
|
||||||
|
def test_server_config_requires_redis_url_in_prod(monkeypatch) -> None:
|
||||||
|
monkeypatch.setenv("AUTHSOME_ENV", "prod")
|
||||||
|
monkeypatch.setenv("AUTHSOME_DATABASE_URL", "postgresql://authsome:secret@localhost/authsome")
|
||||||
|
monkeypatch.delenv("DATABASE_URL", raising=False)
|
||||||
|
monkeypatch.delenv("AUTHSOME_REDIS_URL", raising=False)
|
||||||
|
|
||||||
|
with pytest.raises(ValueError, match="AUTHSOME_REDIS_URL is required when AUTHSOME_ENV=prod"):
|
||||||
|
ServerConfig()
|
||||||
|
|
||||||
|
|
||||||
|
def test_server_config_requires_postgres_database_url_in_prod(monkeypatch) -> None:
|
||||||
|
monkeypatch.setenv("AUTHSOME_ENV", "prod")
|
||||||
|
monkeypatch.setenv("AUTHSOME_DATABASE_URL", "sqlite:////tmp/authsome.db")
|
||||||
|
monkeypatch.setenv("AUTHSOME_REDIS_URL", "redis://localhost:6379/0")
|
||||||
|
|
||||||
|
with pytest.raises(ValueError, match="AUTHSOME_DATABASE_URL must be a Postgres URL when AUTHSOME_ENV=prod"):
|
||||||
|
ServerConfig()
|
||||||
|
|
||||||
|
|
||||||
|
def test_server_config_accepts_prod_with_database_and_redis_urls(monkeypatch) -> None:
|
||||||
|
monkeypatch.setenv("AUTHSOME_ENV", "prod")
|
||||||
|
monkeypatch.setenv("AUTHSOME_DATABASE_URL", "postgresql://authsome:secret@localhost/authsome")
|
||||||
|
monkeypatch.setenv("AUTHSOME_REDIS_URL", "redis://localhost:6379/0")
|
||||||
|
|
||||||
|
config = ServerConfig()
|
||||||
|
|
||||||
|
assert config.env == "prod"
|
||||||
|
assert config.database_url == "postgresql://authsome:secret@localhost/authsome"
|
||||||
|
assert config.redis_url == "redis://localhost:6379/0"
|
||||||
|
|
||||||
|
|
||||||
def test_server_config_rejects_invalid_postgres_pool_range() -> None:
|
def test_server_config_rejects_invalid_postgres_pool_range() -> None:
|
||||||
with pytest.raises(ValueError, match="postgres_pool_min_size must be less than or equal to postgres_pool_max_size"):
|
with pytest.raises(ValueError, match="postgres_pool_min_size must be less than or equal to postgres_pool_max_size"):
|
||||||
ServerConfig(postgres_pool_min_size=10, postgres_pool_max_size=2)
|
ServerConfig(postgres_pool_min_size=10, postgres_pool_max_size=2)
|
||||||
|
|||||||
Reference in New Issue
Block a user