719d5c5719
Admin settings for web login whitelist, blocked IP list with unblock, and optional fail2ban ignoreip sync for SSH jail. Co-authored-by: Cursor <cursoragent@cursor.com>
89 lines
2.6 KiB
Python
89 lines
2.6 KiB
Python
"""Login security whitelist and unblock."""
|
|
|
|
from datetime import datetime, timezone
|
|
|
|
from sqlalchemy import delete
|
|
|
|
from app.models.login_attempt import LoginAttempt
|
|
from app.services.login_security_settings import (
|
|
clear_web_login_block,
|
|
get_effective_login_security_config,
|
|
is_ip_login_whitelisted,
|
|
list_web_login_blocks,
|
|
parse_ip_whitelist_text,
|
|
upsert_login_security_settings,
|
|
)
|
|
|
|
|
|
def test_parse_ip_whitelist_text():
|
|
assert parse_ip_whitelist_text("192.168.160.3\n192.168.160.4") == [
|
|
"192.168.160.3",
|
|
"192.168.160.4",
|
|
]
|
|
assert parse_ip_whitelist_text("192.168.160.3, 10.0.0.1") == [
|
|
"192.168.160.3",
|
|
"10.0.0.1",
|
|
]
|
|
assert parse_ip_whitelist_text("not-an-ip\n192.168.1.1") == ["192.168.1.1"]
|
|
|
|
|
|
def test_whitelisted_ip_not_blocked(client, db_session, monkeypatch):
|
|
monkeypatch.setenv("SAC_LOGIN_MAX_FAILURES", "2")
|
|
monkeypatch.setenv("SAC_LOGIN_ALERT_TELEGRAM", "false")
|
|
monkeypatch.setattr(
|
|
"app.services.login_rate_limit.client_ip_from_request",
|
|
lambda _request: "192.168.160.3",
|
|
)
|
|
from app.config import get_settings
|
|
|
|
get_settings.cache_clear()
|
|
db_session.execute(delete(LoginAttempt))
|
|
db_session.commit()
|
|
|
|
upsert_login_security_settings(
|
|
db_session,
|
|
ip_whitelist_text="192.168.160.3",
|
|
sync_fail2ban=False,
|
|
)
|
|
|
|
for _ in range(5):
|
|
r = client.post(
|
|
"/api/v1/auth/login",
|
|
json={"username": "test-admin", "password": "wrong"},
|
|
)
|
|
assert r.status_code == 401
|
|
|
|
get_settings.cache_clear()
|
|
|
|
|
|
def test_list_web_blocks_and_clear(db_session, monkeypatch):
|
|
monkeypatch.setenv("SAC_LOGIN_MAX_FAILURES", "2")
|
|
monkeypatch.setenv("SAC_LOGIN_FAILURE_WINDOW_MINUTES", "15")
|
|
from app.config import get_settings
|
|
|
|
get_settings.cache_clear()
|
|
|
|
now = datetime.now(timezone.utc)
|
|
db_session.add(
|
|
LoginAttempt(ip_address="203.0.113.50", username="bad", success=False, created_at=now)
|
|
)
|
|
db_session.add(
|
|
LoginAttempt(ip_address="203.0.113.50", username="bad", success=False, created_at=now)
|
|
)
|
|
db_session.commit()
|
|
|
|
blocks = list_web_login_blocks(db_session)
|
|
assert any(b.ip_address == "203.0.113.50" for b in blocks)
|
|
|
|
deleted = clear_web_login_block(db_session, "203.0.113.50")
|
|
assert deleted >= 2
|
|
assert not list_web_login_blocks(db_session)
|
|
|
|
get_settings.cache_clear()
|
|
|
|
|
|
def test_is_ip_login_whitelisted():
|
|
wl = ("192.168.160.3",)
|
|
assert is_ip_login_whitelisted("192.168.160.3", wl)
|
|
assert not is_ip_login_whitelisted("192.168.160.4", wl)
|