Repository navigation
Feat/azure multitenant onboarding - #92
Open
amansingh39 wants to merge 9 commits into
Open
amansingh39 wants to merge 9 commits into
amansingh39 wants to merge 9 commits into
Conversation
One AuthSec multi-tenant app registration, and the customer only sees Microsoft's own screens: admin consent creates AuthSec's service principal and grants its Graph application permissions; a delegated sign-in (PKCE, no refresh token) gives the administrator's ARM token, parked in Redis for at most 15 minutes. Connect then checks the service principal and its Graph permissions (granted, then usable), checks the signed-in user may bind the tenant, creates Reader on each selected subscription WITH THE ADMINISTRATOR'S TOKEN -- AuthSec's principal never holds roleAssignments/write -- and proves each one with AuthSec's own app-only token, polling while Azure applies it. A tenant is one cloud_connector row (scope_kind 'tenant', migration 042) and each subscription one row under it. Verify re-proves either without the customer; Revoke stops using a tenant and its subscriptions. No credential is stored: auth_ref is "azure-app:<client id>" and the secret stays in the deployment environment. Resource Manager and app-only tokens go through the official Azure SDK (azcore, azidentity, armsubscriptions, armauthorization), Graph through the Microsoft Graph SDK. Discovery is not part of this change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… their access Tenant and subscription discovery passes: Entra objects, Microsoft Entra role assignments and definitions (built-in, custom, scoped), app and delegated permissions, Azure RBAC, Key Vault, federation, sign-ins and activity, Foundry, workloads. Agents from Microsoft Entra Agent ID, the Microsoft 365 agent registry, Foundry agent applications and project agents, Azure Bot Service, Logic Apps agent loops and the Teams app catalog, plus inference, each listed once and closed when its source no longer lists it. Scheduled rescans, custom-app onboarding with credentials in Vault, and projection into the shared iga_* graph behind IGA_GRAPH_PROJECTION.
Azure migrations renumbered after staging's (042-044 -> 138-140); the duplicate sortedKeys helper dropped in favour of staging's.
138-140 now leave a constraint that already admits their value as it is, so on a database that ran them under their old numbers (042-044), or whose bootstrap already lists every value, they never narrow it under rows a later source wrote.
The Azure projection states each row's scope in provider_attrs as Kubernetes and GitHub rows do (the tenant for Entra objects; the subscription, with its resource group or region, for resources and workloads), so /api/iga/v1/inventory lists provider azure with scope, native id and as_of from the Azure discovery run. /authsec/discovery/connections lists Azure tenants and subscriptions, with their latest run, coverage and a live graph state.
The shared connections list gives an Azure tenant as the connection and counts its subscriptions in its scope summary instead of listing each one. Every Azure inventory row is scoped to its tenant, with a resource's or workload's subscription as its sub-scope and its subscription id and resource group in its attrs, so filtering by the tenant connection includes them.
Own app: the client secret is stored only after every read it enables is proven, and destroyed on revoke or when the tenant moves to the AuthSec app. Its failures are the customer's (400, credential_invalid, unknown tenant, app not in tenant, named missing permissions), never AuthSec's deployment. Warnings for Graph permissions that can change data, Azure roles beyond Reader, and no readable subscription. A tenant switching between apps moves its other subscriptions to the new credentials. Verify checks revoked first; a passing Microsoft failure no longer stops scheduled discovery; discovery fails closed when the own app's credentials cannot be read; unexpected errors no longer return internals.
Staging took migrations 138-140 (access policy delete, cloud scan schedule); the Azure migrations move to 141-143, with their references.
… pass the tenancy guardrail Every Azure upsert overwrites a row only from a pass at least as new as the one that wrote it, and a pass that loses its lease stops. AWS's Connector, ForRun, verify and revoke act only on AWS connectors, so an Azure connector on an AWS route is not found and is never queued there. Reconnecting a tenant revokes the subscriptions not selected. The Azure projection runs under row-level security for its workspace (tenancy.InWorkspace); every Azure raw statement is bound to its workspace and carries a TENANT-EXEMPT reason, and the sign-in origin update now binds workspace_id; the guardrail is back at its baseline (72). Database tests for the fence, the AWS routes and deselection.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Changes
Testing
go test -short ./tests/unit/)go vet ./...cleanrun-integrationto this PR to trigger integration tests in CI (requires a live DB)Checklist