chore(home): mirror from kalinamall (9883e6a) with papatramp URLs
This commit is contained in:
@@ -0,0 +1,339 @@
|
||||
"""Tests for RDG 302→303 session flap rule."""
|
||||
|
||||
import uuid
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
import pytest
|
||||
|
||||
from app.config import get_settings
|
||||
from app.models import Problem
|
||||
from app.services.ingest import ingest_event
|
||||
from app.services.problems import maybe_create_problem
|
||||
from app.services.problem_rules import RULE_RDG_SESSION_FLAP
|
||||
from app.services.rdg_session_flap import (
|
||||
evaluate_rdg_session_flap,
|
||||
event_has_rdg_flap,
|
||||
find_rdg_success_before_end,
|
||||
resolve_rdg_flap_summary,
|
||||
resolve_rdg_qwinsta_enabled,
|
||||
)
|
||||
from app.services.event_summary import event_to_summary
|
||||
from tests.test_ingest import VALID_EVENT
|
||||
|
||||
|
||||
def _payload(**overrides):
|
||||
base = {
|
||||
**VALID_EVENT,
|
||||
"event_id": str(uuid.uuid4()),
|
||||
"occurred_at": datetime.now(timezone.utc).isoformat(),
|
||||
}
|
||||
base.update(overrides)
|
||||
return base
|
||||
|
||||
|
||||
def _ingest(db, occurred_at: datetime, **overrides):
|
||||
payload = _payload(**overrides)
|
||||
payload["occurred_at"] = occurred_at.isoformat()
|
||||
event, _ = ingest_event(db, payload)
|
||||
db.flush()
|
||||
return event
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def rdg_settings(monkeypatch):
|
||||
monkeypatch.setenv("SAC_RDG_FLAP_WINDOW_MIN_SEC", "1")
|
||||
monkeypatch.setenv("SAC_RDG_FLAP_WINDOW_MAX_SEC", "10")
|
||||
monkeypatch.setenv("SAC_RDG_FLAP_DEDUP_SEC", "30")
|
||||
get_settings.cache_clear()
|
||||
yield
|
||||
get_settings.cache_clear()
|
||||
|
||||
|
||||
def test_rdg_flap_detects_302_then_303(db_session, rdg_settings):
|
||||
t0 = datetime.now(timezone.utc)
|
||||
user = "B26\\test.user"
|
||||
details = {"user": user, "internal_ip": "192.168.163.32"}
|
||||
|
||||
_ingest(
|
||||
db_session,
|
||||
t0,
|
||||
type="rdg.connection.success",
|
||||
category="auth",
|
||||
severity="info",
|
||||
title="RD Gateway event 302",
|
||||
summary="302",
|
||||
details=details,
|
||||
)
|
||||
end = _ingest(
|
||||
db_session,
|
||||
t0 + timedelta(seconds=4),
|
||||
type="rdg.connection.disconnected",
|
||||
category="auth",
|
||||
severity="info",
|
||||
title="RD Gateway event 303",
|
||||
summary="303",
|
||||
details=details,
|
||||
)
|
||||
|
||||
match = evaluate_rdg_session_flap(db_session, end)
|
||||
assert match is not None
|
||||
assert match.rule_id == RULE_RDG_SESSION_FLAP
|
||||
assert event_has_rdg_flap(end) is True
|
||||
|
||||
problem, created = maybe_create_problem(db_session, end)
|
||||
assert created is True
|
||||
assert problem.rule_id == RULE_RDG_SESSION_FLAP
|
||||
|
||||
|
||||
def test_rdg_flap_ignores_gap_over_10_sec(db_session, rdg_settings):
|
||||
t0 = datetime.now(timezone.utc)
|
||||
user = "B26\\slow.user"
|
||||
details = {"user": user}
|
||||
|
||||
_ingest(
|
||||
db_session,
|
||||
t0,
|
||||
type="rdg.connection.success",
|
||||
category="auth",
|
||||
severity="info",
|
||||
title="302",
|
||||
summary="302",
|
||||
details=details,
|
||||
)
|
||||
end = _ingest(
|
||||
db_session,
|
||||
t0 + timedelta(seconds=15),
|
||||
type="rdg.connection.disconnected",
|
||||
category="auth",
|
||||
severity="info",
|
||||
title="303",
|
||||
summary="303",
|
||||
details=details,
|
||||
)
|
||||
|
||||
assert find_rdg_success_before_end(db_session, end) is None
|
||||
assert evaluate_rdg_session_flap(db_session, end) is None
|
||||
|
||||
|
||||
def test_rdg_flap_dedup_within_30_sec(db_session, rdg_settings):
|
||||
t0 = datetime.now(timezone.utc)
|
||||
user = "B26\\dup.user"
|
||||
details = {"user": user}
|
||||
|
||||
def pair(at: datetime):
|
||||
_ingest(
|
||||
db_session,
|
||||
at,
|
||||
type="rdg.connection.success",
|
||||
category="auth",
|
||||
severity="info",
|
||||
title="302",
|
||||
summary="302",
|
||||
details=details,
|
||||
)
|
||||
return _ingest(
|
||||
db_session,
|
||||
at + timedelta(seconds=5),
|
||||
type="rdg.connection.disconnected",
|
||||
category="auth",
|
||||
severity="info",
|
||||
title="303",
|
||||
summary="303",
|
||||
details=details,
|
||||
)
|
||||
|
||||
end1 = pair(t0)
|
||||
maybe_create_problem(db_session, end1)
|
||||
db_session.flush()
|
||||
|
||||
end2 = pair(t0 + timedelta(seconds=10))
|
||||
maybe_create_problem(db_session, end2)
|
||||
db_session.flush()
|
||||
|
||||
from sqlalchemy import func, select
|
||||
|
||||
open_count = db_session.scalar(
|
||||
select(func.count()).select_from(Problem).where(
|
||||
Problem.rule_id == RULE_RDG_SESSION_FLAP,
|
||||
Problem.status == "open",
|
||||
)
|
||||
)
|
||||
assert open_count == 1
|
||||
|
||||
|
||||
def test_resolve_rdg_flap_summary_for_302_and_303(db_session, rdg_settings):
|
||||
t0 = datetime.now(timezone.utc)
|
||||
user = "B26\\pair.user"
|
||||
details = {"user": user, "internal_ip": "192.168.163.48"}
|
||||
|
||||
start = _ingest(
|
||||
db_session,
|
||||
t0,
|
||||
type="rdg.connection.success",
|
||||
category="auth",
|
||||
severity="warning",
|
||||
title="RD Gateway event 302",
|
||||
summary="302",
|
||||
details=details,
|
||||
)
|
||||
end = _ingest(
|
||||
db_session,
|
||||
t0 + timedelta(seconds=5),
|
||||
type="rdg.connection.disconnected",
|
||||
category="auth",
|
||||
severity="info",
|
||||
title="RD Gateway event 303",
|
||||
summary="303",
|
||||
details=details,
|
||||
)
|
||||
evaluate_rdg_session_flap(db_session, end)
|
||||
db_session.flush()
|
||||
|
||||
end_flap, end_pair, end_qwinsta = resolve_rdg_flap_summary(db_session, end)
|
||||
start_flap, start_pair, start_qwinsta = resolve_rdg_flap_summary(db_session, start)
|
||||
|
||||
assert end_flap is True
|
||||
assert end_pair == start.id
|
||||
assert end_qwinsta == start.id
|
||||
|
||||
assert start_flap is True
|
||||
assert start_pair == end.id
|
||||
assert start_qwinsta == start.id
|
||||
|
||||
end_summary = event_to_summary(end, db_session)
|
||||
start_summary = event_to_summary(start, db_session)
|
||||
assert end_summary.rdg_flap is True
|
||||
assert start_summary.rdg_flap is True
|
||||
assert start_summary.rdg_flap_qwinsta_event_id == start.id
|
||||
assert start_summary.rdg_qwinsta_enabled is True
|
||||
assert end_summary.rdg_qwinsta_enabled is False
|
||||
|
||||
|
||||
def test_rdg_qwinsta_disabled_after_normal_session_end(db_session, rdg_settings):
|
||||
t0 = datetime.now(timezone.utc)
|
||||
user = "B26\\normal.user"
|
||||
details = {"user": user, "internal_ip": "192.168.163.49"}
|
||||
|
||||
start = _ingest(
|
||||
db_session,
|
||||
t0,
|
||||
type="rdg.connection.success",
|
||||
category="auth",
|
||||
severity="info",
|
||||
title="302",
|
||||
summary="302",
|
||||
details=details,
|
||||
)
|
||||
end = _ingest(
|
||||
db_session,
|
||||
t0 + timedelta(minutes=20),
|
||||
type="rdg.connection.disconnected",
|
||||
category="auth",
|
||||
severity="info",
|
||||
title="303",
|
||||
summary="303",
|
||||
details=details,
|
||||
)
|
||||
|
||||
assert resolve_rdg_qwinsta_enabled(db_session, start) is False
|
||||
assert resolve_rdg_qwinsta_enabled(db_session, end) is False
|
||||
|
||||
start_summary = event_to_summary(start, db_session)
|
||||
end_summary = event_to_summary(end, db_session)
|
||||
assert start_summary.rdg_qwinsta_enabled is False
|
||||
assert end_summary.rdg_qwinsta_enabled is False
|
||||
|
||||
|
||||
def test_rdg_qwinsta_enabled_while_session_open(db_session, rdg_settings):
|
||||
t0 = datetime.now(timezone.utc)
|
||||
details = {"user": r"B26\active.user", "internal_ip": "192.168.163.50"}
|
||||
|
||||
start = _ingest(
|
||||
db_session,
|
||||
t0,
|
||||
type="rdg.connection.success",
|
||||
category="auth",
|
||||
severity="info",
|
||||
title="302",
|
||||
summary="302",
|
||||
details=details,
|
||||
)
|
||||
|
||||
assert resolve_rdg_qwinsta_enabled(db_session, start) is True
|
||||
assert event_to_summary(start, db_session).rdg_qwinsta_enabled is True
|
||||
|
||||
|
||||
def test_rdg_qwinsta_disabled_on_flap_302_after_later_success(db_session, rdg_settings):
|
||||
t0 = datetime.now(timezone.utc)
|
||||
user = r"B26\m.semenova"
|
||||
details = {"user": user, "internal_ip": "192.168.164.45"}
|
||||
|
||||
flap_start = _ingest(
|
||||
db_session,
|
||||
t0,
|
||||
type="rdg.connection.success",
|
||||
category="auth",
|
||||
severity="warning",
|
||||
title="302",
|
||||
summary="302",
|
||||
details=details,
|
||||
)
|
||||
flap_end = _ingest(
|
||||
db_session,
|
||||
t0 + timedelta(seconds=5),
|
||||
type="rdg.connection.disconnected",
|
||||
category="auth",
|
||||
severity="info",
|
||||
title="303",
|
||||
summary="303",
|
||||
details=details,
|
||||
)
|
||||
evaluate_rdg_session_flap(db_session, flap_end)
|
||||
db_session.flush()
|
||||
|
||||
assert resolve_rdg_qwinsta_enabled(db_session, flap_start) is True
|
||||
|
||||
_ingest(
|
||||
db_session,
|
||||
t0 + timedelta(minutes=2, seconds=44),
|
||||
type="rdg.connection.success",
|
||||
category="auth",
|
||||
severity="warning",
|
||||
title="302",
|
||||
summary="302",
|
||||
details=details,
|
||||
)
|
||||
|
||||
assert resolve_rdg_qwinsta_enabled(db_session, flap_start) is False
|
||||
assert event_to_summary(flap_start, db_session).rdg_qwinsta_enabled is False
|
||||
|
||||
|
||||
def test_rdg_qwinsta_stays_enabled_when_unrelated_303_without_internal_ip(db_session, rdg_settings):
|
||||
t0 = datetime.now(timezone.utc)
|
||||
user = "B26\\khodasevich"
|
||||
details_302 = {"user": user, "internal_ip": "192.168.160.209"}
|
||||
details_303_other = {"user": user}
|
||||
|
||||
start = _ingest(
|
||||
db_session,
|
||||
t0,
|
||||
type="rdg.connection.success",
|
||||
category="auth",
|
||||
severity="warning",
|
||||
title="302",
|
||||
summary="302",
|
||||
details=details_302,
|
||||
)
|
||||
_ingest(
|
||||
db_session,
|
||||
t0 + timedelta(minutes=5),
|
||||
type="rdg.connection.disconnected",
|
||||
category="auth",
|
||||
severity="info",
|
||||
title="303",
|
||||
summary="303",
|
||||
details=details_303_other,
|
||||
)
|
||||
|
||||
assert resolve_rdg_qwinsta_enabled(db_session, start) is True
|
||||
assert event_to_summary(start, db_session).rdg_qwinsta_enabled is True
|
||||
Reference in New Issue
Block a user