"""Tests for the central cloud-role governance classifier + per-driver declared sets. The classifier sorts every requestable cloud role into one of four tiers (normal/elevated/restricted/ungrantable) that later drive visibility / request / approval gating. These tests pin: * the pure ``classify_role`` algorithm — precedence, explicit-set wins, keyword backstop, owner fold-in, bounded-admin allowlist; * each cloud driver's declared sets produce the intended tier for a representative role (so a future edit that drops a set fails loudly). """ from __future__ import annotations import pytest from app.integrations.cloud_role_governance import ( TIER_ELEVATED, TIER_NORMAL, TIER_RESTRICTED, TIER_UNGRANTABLE, classify_role, most_severe, ) # ── central classifier: precedence + sources ───────────────────── def test_ungrantable_wins_over_everything() -> None: # A role listed as both ungrantable and restricted is ungrantable. g = classify_role( "roles/billing.admin", "Billing Admin", ungrantable_keys={"roles/billing.admin"}, restricted_keys={"roles/billing.admin"}, ) assert g.tier == TIER_UNGRANTABLE def test_explicit_restricted_beats_elevated_keyword() -> None: # "AliyunRAMFullAccess" matches the elevated "fullaccess" keyword, but # an explicit restricted listing must win (RAM admin = IAM escalation). g = classify_role( "System:AliyunRAMFullAccess", "AliyunRAMFullAccess", restricted_keys={"System:AliyunRAMFullAccess"}, ) assert g.tier == TIER_RESTRICTED def test_owner_role_keys_folded_into_restricted() -> None: g = classify_role("roles/owner", "Owner", owner_role_keys={"roles/owner"}) assert g.tier == TIER_RESTRICTED assert "owner" in g.reason.lower() def test_admin_keyword_restricted() -> None: assert classify_role("Custom:TidbAdmin", "Tidb Admin").tier == TIER_RESTRICTED assert classify_role("custom-role", "数据库管理员").tier == TIER_RESTRICTED def test_owner_keyword_restricted_even_without_admin_token() -> None: # The legacy is_admin_role sieve missed "Owner" (no "admin" token); # the governance classifier catches it via the \bowner\b pattern. assert classify_role("Custom:ProjectOwner", "Project Owner").tier == TIER_RESTRICTED def test_elevated_keyword_backstop() -> None: assert classify_role("Qcloud-CVM-FullAccess", "CVM FullAccess").tier == TIER_ELEVATED assert classify_role("x", "Contributor").tier == TIER_ELEVATED assert classify_role("roles/editor", "Editor").tier == TIER_ELEVATED def test_normal_default() -> None: assert classify_role("roles/viewer", "Viewer").tier == TIER_NORMAL assert classify_role("System:ReadOnlyAccess", "ReadOnlyAccess").tier == TIER_NORMAL def test_bounded_admin_allowlist_not_restricted() -> None: # DBaaS-Prod-Admin-Role is an intentionally self-serviceable bounded # admin — the admin keyword must NOT fire on it. g = classify_role("DBaaS-Prod-Admin-Role", "DBaaS-Prod-Admin-Role") assert g.tier != TIER_RESTRICTED def test_explicit_elevated_set() -> None: g = classify_role( "roles/iam.serviceAccountUser", "Service Account User", elevated_keys={"roles/iam.serviceAccountUser"}, ) assert g.tier == TIER_ELEVATED def test_most_severe() -> None: assert most_severe(TIER_NORMAL, TIER_ELEVATED, TIER_RESTRICTED) == TIER_RESTRICTED assert most_severe(TIER_NORMAL, TIER_ELEVATED) == TIER_ELEVATED assert most_severe(TIER_UNGRANTABLE, TIER_RESTRICTED) == TIER_UNGRANTABLE assert most_severe() == TIER_NORMAL assert most_severe("bogus") == TIER_NORMAL # ── per-driver wiring ──────────────────────────────────────────── def _gcp(): import json from app.integrations.drivers.gcp_cloud import GcpCloudDriver return GcpCloudDriver(integration_id="t", config={ "organization_id": "1", "service_account_json": json.dumps({ "type": "service_account", "project_id": "p", "private_key": "k", "client_email": "a@b.iam.gserviceaccount.com", }), }) @pytest.mark.parametrize("role_key,scope_type,expected", [ ("roles/billing.viewer", "gcp_project", TIER_UNGRANTABLE), ("roles/resourcemanager.organizationAdmin", "gcp_project", TIER_UNGRANTABLE), ("roles/orgpolicy.policyAdmin", "gcp_project", TIER_UNGRANTABLE), ("roles/owner", "gcp_project", TIER_RESTRICTED), ("roles/editor", "gcp_project", TIER_RESTRICTED), ("roles/iam.securityAdmin", "gcp_project", TIER_RESTRICTED), ("roles/iam.serviceAccountUser", "gcp_project", TIER_ELEVATED), ("roles/viewer", "gcp_project", TIER_NORMAL), ("roles/browser", "gcp_project", TIER_NORMAL), ]) def test_gcp_driver_tiers(role_key, scope_type, expected) -> None: assert _gcp().classify_role(role_key, role_key, scope_type).tier == expected def test_gcp_billing_projectmanager_not_ungrantable() -> None: # projectManager IS project-grantable — must not be swept up with the # billing.* family. g = _gcp().classify_role( "roles/billing.projectManager", "Project Billing Manager", "gcp_project", ) assert g.tier != TIER_UNGRANTABLE def _build(provider): """Best-effort minimal driver instance for tier wiring checks.""" cfgs = { "aws": {"access_key_id": "x", "secret_access_key": "y", "region": "us-east-1"}, "azure": {"tenant_id": "t", "client_id": "c", "client_secret": "s", "subscription_id": "su"}, "aliyun": {"access_key_id": "x", "access_key_secret": "y"}, "tencent": {"secret_id": "x", "secret_key": "y"}, "alicloud_intl": {"access_key_id": "x", "access_key_secret": "y"}, } if provider == "aws": from app.integrations.drivers.aws_cloud import AwsCloudDriver as C elif provider == "azure": from app.integrations.drivers.azure_cloud import AzureCloudDriver as C elif provider == "aliyun": from app.integrations.drivers.aliyun_cloud import AliyunCloudDriver as C elif provider == "tencent": from app.integrations.drivers.tencent_cloud import TencentCloudDriver as C else: from app.integrations.drivers.alicloud_intl_cloud import AlicloudIntlCloudDriver as C return C(integration_id="t", config=cfgs[provider]) @pytest.mark.parametrize("provider,role_key,scope_type,expected", [ ("aws", "arn:aws:iam::aws:policy/AdministratorAccess", "aws_account", TIER_RESTRICTED), ("aws", "arn:aws:iam::aws:policy/IAMFullAccess", "aws_account", TIER_RESTRICTED), ("aws", "arn:aws:iam::aws:policy/PowerUserAccess", "aws_account", TIER_ELEVATED), ("aws", "arn:aws:iam::aws:policy/ReadOnlyAccess", "aws_account", TIER_NORMAL), ("aliyun", "System:AdministratorAccess", "aliyun_account", TIER_RESTRICTED), ("aliyun", "System:AliyunRAMFullAccess", "aliyun_account", TIER_RESTRICTED), ("aliyun", "System:AliyunBSSFullAccess", "aliyun_account", TIER_ELEVATED), ("aliyun", "System:ReadOnlyAccess", "aliyun_account", TIER_NORMAL), ("tencent", "AdministratorAccess", "tencent_account", TIER_RESTRICTED), ("tencent", "QcloudCamFullAccess", "tencent_account", TIER_RESTRICTED), # CAM role-management presets grant privilege escalation (mint a role, # attach admin, assume / authorize onto a sub-account). They carry no # "admin" keyword, so without the explicit restricted listing the # "FullAccess" token would land them at elevated (employee-visible). # Pin restricted so a future edit that drops them fails loudly. ("tencent", "QcloudCamRoleFullAccess", "tencent_account", TIER_RESTRICTED), ("tencent", "QcloudCamSubaccountsAuthorizeRoleFullAccess", "tencent_account", TIER_RESTRICTED), ("tencent", "QcloudCVMFullAccess", "tencent_account", TIER_ELEVATED), ("tencent", "ReadOnlyAccess", "tencent_account", TIER_NORMAL), ]) def test_other_driver_tiers(provider, role_key, scope_type, expected) -> None: assert _build(provider).classify_role(role_key, role_key, scope_type).tier == expected def test_azure_driver_tiers() -> None: d = _build("azure") rd = "/providers/Microsoft.Authorization/roleDefinitions/" assert d.classify_role(rd + "8e3af657-a8ff-443c-a75c-2fe8c4bcb635", "Owner", "azure_subscription").tier == TIER_RESTRICTED assert d.classify_role(rd + "18d7d88d-d35e-4fb5-a5c3-7773c20a72d9", "User Access Administrator", "azure_subscription").tier == TIER_RESTRICTED assert d.classify_role(rd + "b24988ac-6180-42a0-ab88-20f7382dd24c", "Contributor", "azure_subscription").tier == TIER_ELEVATED def test_alicloud_intl_bounded_admin_elevated() -> None: d = _build("alicloud_intl") # admin = owner-equivalent → restricted assert d.classify_role("admin", "admin", "aliyun_account").tier == TIER_RESTRICTED # DBaaS-Prod-Admin-Role = bounded admin, explicitly elevated assert d.classify_role("DBaaS-Prod-Admin-Role", "DBaaS-Prod-Admin-Role", "aliyun_account").tier == TIER_ELEVATED