"""Effective ownership for the unified cloud resource directory. ``CmdbCloudResource.owner_person_id`` remains the resource's explicit owner. Cloud subscriptions/projects are already the authoritative ownership boundary in Helix, so a resource without an explicit owner inherits the most-specific active scope owner at read time. Keeping this derived avoids stale mass backfills whenever a subscription owner changes. """ from __future__ import annotations from dataclasses import dataclass from typing import Any from sqlalchemy import and_, exists, or_, select from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import aliased from app.domains.cmdb.models import ( SCOPE_TYPE_AZURE_RESOURCE_GROUP, CmdbCloudResource, CmdbCloudScope, ) @dataclass(frozen=True) class EffectiveResourceOwner: person_id: str # resource | parent_resource | resource_group | subscription | integration_scope source: str scope_id: str | None = None scope_name: str | None = None def inherited_scope_owner_exists() -> Any: """Correlated predicate for resources with an inherited scope owner. Azure resource groups are a child scope: their own owner wins; otherwise the parent subscription owner applies. Other providers map directly by ``scope_external_id`` (AWS account, GCP project, Azure subscription, AliCloud sub-account). """ scope = aliased(CmdbCloudScope) resource_group = CmdbCloudResource.raw_metadata["resource_group"].as_string() direct = exists(select(scope.id).where( scope.integration_id == CmdbCloudResource.integration_id, scope.deleted_at.is_(None), scope.owner_person_id.is_not(None), or_( and_( scope.scope_type == SCOPE_TYPE_AZURE_RESOURCE_GROUP, scope.external_id == resource_group, ), and_( scope.scope_type != SCOPE_TYPE_AZURE_RESOURCE_GROUP, scope.external_id == CmdbCloudResource.scope_external_id, ), ), )).correlate(CmdbCloudResource) group = aliased(CmdbCloudScope) parent = aliased(CmdbCloudScope) parent_owner = exists(select(parent.id).select_from(group).join( parent, parent.id == group.parent_scope_id, ).where( group.integration_id == CmdbCloudResource.integration_id, group.scope_type == SCOPE_TYPE_AZURE_RESOURCE_GROUP, group.deleted_at.is_(None), group.external_id == resource_group, parent.integration_id == group.integration_id, parent.deleted_at.is_(None), parent.owner_person_id.is_not(None), )).correlate(CmdbCloudResource) # Some single-account connectors historically did not stamp their # account id on specialized resources. Falling back is safe only when # the integration has exactly one active non-RG scope; multi-account # connectors must remain unresolved rather than guess. singleton = aliased(CmdbCloudScope) sibling = aliased(CmdbCloudScope) singleton_owner = exists(select(singleton.id).where( or_( CmdbCloudResource.scope_external_id.is_(None), CmdbCloudResource.scope_external_id == "", ), singleton.integration_id == CmdbCloudResource.integration_id, singleton.scope_type != SCOPE_TYPE_AZURE_RESOURCE_GROUP, singleton.deleted_at.is_(None), singleton.owner_person_id.is_not(None), ~exists(select(sibling.id).where( sibling.integration_id == singleton.integration_id, sibling.scope_type != SCOPE_TYPE_AZURE_RESOURCE_GROUP, sibling.deleted_at.is_(None), sibling.id != singleton.id, )), )).correlate(CmdbCloudResource) # Network inventory is hierarchical even when the provider connector has # no cloud-scope row (DNS-only connectors are the common case). A record # belongs to its zone domain, and a CDN entry with the same hostname is a # child of that managed domain. Domain ownership is already the mature # authoritative boundary for these resources, so reuse it instead of # presenting hundreds of children as unowned. parent_resource = aliased(CmdbCloudResource) zone_name = CmdbCloudResource.normalized_metadata["zone_name"].as_string() parent_resource_owner = exists(select(parent_resource.id).where( parent_resource.integration_id == CmdbCloudResource.integration_id, parent_resource.deleted_at.is_(None), parent_resource.resource_type == "domain", parent_resource.owner_person_id.is_not(None), or_( and_( CmdbCloudResource.resource_type == "dns_record", parent_resource.provider_resource_id == zone_name, ), and_( CmdbCloudResource.resource_type == "cdn_domain", parent_resource.provider_resource_id == CmdbCloudResource.provider_resource_id, ), ), )).correlate(CmdbCloudResource) return or_(direct, parent_owner, singleton_owner, parent_resource_owner) async def resolve_effective_resource_owners( db: AsyncSession, resources: list[CmdbCloudResource], ) -> dict[str, EffectiveResourceOwner]: """Resolve explicit-or-inherited owners for one bounded API page. The directory API pages at most 200 resources. Loading active scopes for their integrations is deliberately bounded by the small cloud-scope catalog and avoids one correlated lookup per resource. """ if not resources: return {} integration_ids = {str(row.integration_id) for row in resources} domain_parent_names = { str((row.normalized_metadata or {}).get("zone_name") or "").rstrip(".") if row.resource_type == "dns_record" else str(row.provider_resource_id or "").rstrip(".") for row in resources if row.resource_type in {"dns_record", "cdn_domain"} } - {""} scopes = list((await db.scalars(select(CmdbCloudScope).where( CmdbCloudScope.integration_id.in_(integration_ids), CmdbCloudScope.deleted_at.is_(None), ))).all()) domain_resources = list((await db.scalars(select(CmdbCloudResource).where( CmdbCloudResource.integration_id.in_(integration_ids), CmdbCloudResource.resource_type == "domain", CmdbCloudResource.provider_resource_id.in_(domain_parent_names), CmdbCloudResource.deleted_at.is_(None), CmdbCloudResource.owner_person_id.is_not(None), ))).all()) if domain_parent_names else [] domain_owners = { (str(row.integration_id), str(row.provider_resource_id).rstrip(".").casefold()): row for row in domain_resources } by_id = {str(scope.id): scope for scope in scopes} ordinary: dict[tuple[str, str], CmdbCloudScope] = {} ordinary_by_integration: dict[str, list[CmdbCloudScope]] = {} groups: dict[tuple[str, str], CmdbCloudScope] = {} for scope in scopes: key = (str(scope.integration_id), str(scope.external_id)) if scope.scope_type == SCOPE_TYPE_AZURE_RESOURCE_GROUP: groups[key] = scope else: ordinary_by_integration.setdefault(str(scope.integration_id), []).append(scope) # Scope external IDs are provider-native and unique per # integration. Prefer an owned row defensively if old imports # left duplicate scope types behind. if key not in ordinary or ( scope.owner_person_id and not ordinary[key].owner_person_id ): ordinary[key] = scope resolved: dict[str, EffectiveResourceOwner] = {} for resource in resources: resource_id = str(resource.id) if resource.owner_person_id: resolved[resource_id] = EffectiveResourceOwner( person_id=str(resource.owner_person_id), source="resource", ) continue normalized: dict[str, Any] = resource.normalized_metadata or {} parent_name = "" if resource.resource_type == "dns_record": parent_name = str(normalized.get("zone_name") or "") elif resource.resource_type == "cdn_domain": parent_name = str(resource.provider_resource_id or "") parent_resource = domain_owners.get(( str(resource.integration_id), parent_name.rstrip(".").casefold(), )) if parent_resource is not None and parent_resource.owner_person_id: resolved[resource_id] = EffectiveResourceOwner( person_id=str(parent_resource.owner_person_id), source="parent_resource", scope_id=str(parent_resource.id), scope_name=parent_resource.name, ) continue raw: dict[str, Any] = resource.raw_metadata or {} resource_group = str(raw.get("resource_group") or "").strip() if resource_group: group = groups.get((str(resource.integration_id), resource_group)) if group is not None: if group.owner_person_id: resolved[resource_id] = EffectiveResourceOwner( person_id=str(group.owner_person_id), source="resource_group", scope_id=str(group.id), scope_name=group.display_name or group.external_id, ) continue if group.parent_scope_id: parent = by_id.get(str(group.parent_scope_id)) if parent is not None and parent.owner_person_id: resolved[resource_id] = EffectiveResourceOwner( person_id=str(parent.owner_person_id), source="subscription", scope_id=str(parent.id), scope_name=parent.display_name or parent.external_id, ) continue scope_external_id = str(resource.scope_external_id or "").strip() inherited_scope = ordinary.get((str(resource.integration_id), scope_external_id)) if inherited_scope is not None and inherited_scope.owner_person_id: resolved[resource_id] = EffectiveResourceOwner( person_id=str(inherited_scope.owner_person_id), source="subscription", scope_id=str(inherited_scope.id), scope_name=inherited_scope.display_name or inherited_scope.external_id, ) continue candidates = ordinary_by_integration.get(str(resource.integration_id), []) if not scope_external_id and len(candidates) == 1 and candidates[0].owner_person_id: singleton = candidates[0] resolved[resource_id] = EffectiveResourceOwner( person_id=str(singleton.owner_person_id), source="integration_scope", scope_id=str(singleton.id), scope_name=singleton.display_name or singleton.external_id, ) return resolved