atlas-chat 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- atlas/__init__.py +40 -0
- atlas/application/__init__.py +7 -0
- atlas/application/chat/__init__.py +7 -0
- atlas/application/chat/agent/__init__.py +10 -0
- atlas/application/chat/agent/act_loop.py +179 -0
- atlas/application/chat/agent/factory.py +142 -0
- atlas/application/chat/agent/protocols.py +46 -0
- atlas/application/chat/agent/react_loop.py +338 -0
- atlas/application/chat/agent/think_act_loop.py +171 -0
- atlas/application/chat/approval_manager.py +151 -0
- atlas/application/chat/elicitation_manager.py +191 -0
- atlas/application/chat/events/__init__.py +1 -0
- atlas/application/chat/events/agent_event_relay.py +112 -0
- atlas/application/chat/modes/__init__.py +1 -0
- atlas/application/chat/modes/agent.py +125 -0
- atlas/application/chat/modes/plain.py +74 -0
- atlas/application/chat/modes/rag.py +81 -0
- atlas/application/chat/modes/tools.py +179 -0
- atlas/application/chat/orchestrator.py +213 -0
- atlas/application/chat/policies/__init__.py +1 -0
- atlas/application/chat/policies/tool_authorization.py +99 -0
- atlas/application/chat/preprocessors/__init__.py +1 -0
- atlas/application/chat/preprocessors/message_builder.py +92 -0
- atlas/application/chat/preprocessors/prompt_override_service.py +104 -0
- atlas/application/chat/service.py +454 -0
- atlas/application/chat/utilities/__init__.py +6 -0
- atlas/application/chat/utilities/error_handler.py +367 -0
- atlas/application/chat/utilities/event_notifier.py +546 -0
- atlas/application/chat/utilities/file_processor.py +613 -0
- atlas/application/chat/utilities/tool_executor.py +789 -0
- atlas/atlas_chat_cli.py +347 -0
- atlas/atlas_client.py +238 -0
- atlas/core/__init__.py +0 -0
- atlas/core/auth.py +205 -0
- atlas/core/authorization_manager.py +27 -0
- atlas/core/capabilities.py +123 -0
- atlas/core/compliance.py +215 -0
- atlas/core/domain_whitelist.py +147 -0
- atlas/core/domain_whitelist_middleware.py +82 -0
- atlas/core/http_client.py +28 -0
- atlas/core/log_sanitizer.py +102 -0
- atlas/core/metrics_logger.py +59 -0
- atlas/core/middleware.py +131 -0
- atlas/core/otel_config.py +242 -0
- atlas/core/prompt_risk.py +200 -0
- atlas/core/rate_limit.py +0 -0
- atlas/core/rate_limit_middleware.py +64 -0
- atlas/core/security_headers_middleware.py +51 -0
- atlas/domain/__init__.py +37 -0
- atlas/domain/chat/__init__.py +1 -0
- atlas/domain/chat/dtos.py +85 -0
- atlas/domain/errors.py +96 -0
- atlas/domain/messages/__init__.py +12 -0
- atlas/domain/messages/models.py +160 -0
- atlas/domain/rag_mcp_service.py +664 -0
- atlas/domain/sessions/__init__.py +7 -0
- atlas/domain/sessions/models.py +36 -0
- atlas/domain/unified_rag_service.py +371 -0
- atlas/infrastructure/__init__.py +10 -0
- atlas/infrastructure/app_factory.py +135 -0
- atlas/infrastructure/events/__init__.py +1 -0
- atlas/infrastructure/events/cli_event_publisher.py +140 -0
- atlas/infrastructure/events/websocket_publisher.py +140 -0
- atlas/infrastructure/sessions/in_memory_repository.py +56 -0
- atlas/infrastructure/transport/__init__.py +7 -0
- atlas/infrastructure/transport/websocket_connection_adapter.py +33 -0
- atlas/init_cli.py +226 -0
- atlas/interfaces/__init__.py +15 -0
- atlas/interfaces/events.py +134 -0
- atlas/interfaces/llm.py +54 -0
- atlas/interfaces/rag.py +40 -0
- atlas/interfaces/sessions.py +75 -0
- atlas/interfaces/tools.py +57 -0
- atlas/interfaces/transport.py +24 -0
- atlas/main.py +564 -0
- atlas/mcp/api_key_demo/README.md +76 -0
- atlas/mcp/api_key_demo/main.py +172 -0
- atlas/mcp/api_key_demo/run.sh +56 -0
- atlas/mcp/basictable/main.py +147 -0
- atlas/mcp/calculator/main.py +149 -0
- atlas/mcp/code-executor/execution_engine.py +98 -0
- atlas/mcp/code-executor/execution_environment.py +95 -0
- atlas/mcp/code-executor/main.py +528 -0
- atlas/mcp/code-executor/result_processing.py +276 -0
- atlas/mcp/code-executor/script_generation.py +195 -0
- atlas/mcp/code-executor/security_checker.py +140 -0
- atlas/mcp/corporate_cars/main.py +437 -0
- atlas/mcp/csv_reporter/main.py +545 -0
- atlas/mcp/duckduckgo/main.py +182 -0
- atlas/mcp/elicitation_demo/README.md +171 -0
- atlas/mcp/elicitation_demo/main.py +262 -0
- atlas/mcp/env-demo/README.md +158 -0
- atlas/mcp/env-demo/main.py +199 -0
- atlas/mcp/file_size_test/main.py +284 -0
- atlas/mcp/filesystem/main.py +348 -0
- atlas/mcp/image_demo/main.py +113 -0
- atlas/mcp/image_demo/requirements.txt +4 -0
- atlas/mcp/logging_demo/README.md +72 -0
- atlas/mcp/logging_demo/main.py +103 -0
- atlas/mcp/many_tools_demo/main.py +50 -0
- atlas/mcp/order_database/__init__.py +0 -0
- atlas/mcp/order_database/main.py +369 -0
- atlas/mcp/order_database/signal_data.csv +1001 -0
- atlas/mcp/pdfbasic/main.py +394 -0
- atlas/mcp/pptx_generator/main.py +760 -0
- atlas/mcp/pptx_generator/requirements.txt +13 -0
- atlas/mcp/pptx_generator/run_test.sh +1 -0
- atlas/mcp/pptx_generator/test_pptx_generator_security.py +169 -0
- atlas/mcp/progress_demo/main.py +167 -0
- atlas/mcp/progress_updates_demo/QUICKSTART.md +273 -0
- atlas/mcp/progress_updates_demo/README.md +120 -0
- atlas/mcp/progress_updates_demo/main.py +497 -0
- atlas/mcp/prompts/main.py +222 -0
- atlas/mcp/public_demo/main.py +189 -0
- atlas/mcp/sampling_demo/README.md +169 -0
- atlas/mcp/sampling_demo/main.py +234 -0
- atlas/mcp/thinking/main.py +77 -0
- atlas/mcp/tool_planner/main.py +240 -0
- atlas/mcp/ui-demo/badmesh.png +0 -0
- atlas/mcp/ui-demo/main.py +383 -0
- atlas/mcp/ui-demo/templates/button_demo.html +32 -0
- atlas/mcp/ui-demo/templates/data_visualization.html +32 -0
- atlas/mcp/ui-demo/templates/form_demo.html +28 -0
- atlas/mcp/username-override-demo/README.md +320 -0
- atlas/mcp/username-override-demo/main.py +308 -0
- atlas/modules/__init__.py +0 -0
- atlas/modules/config/__init__.py +34 -0
- atlas/modules/config/cli.py +231 -0
- atlas/modules/config/config_manager.py +1096 -0
- atlas/modules/file_storage/__init__.py +22 -0
- atlas/modules/file_storage/cli.py +330 -0
- atlas/modules/file_storage/content_extractor.py +290 -0
- atlas/modules/file_storage/manager.py +295 -0
- atlas/modules/file_storage/mock_s3_client.py +402 -0
- atlas/modules/file_storage/s3_client.py +417 -0
- atlas/modules/llm/__init__.py +19 -0
- atlas/modules/llm/caller.py +287 -0
- atlas/modules/llm/litellm_caller.py +675 -0
- atlas/modules/llm/models.py +19 -0
- atlas/modules/mcp_tools/__init__.py +17 -0
- atlas/modules/mcp_tools/client.py +2123 -0
- atlas/modules/mcp_tools/token_storage.py +556 -0
- atlas/modules/prompts/prompt_provider.py +130 -0
- atlas/modules/rag/__init__.py +24 -0
- atlas/modules/rag/atlas_rag_client.py +336 -0
- atlas/modules/rag/client.py +129 -0
- atlas/routes/admin_routes.py +865 -0
- atlas/routes/config_routes.py +484 -0
- atlas/routes/feedback_routes.py +361 -0
- atlas/routes/files_routes.py +274 -0
- atlas/routes/health_routes.py +40 -0
- atlas/routes/mcp_auth_routes.py +223 -0
- atlas/server_cli.py +164 -0
- atlas/tests/conftest.py +20 -0
- atlas/tests/integration/test_mcp_auth_integration.py +152 -0
- atlas/tests/manual_test_sampling.py +87 -0
- atlas/tests/modules/mcp_tools/test_client_auth.py +226 -0
- atlas/tests/modules/mcp_tools/test_client_env.py +191 -0
- atlas/tests/test_admin_mcp_server_management_routes.py +141 -0
- atlas/tests/test_agent_roa.py +135 -0
- atlas/tests/test_app_factory_smoke.py +47 -0
- atlas/tests/test_approval_manager.py +439 -0
- atlas/tests/test_atlas_client.py +188 -0
- atlas/tests/test_atlas_rag_client.py +447 -0
- atlas/tests/test_atlas_rag_integration.py +224 -0
- atlas/tests/test_attach_file_flow.py +287 -0
- atlas/tests/test_auth_utils.py +165 -0
- atlas/tests/test_backend_public_url.py +185 -0
- atlas/tests/test_banner_logging.py +287 -0
- atlas/tests/test_capability_tokens_and_injection.py +203 -0
- atlas/tests/test_compliance_level.py +54 -0
- atlas/tests/test_compliance_manager.py +253 -0
- atlas/tests/test_config_manager.py +617 -0
- atlas/tests/test_config_manager_paths.py +12 -0
- atlas/tests/test_core_auth.py +18 -0
- atlas/tests/test_core_utils.py +190 -0
- atlas/tests/test_docker_env_sync.py +202 -0
- atlas/tests/test_domain_errors.py +329 -0
- atlas/tests/test_domain_whitelist.py +359 -0
- atlas/tests/test_elicitation_manager.py +408 -0
- atlas/tests/test_elicitation_routing.py +296 -0
- atlas/tests/test_env_demo_server.py +88 -0
- atlas/tests/test_error_classification.py +113 -0
- atlas/tests/test_error_flow_integration.py +116 -0
- atlas/tests/test_feedback_routes.py +333 -0
- atlas/tests/test_file_content_extraction.py +1134 -0
- atlas/tests/test_file_extraction_routes.py +158 -0
- atlas/tests/test_file_library.py +107 -0
- atlas/tests/test_file_manager_unit.py +18 -0
- atlas/tests/test_health_route.py +49 -0
- atlas/tests/test_http_client_stub.py +8 -0
- atlas/tests/test_imports_smoke.py +30 -0
- atlas/tests/test_interfaces_llm_response.py +9 -0
- atlas/tests/test_issue_access_denied_fix.py +136 -0
- atlas/tests/test_llm_env_expansion.py +836 -0
- atlas/tests/test_log_level_sensitive_data.py +285 -0
- atlas/tests/test_mcp_auth_routes.py +341 -0
- atlas/tests/test_mcp_client_auth.py +331 -0
- atlas/tests/test_mcp_data_injection.py +270 -0
- atlas/tests/test_mcp_get_authorized_servers.py +95 -0
- atlas/tests/test_mcp_hot_reload.py +512 -0
- atlas/tests/test_mcp_image_content.py +424 -0
- atlas/tests/test_mcp_logging.py +172 -0
- atlas/tests/test_mcp_progress_updates.py +313 -0
- atlas/tests/test_mcp_prompt_override_system_prompt.py +102 -0
- atlas/tests/test_mcp_prompts_server.py +39 -0
- atlas/tests/test_mcp_tool_result_parsing.py +296 -0
- atlas/tests/test_metrics_logger.py +56 -0
- atlas/tests/test_middleware_auth.py +379 -0
- atlas/tests/test_prompt_risk_and_acl.py +141 -0
- atlas/tests/test_rag_mcp_aggregator.py +204 -0
- atlas/tests/test_rag_mcp_service.py +224 -0
- atlas/tests/test_rate_limit_middleware.py +45 -0
- atlas/tests/test_routes_config_smoke.py +60 -0
- atlas/tests/test_routes_files_download_token.py +41 -0
- atlas/tests/test_routes_files_health.py +18 -0
- atlas/tests/test_runtime_imports.py +53 -0
- atlas/tests/test_sampling_integration.py +482 -0
- atlas/tests/test_security_admin_routes.py +61 -0
- atlas/tests/test_security_capability_tokens.py +65 -0
- atlas/tests/test_security_file_stats_scope.py +21 -0
- atlas/tests/test_security_header_injection.py +191 -0
- atlas/tests/test_security_headers_and_filename.py +63 -0
- atlas/tests/test_shared_session_repository.py +101 -0
- atlas/tests/test_system_prompt_loading.py +181 -0
- atlas/tests/test_token_storage.py +505 -0
- atlas/tests/test_tool_approval_config.py +93 -0
- atlas/tests/test_tool_approval_utils.py +356 -0
- atlas/tests/test_tool_authorization_group_filtering.py +223 -0
- atlas/tests/test_tool_details_in_config.py +108 -0
- atlas/tests/test_tool_planner.py +300 -0
- atlas/tests/test_unified_rag_service.py +398 -0
- atlas/tests/test_username_override_in_approval.py +258 -0
- atlas/tests/test_websocket_auth_header.py +168 -0
- atlas/version.py +6 -0
- atlas_chat-0.1.0.data/data/.env.example +253 -0
- atlas_chat-0.1.0.data/data/config/defaults/compliance-levels.json +44 -0
- atlas_chat-0.1.0.data/data/config/defaults/domain-whitelist.json +123 -0
- atlas_chat-0.1.0.data/data/config/defaults/file-extractors.json +74 -0
- atlas_chat-0.1.0.data/data/config/defaults/help-config.json +198 -0
- atlas_chat-0.1.0.data/data/config/defaults/llmconfig-buggy.yml +11 -0
- atlas_chat-0.1.0.data/data/config/defaults/llmconfig.yml +19 -0
- atlas_chat-0.1.0.data/data/config/defaults/mcp.json +138 -0
- atlas_chat-0.1.0.data/data/config/defaults/rag-sources.json +17 -0
- atlas_chat-0.1.0.data/data/config/defaults/splash-config.json +16 -0
- atlas_chat-0.1.0.dist-info/METADATA +236 -0
- atlas_chat-0.1.0.dist-info/RECORD +250 -0
- atlas_chat-0.1.0.dist-info/WHEEL +5 -0
- atlas_chat-0.1.0.dist-info/entry_points.txt +4 -0
- atlas_chat-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""Test compliance level functionality for MCP servers and data sources."""
|
|
2
|
+
|
|
3
|
+
from atlas.modules.config.config_manager import MCPConfig, MCPServerConfig
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_mcp_server_config_with_compliance_level():
|
|
7
|
+
"""Test that MCPServerConfig accepts and stores compliance_level."""
|
|
8
|
+
config = MCPServerConfig(
|
|
9
|
+
description="Test server",
|
|
10
|
+
compliance_level="SOC2"
|
|
11
|
+
)
|
|
12
|
+
assert config.compliance_level == "SOC2"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_mcp_server_config_without_compliance_level():
|
|
16
|
+
"""Test that MCPServerConfig works without compliance_level (backward compatible)."""
|
|
17
|
+
config = MCPServerConfig(
|
|
18
|
+
description="Test server"
|
|
19
|
+
)
|
|
20
|
+
assert config.compliance_level is None
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_mcp_config_from_dict_with_compliance():
|
|
24
|
+
"""Test that MCPConfig properly parses servers with compliance levels."""
|
|
25
|
+
data = {
|
|
26
|
+
"servers": {
|
|
27
|
+
"test_server": {
|
|
28
|
+
"description": "Test description",
|
|
29
|
+
"compliance_level": "HIPAA"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
config = MCPConfig(**data)
|
|
34
|
+
assert "test_server" in config.servers
|
|
35
|
+
assert config.servers["test_server"].compliance_level == "HIPAA"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_compliance_level_in_config_response():
|
|
39
|
+
"""Test that /api/config returns compliance_level in tools response."""
|
|
40
|
+
# This is an integration test that would require full app setup
|
|
41
|
+
# For now, we verify the model supports it
|
|
42
|
+
config_dict = {
|
|
43
|
+
"description": "PDF processor",
|
|
44
|
+
"author": "Test",
|
|
45
|
+
"compliance_level": "SOC2",
|
|
46
|
+
"groups": ["users"],
|
|
47
|
+
"enabled": True
|
|
48
|
+
}
|
|
49
|
+
server_config = MCPServerConfig(**config_dict)
|
|
50
|
+
|
|
51
|
+
# Verify it can be serialized to dict (as done in API responses)
|
|
52
|
+
as_dict = server_config.model_dump()
|
|
53
|
+
assert as_dict["compliance_level"] == "SOC2"
|
|
54
|
+
assert as_dict["description"] == "PDF processor"
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
"""Comprehensive tests for ComplianceLevelManager."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from tempfile import TemporaryDirectory
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
from atlas.core.compliance import ComplianceLevelManager
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@pytest.fixture
|
|
13
|
+
def sample_compliance_config():
|
|
14
|
+
"""Sample compliance level configuration."""
|
|
15
|
+
return {
|
|
16
|
+
"version": "2.0",
|
|
17
|
+
"mode": "explicit_allowlist",
|
|
18
|
+
"levels": [
|
|
19
|
+
{
|
|
20
|
+
"name": "Public",
|
|
21
|
+
"description": "Publicly accessible",
|
|
22
|
+
"aliases": ["public"],
|
|
23
|
+
"allowed_with": ["Public"]
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"name": "External",
|
|
27
|
+
"description": "External services",
|
|
28
|
+
"aliases": ["ext"],
|
|
29
|
+
"allowed_with": ["External"]
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"name": "Internal",
|
|
33
|
+
"description": "Internal systems",
|
|
34
|
+
"aliases": ["int"],
|
|
35
|
+
"allowed_with": ["Internal"]
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"name": "SOC2",
|
|
39
|
+
"description": "SOC 2 compliant",
|
|
40
|
+
"aliases": ["SOC-2", "SOC 2"],
|
|
41
|
+
"allowed_with": ["SOC2"]
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"name": "HIPAA",
|
|
45
|
+
"description": "HIPAA compliant",
|
|
46
|
+
"aliases": ["HIPAA-Compliant"],
|
|
47
|
+
"allowed_with": ["HIPAA", "SOC2"]
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"name": "FedRAMP",
|
|
51
|
+
"description": "FedRAMP authorized",
|
|
52
|
+
"aliases": ["FedRAMP-Moderate"],
|
|
53
|
+
"allowed_with": ["FedRAMP", "SOC2"]
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@pytest.fixture
|
|
60
|
+
def temp_compliance_config(sample_compliance_config):
|
|
61
|
+
"""Create a temporary compliance config file."""
|
|
62
|
+
with TemporaryDirectory() as tmpdir:
|
|
63
|
+
config_path = Path(tmpdir) / "compliance-levels.json"
|
|
64
|
+
with open(config_path, 'w', encoding='utf-8') as f:
|
|
65
|
+
json.dump(sample_compliance_config, f)
|
|
66
|
+
yield config_path
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class TestComplianceLevelManager:
|
|
70
|
+
"""Tests for ComplianceLevelManager class."""
|
|
71
|
+
|
|
72
|
+
def test_load_config_success(self, temp_compliance_config):
|
|
73
|
+
"""Test loading a valid compliance configuration."""
|
|
74
|
+
manager = ComplianceLevelManager(temp_compliance_config)
|
|
75
|
+
|
|
76
|
+
assert len(manager.levels) == 6
|
|
77
|
+
assert "Public" in manager.levels
|
|
78
|
+
assert "HIPAA" in manager.levels
|
|
79
|
+
assert "FedRAMP" in manager.levels
|
|
80
|
+
assert manager.mode == "explicit_allowlist"
|
|
81
|
+
|
|
82
|
+
def test_load_config_missing_file(self):
|
|
83
|
+
"""Test handling of missing config file."""
|
|
84
|
+
manager = ComplianceLevelManager(Path("/nonexistent/path.json"))
|
|
85
|
+
|
|
86
|
+
# Should not crash, should have empty levels
|
|
87
|
+
assert len(manager.levels) == 0
|
|
88
|
+
|
|
89
|
+
def test_get_canonical_name_exact_match(self, temp_compliance_config):
|
|
90
|
+
"""Test getting canonical name with exact match."""
|
|
91
|
+
manager = ComplianceLevelManager(temp_compliance_config)
|
|
92
|
+
|
|
93
|
+
assert manager.get_canonical_name("Public") == "Public"
|
|
94
|
+
assert manager.get_canonical_name("HIPAA") == "HIPAA"
|
|
95
|
+
assert manager.get_canonical_name("SOC2") == "SOC2"
|
|
96
|
+
|
|
97
|
+
def test_get_canonical_name_alias(self, temp_compliance_config):
|
|
98
|
+
"""Test getting canonical name from alias."""
|
|
99
|
+
manager = ComplianceLevelManager(temp_compliance_config)
|
|
100
|
+
|
|
101
|
+
assert manager.get_canonical_name("SOC 2") == "SOC2"
|
|
102
|
+
assert manager.get_canonical_name("SOC-2") == "SOC2"
|
|
103
|
+
assert manager.get_canonical_name("HIPAA-Compliant") == "HIPAA"
|
|
104
|
+
assert manager.get_canonical_name("FedRAMP-Moderate") == "FedRAMP"
|
|
105
|
+
|
|
106
|
+
def test_get_canonical_name_invalid(self, temp_compliance_config):
|
|
107
|
+
"""Test getting canonical name for invalid level."""
|
|
108
|
+
manager = ComplianceLevelManager(temp_compliance_config)
|
|
109
|
+
|
|
110
|
+
assert manager.get_canonical_name("Invalid") is None
|
|
111
|
+
assert manager.get_canonical_name("SOCII") is None
|
|
112
|
+
assert manager.get_canonical_name(None) is None
|
|
113
|
+
|
|
114
|
+
def test_validate_compliance_level_valid(self, temp_compliance_config):
|
|
115
|
+
"""Test validation of valid compliance levels."""
|
|
116
|
+
manager = ComplianceLevelManager(temp_compliance_config)
|
|
117
|
+
|
|
118
|
+
assert manager.validate_compliance_level("Public") == "Public"
|
|
119
|
+
assert manager.validate_compliance_level("HIPAA") == "HIPAA"
|
|
120
|
+
assert manager.validate_compliance_level("SOC2") == "SOC2"
|
|
121
|
+
|
|
122
|
+
def test_validate_compliance_level_alias(self, temp_compliance_config):
|
|
123
|
+
"""Test validation with alias (should return canonical name)."""
|
|
124
|
+
manager = ComplianceLevelManager(temp_compliance_config)
|
|
125
|
+
|
|
126
|
+
assert manager.validate_compliance_level("SOC 2") == "SOC2"
|
|
127
|
+
assert manager.validate_compliance_level("SOC-2") == "SOC2"
|
|
128
|
+
assert manager.validate_compliance_level("HIPAA-Compliant") == "HIPAA"
|
|
129
|
+
|
|
130
|
+
def test_validate_compliance_level_invalid(self, temp_compliance_config):
|
|
131
|
+
"""Test validation of invalid compliance level (should return None and log)."""
|
|
132
|
+
manager = ComplianceLevelManager(temp_compliance_config)
|
|
133
|
+
|
|
134
|
+
assert manager.validate_compliance_level("InvalidLevel") is None
|
|
135
|
+
assert manager.validate_compliance_level("SOCII") is None
|
|
136
|
+
assert manager.validate_compliance_level("") is None
|
|
137
|
+
assert manager.validate_compliance_level(None) is None
|
|
138
|
+
|
|
139
|
+
def test_is_accessible_same_level(self, temp_compliance_config):
|
|
140
|
+
"""Test access control when user and resource have same level."""
|
|
141
|
+
manager = ComplianceLevelManager(temp_compliance_config)
|
|
142
|
+
|
|
143
|
+
# Each level can access itself
|
|
144
|
+
assert manager.is_accessible("Public", "Public") is True
|
|
145
|
+
assert manager.is_accessible("Internal", "Internal") is True
|
|
146
|
+
assert manager.is_accessible("HIPAA", "HIPAA") is True
|
|
147
|
+
|
|
148
|
+
def test_is_accessible_different_level_not_allowed(self, temp_compliance_config):
|
|
149
|
+
"""Test access control when different levels are not in allowlist."""
|
|
150
|
+
manager = ComplianceLevelManager(temp_compliance_config)
|
|
151
|
+
|
|
152
|
+
# Public cannot access HIPAA
|
|
153
|
+
assert manager.is_accessible("Public", "HIPAA") is False
|
|
154
|
+
|
|
155
|
+
# HIPAA cannot access Public (security!)
|
|
156
|
+
assert manager.is_accessible("HIPAA", "Public") is False
|
|
157
|
+
|
|
158
|
+
# Internal cannot access External
|
|
159
|
+
assert manager.is_accessible("Internal", "External") is False
|
|
160
|
+
|
|
161
|
+
def test_is_accessible_allowlist_grants_access(self, temp_compliance_config):
|
|
162
|
+
"""Test access control when allowlist grants access."""
|
|
163
|
+
manager = ComplianceLevelManager(temp_compliance_config)
|
|
164
|
+
|
|
165
|
+
# HIPAA can access SOC2 (in allowlist)
|
|
166
|
+
assert manager.is_accessible("HIPAA", "SOC2") is True
|
|
167
|
+
|
|
168
|
+
# FedRAMP can access SOC2 (in allowlist)
|
|
169
|
+
assert manager.is_accessible("FedRAMP", "SOC2") is True
|
|
170
|
+
|
|
171
|
+
def test_is_accessible_one_sided_allowlist(self, temp_compliance_config):
|
|
172
|
+
"""Test that allowlist is not bidirectional."""
|
|
173
|
+
manager = ComplianceLevelManager(temp_compliance_config)
|
|
174
|
+
|
|
175
|
+
# HIPAA can access SOC2
|
|
176
|
+
assert manager.is_accessible("HIPAA", "SOC2") is True
|
|
177
|
+
|
|
178
|
+
# But SOC2 cannot access HIPAA (not in SOC2's allowlist)
|
|
179
|
+
assert manager.is_accessible("SOC2", "HIPAA") is False
|
|
180
|
+
|
|
181
|
+
def test_is_accessible_none_is_permissive(self, temp_compliance_config):
|
|
182
|
+
"""Test that None (unset) compliance level is always accessible."""
|
|
183
|
+
manager = ComplianceLevelManager(temp_compliance_config)
|
|
184
|
+
|
|
185
|
+
# None user can access any resource
|
|
186
|
+
assert manager.is_accessible(None, "HIPAA") is True
|
|
187
|
+
assert manager.is_accessible(None, "Public") is True
|
|
188
|
+
|
|
189
|
+
# Any user can access None resource
|
|
190
|
+
assert manager.is_accessible("HIPAA", None) is True
|
|
191
|
+
assert manager.is_accessible("Public", None) is True
|
|
192
|
+
|
|
193
|
+
# None to None
|
|
194
|
+
assert manager.is_accessible(None, None) is True
|
|
195
|
+
|
|
196
|
+
def test_get_accessible_levels_public(self, temp_compliance_config):
|
|
197
|
+
"""Test getting accessible levels for Public."""
|
|
198
|
+
manager = ComplianceLevelManager(temp_compliance_config)
|
|
199
|
+
|
|
200
|
+
accessible = manager.get_accessible_levels("Public")
|
|
201
|
+
|
|
202
|
+
assert accessible == {"Public"}
|
|
203
|
+
|
|
204
|
+
def test_get_accessible_levels_hipaa(self, temp_compliance_config):
|
|
205
|
+
"""Test getting accessible levels for HIPAA."""
|
|
206
|
+
manager = ComplianceLevelManager(temp_compliance_config)
|
|
207
|
+
|
|
208
|
+
accessible = manager.get_accessible_levels("HIPAA")
|
|
209
|
+
|
|
210
|
+
assert accessible == {"HIPAA", "SOC2"}
|
|
211
|
+
|
|
212
|
+
def test_get_accessible_levels_fedramp(self, temp_compliance_config):
|
|
213
|
+
"""Test getting accessible levels for FedRAMP."""
|
|
214
|
+
manager = ComplianceLevelManager(temp_compliance_config)
|
|
215
|
+
|
|
216
|
+
accessible = manager.get_accessible_levels("FedRAMP")
|
|
217
|
+
|
|
218
|
+
assert accessible == {"FedRAMP", "SOC2"}
|
|
219
|
+
|
|
220
|
+
def test_get_accessible_levels_none(self, temp_compliance_config):
|
|
221
|
+
"""Test getting accessible levels when user level is None."""
|
|
222
|
+
manager = ComplianceLevelManager(temp_compliance_config)
|
|
223
|
+
|
|
224
|
+
accessible = manager.get_accessible_levels(None)
|
|
225
|
+
|
|
226
|
+
# Should return all levels
|
|
227
|
+
assert len(accessible) == 6
|
|
228
|
+
assert "Public" in accessible
|
|
229
|
+
assert "HIPAA" in accessible
|
|
230
|
+
|
|
231
|
+
def test_get_all_levels(self, temp_compliance_config):
|
|
232
|
+
"""Test getting all defined compliance levels."""
|
|
233
|
+
manager = ComplianceLevelManager(temp_compliance_config)
|
|
234
|
+
|
|
235
|
+
all_levels = manager.get_all_levels()
|
|
236
|
+
|
|
237
|
+
assert len(all_levels) == 6
|
|
238
|
+
assert "Public" in all_levels
|
|
239
|
+
assert "External" in all_levels
|
|
240
|
+
assert "Internal" in all_levels
|
|
241
|
+
assert "SOC2" in all_levels
|
|
242
|
+
assert "HIPAA" in all_levels
|
|
243
|
+
assert "FedRAMP" in all_levels
|
|
244
|
+
|
|
245
|
+
def test_permissive_mode_no_config(self):
|
|
246
|
+
"""Test permissive mode when no config is loaded."""
|
|
247
|
+
manager = ComplianceLevelManager(Path("/nonexistent"))
|
|
248
|
+
|
|
249
|
+
# Should validate anything in permissive mode
|
|
250
|
+
assert manager.validate_compliance_level("AnyLevel") == "AnyLevel"
|
|
251
|
+
|
|
252
|
+
# Should allow all access
|
|
253
|
+
assert manager.is_accessible("Level1", "Level2") is True
|