diff --git a/tests/providers/okta/services/signon/signon_fixtures.py b/tests/providers/okta/services/signon/signon_fixtures.py
new file mode 100644
index 0000000000..99859fad81
--- /dev/null
+++ b/tests/providers/okta/services/signon/signon_fixtures.py
@@ -0,0 +1,124 @@
+"""Shared helpers for `signon` service check tests.
+
+The original idle-timeout check test file defined these helpers locally;
+they were extracted here so the four checks added on top of the same
+service (`signon_global_session_lifetime_18h`,
+`signon_global_session_cookies_not_persistent`,
+`signon_global_session_policy_network_zone_enforced`,
+`signon_dod_warning_banner_configured`) can reuse them without copy-paste.
+"""
+
+from unittest import mock
+
+from prowler.providers.okta.services.signon.signon_service import (
+ GlobalSessionPolicy,
+ GlobalSessionPolicyRule,
+ SignInPage,
+)
+from tests.providers.okta.okta_fixtures import set_mocked_okta_provider
+
+
+def build_signon_client(
+ policies: dict = None,
+ audit_config: dict = None,
+ sign_in_pages: dict = None,
+):
+ client = mock.MagicMock()
+ client.global_session_policies = policies or {}
+ client.provider = set_mocked_okta_provider()
+ client.audit_config = audit_config or {}
+ client.sign_in_pages = sign_in_pages or {}
+ return client
+
+
+def default_policy(rules):
+ return GlobalSessionPolicy(
+ id="pol-default",
+ name="Default Policy",
+ priority=99,
+ status="ACTIVE",
+ is_default=True,
+ rules=rules,
+ )
+
+
+def custom_policy(rules, name: str = "Admins Policy"):
+ return GlobalSessionPolicy(
+ id="pol-custom",
+ name=name,
+ priority=1,
+ status="ACTIVE",
+ is_default=False,
+ rules=rules,
+ )
+
+
+def default_rule(
+ idle_min: int = 480,
+ lifetime_min: int = None,
+ use_persistent_cookie: bool = None,
+ priority: int = 2,
+ status: str = "ACTIVE",
+):
+ return GlobalSessionPolicyRule(
+ id="rule-default",
+ name="Default Rule",
+ priority=priority,
+ status=status,
+ is_default=True,
+ max_session_idle_minutes=idle_min,
+ max_session_lifetime_minutes=lifetime_min,
+ use_persistent_cookie=use_persistent_cookie,
+ )
+
+
+def non_default_rule(
+ name: str,
+ *,
+ idle_min: int = None,
+ lifetime_min: int = None,
+ use_persistent_cookie: bool = None,
+ network_zones_include: list = None,
+ network_zones_exclude: list = None,
+ priority: int = 1,
+ status: str = "ACTIVE",
+):
+ return GlobalSessionPolicyRule(
+ id=f"rule-{name.lower().replace(' ', '-')}",
+ name=name,
+ priority=priority,
+ status=status,
+ is_default=False,
+ max_session_idle_minutes=idle_min,
+ max_session_lifetime_minutes=lifetime_min,
+ use_persistent_cookie=use_persistent_cookie,
+ network_zones_include=network_zones_include or [],
+ network_zones_exclude=network_zones_exclude or [],
+ )
+
+
+def sign_in_page(
+ brand_id: str = "brand-1",
+ brand_name: str = "Default Brand",
+ is_customized: bool = True,
+ page_content: str = None,
+ fetch_error: str = None,
+):
+ return SignInPage(
+ brand_id=brand_id,
+ brand_name=brand_name,
+ is_customized=is_customized,
+ page_content=page_content,
+ fetch_error=fetch_error,
+ )
+
+
+# Two distinctive marker phrases from the DTM-08-060 banner — enough to
+# meet the check's MIN_MARKER_MATCHES=2 threshold without reproducing the
+# full ~1300-char banner verbatim in tests.
+DOD_BANNER_HTML_SNIPPET = (
+ "
You are accessing a U.S. Government (USG) Information System "
+ "(IS) that is provided for USG-authorized use only. "
+ "Communications using, or data stored on, this IS may be intercepted, "
+ "searched, monitored, and recorded.
"
+)
diff --git a/tests/providers/okta/services/signon/signon_global_session_idle_timeout_15min/signon_global_session_idle_timeout_15min_test.py b/tests/providers/okta/services/signon/signon_global_session_idle_timeout_15min/signon_global_session_idle_timeout_15min_test.py
index 912fd2014e..690eaaf771 100644
--- a/tests/providers/okta/services/signon/signon_global_session_idle_timeout_15min/signon_global_session_idle_timeout_15min_test.py
+++ b/tests/providers/okta/services/signon/signon_global_session_idle_timeout_15min/signon_global_session_idle_timeout_15min_test.py
@@ -5,6 +5,13 @@ from prowler.providers.okta.services.signon.signon_service import (
GlobalSessionPolicyRule,
)
from tests.providers.okta.okta_fixtures import set_mocked_okta_provider
+from tests.providers.okta.services.signon.signon_fixtures import (
+ build_signon_client,
+ custom_policy,
+ default_policy,
+ default_rule,
+ non_default_rule,
+)
CHECK_PATH = (
"prowler.providers.okta.services.signon."
@@ -13,61 +20,9 @@ CHECK_PATH = (
)
-def _build_signon_client(policies, audit_config: dict = None):
- client = mock.MagicMock()
- client.global_session_policies = policies
- client.provider = set_mocked_okta_provider()
- client.audit_config = audit_config or {}
- return client
-
-
-def _default_policy(rules):
- return GlobalSessionPolicy(
- id="pol-default",
- name="Default Policy",
- priority=99,
- status="ACTIVE",
- is_default=True,
- rules=rules,
- )
-
-
-def _custom_policy(rules):
- return GlobalSessionPolicy(
- id="pol-custom",
- name="Admins Policy",
- priority=1,
- status="ACTIVE",
- is_default=False,
- rules=rules,
- )
-
-
-def _default_rule(idle_min=480, priority=2, status="ACTIVE"):
- return GlobalSessionPolicyRule(
- id="rule-default",
- name="Default Rule",
- priority=priority,
- status=status,
- is_default=True,
- max_session_idle_minutes=idle_min,
- )
-
-
-def _non_default_rule(name, idle_min, priority=1, status="ACTIVE"):
- return GlobalSessionPolicyRule(
- id=f"rule-{name.lower().replace(' ', '-')}",
- name=name,
- priority=priority,
- status=status,
- is_default=False,
- max_session_idle_minutes=idle_min,
- )
-
-
class Test_signon_global_session_idle_timeout_15min:
def test_no_policies(self):
- signon_client = _build_signon_client({})
+ signon_client = build_signon_client({})
with (
mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
@@ -85,13 +40,13 @@ class Test_signon_global_session_idle_timeout_15min:
assert "was not found" in findings[0].status_extended
def test_pass_when_priority_one_non_default_rule_is_compliant(self):
- policy = _default_policy(
+ policy = default_policy(
[
- _non_default_rule("Strict 15min", 15, priority=1),
- _default_rule(priority=2),
+ non_default_rule("Strict 15min", idle_min=15, priority=1),
+ default_rule(priority=2),
]
)
- signon_client = _build_signon_client({"pol-default": policy})
+ signon_client = build_signon_client({"pol-default": policy})
with (
mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
@@ -110,8 +65,8 @@ class Test_signon_global_session_idle_timeout_15min:
assert "Priority 1 non-default rule" in findings[0].status_extended
def test_fail_when_only_default_rule(self):
- policy = _default_policy([_default_rule(priority=1)])
- signon_client = _build_signon_client({"pol-default": policy})
+ policy = default_policy([default_rule(priority=1)])
+ signon_client = build_signon_client({"pol-default": policy})
with (
mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
@@ -131,10 +86,7 @@ class Test_signon_global_session_idle_timeout_15min:
)
def test_fail_when_priority_one_non_default_rule_has_null_idle(self):
- # Rules without a session block leave max_session_idle_minutes as
- # None. The check must treat those as non-compliant — they cannot
- # enforce any timeout.
- policy = _default_policy(
+ policy = default_policy(
[
GlobalSessionPolicyRule(
id="rule-no-session",
@@ -144,10 +96,10 @@ class Test_signon_global_session_idle_timeout_15min:
is_default=False,
max_session_idle_minutes=None,
),
- _default_rule(priority=2),
+ default_rule(priority=2),
]
)
- signon_client = _build_signon_client({"pol-default": policy})
+ signon_client = build_signon_client({"pol-default": policy})
with (
mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
@@ -166,13 +118,13 @@ class Test_signon_global_session_idle_timeout_15min:
assert "does not define" in findings[0].status_extended
def test_fail_when_priority_one_non_default_rule_exceeds_threshold(self):
- policy = _default_policy(
+ policy = default_policy(
[
- _non_default_rule("Loose 60min", 60, priority=1),
- _default_rule(priority=2),
+ non_default_rule("Loose 60min", idle_min=60, priority=1),
+ default_rule(priority=2),
]
)
- signon_client = _build_signon_client({"pol-default": policy})
+ signon_client = build_signon_client({"pol-default": policy})
with (
mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
@@ -191,13 +143,13 @@ class Test_signon_global_session_idle_timeout_15min:
assert "exceeding the configured threshold" in findings[0].status_extended
def test_fail_when_compliant_non_default_rule_is_not_priority_one(self):
- policy = _default_policy(
+ policy = default_policy(
[
- _default_rule(priority=1),
- _non_default_rule("Strict 15min", 15, priority=2),
+ default_rule(priority=1),
+ non_default_rule("Strict 15min", idle_min=15, priority=2),
]
)
- signon_client = _build_signon_client({"pol-default": policy})
+ signon_client = build_signon_client({"pol-default": policy})
with (
mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
@@ -217,20 +169,23 @@ class Test_signon_global_session_idle_timeout_15min:
)
def test_ignores_other_custom_policies(self):
- default_policy = _default_policy(
+ default_policy_with_strict_rule = default_policy(
[
- _non_default_rule("Strict 15min", 15, priority=1),
- _default_rule(priority=2),
+ non_default_rule("Strict 15min", idle_min=15, priority=1),
+ default_rule(priority=2),
]
)
- custom_policy = _custom_policy(
+ custom_loose_policy = custom_policy(
[
- _non_default_rule("Loose Admin Rule", 60, priority=1),
- _default_rule(priority=2),
+ non_default_rule("Loose Admin Rule", idle_min=60, priority=1),
+ default_rule(priority=2),
]
)
- signon_client = _build_signon_client(
- {"pol-custom": custom_policy, "pol-default": default_policy}
+ signon_client = build_signon_client(
+ {
+ "pol-custom": custom_loose_policy,
+ "pol-default": default_policy_with_strict_rule,
+ }
)
with (
mock.patch(
@@ -255,9 +210,9 @@ class Test_signon_global_session_idle_timeout_15min:
priority=99,
status="INACTIVE",
is_default=True,
- rules=[_non_default_rule("Strict 15min", 15, priority=1)],
+ rules=[non_default_rule("Strict 15min", idle_min=15, priority=1)],
)
- signon_client = _build_signon_client({"pol-default": policy})
+ signon_client = build_signon_client({"pol-default": policy})
with (
mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
@@ -275,15 +230,13 @@ class Test_signon_global_session_idle_timeout_15min:
assert "status 'INACTIVE'" in findings[0].status_extended
def test_threshold_overridden_via_audit_config(self):
- # 30-minute rule fails the STIG default of 15, but passes a relaxed
- # threshold of 60 minutes set in audit_config.
- policy = _default_policy(
+ policy = default_policy(
[
- _non_default_rule("Relaxed 30min", 30, priority=1),
- _default_rule(priority=2),
+ non_default_rule("Relaxed 30min", idle_min=30, priority=1),
+ default_rule(priority=2),
]
)
- signon_client = _build_signon_client(
+ signon_client = build_signon_client(
{"pol-default": policy},
audit_config={"okta_max_session_idle_minutes": 60},
)