MCP Gateway Authorization — As-Built Topology
flowchart TB HRIS["HRIS → IGA → ITSM gate
onboarding drives AD"] subgraph SOT["AD on-prem — source of truth"] ADG["Users + 17 SG-* groups
in an AD OU · tiered T0–T4"] end subgraph PROXY["The auth-proxy host — two sync engines, side by side"] ECN["Entra Connect
AD users+groups → Entra"] DDS["AD Duo Auth Proxy
Duo Directory Sync · [ADDS]"] end ENT["Entra tenant"] DUO["Duo directory
AD-synced groups (incl. 17 SG-*)"] subgraph PAC["Policy-as-code · SSOT"] INT["mcp-authz-intent.yaml"]-->RND["the policy renderer"] end subgraph PDP["Decision · Duo cloud Authorization API (true PDP)"] DAC["ext_authz connectors
agentgw + envoy · LIVE"] CSA["Cisco Secure Access
managed SSE · PLANNED"] end subgraph PEP["Enforcement · gateways (PEP) — one job each"] AGW["agentgateway · LIVE
MCP tools"] ENV["Envoy AI Gateway · LIVE
LLM providers"] SAG["Cisco Secure Access
private apps (ZTNA) · PLANNED"] end subgraph RES["Resources"] MCP["MCP servers
github · ms-learn · splunk"] LLM["LLM providers
Anthropic · OpenAI · Ollama"] APPS["Private apps
-lite consoles + fabric API"] end HRIS-->ADG ADG-->|Entra path|ECN-->ENT ADG-->|AD→Duo path · SG-* groups|DDS-->DUO ENT-.->|Entra→Duo sync|DUO DUO-->DAC ENT-.->CSA RND-->DAC RND-->CSA DAC-->AGW DAC-->ENV CSA-->SAG AGW-->MCP ENV-->LLM SAG-->APPS LEAVER["HRIS leaver → IGA → SSF/CAEP session revoke"]-.->|pulls token|AGW LEAVER-.->ENV LEAVER-.->SAG
Groups are an identity-plane object, not a gateway object. 17 AD security groups in an AD OU — tiered T0–T4 — reach Duo via the AD Duo Directory Sync (the Auth-Proxy path) — a distinct sync from Entra Connect's AD → Entra — and serve every gateway. What is per-gateway is the policy binding, authored once in mcp-authz-intent.yaml and rendered to each PDP. The same 17 groups govern all three planes — MCP tools, LLM providers, and private apps; a new gateway or plane renders the same intent to its PDP, it never mints a new group set.
The plane, end to end
Source of truth → sync → decision (PDP) → enforcement (PEP) → resources. Policy-as-code drives the PDPs; the leaver signal pulls tokens back out.
HRIS onboarding drives AD on-prem. The auth-proxy host runs two sync engines side by side: Entra Connect pushes AD users + groups into the Entra tenant, and the AD Duo Auth Proxy (the [ADDS] Duo Directory Sync) pushes them into Duo. The 17 SG-* groups reach Duo on the AD path — not through Entra. Duo's directory holds the AD-synced groups (incl. all 17 SG-*), plus groups from a Microsoft Entra sync and a Google sync — three inbound directory syncs converging on one Duo, which the gateways' authorization then reads.
Per-tool-call decision
Two checks on every call: authenticate the Duo JWT, then authorize the tool against the sponsor's groups. Default-deny.
sequenceDiagram
participant C as Agent / MCP client
participant G as Gateway (PEP)
participant D as Duo Authorization Connector (PDP)
C->>G: tools/call (Bearer Duo JWT)
G->>G: mcpAuthentication — validate iss/aud/JWKS
G->>D: ext_authz Check (token + target_tool)
D->>D: sponsor groups ∩ allowedTools(group, server)
alt authorized
D-->>G: ALLOW (allowedTools)
G-->>C: tool result
else not in any group's bundle
D-->>G: DENY
G-->>C: 403 (tool hidden / refused)
end
The 17 groups (net-new, deployed to ADUC)
| AD group | Plane | Tier | Provisioning | Scope |
|---|---|---|---|---|
| SG-MCP-MSLearn | MCP | T0 | birthright | ms-learn ×3 |
| SG-MCP-GitHub-Read | MCP | T1 | birthright | github read ×26 |
| SG-MCP-GitHub-Write | MCP | T2 | requestable | github write ×14 |
| SG-MCP-GitHub-Merge | MCP | T3 | JIT · .adm | merge_pull_request · SoD ≠ Write |
| SG-MCP-GitHub-Admin | MCP | T3 | JIT · .adm | create_repository, delete_file |
| SG-MCP-AppSec | MCP | T4 | JIT+alert · .adm | run_secret_scanning |
| SG-MCP-Splunk-Read | MCP | T1 | birthright | splunk metadata ×6 |
| SG-MCP-Splunk-Query | MCP | T3 | JIT · .adm | run_query, run_saved_search |
| SG-MCP-Splunk-IAMData | MCP | T4 | JIT+alert · .adm | get_user_info, get_user_list |
| SG-MCP-Duo-Read | MCP | T1 | birthright | duo read ×47 · detail |
| SG-MCP-Duo-LogSync | MCP | T1 | birthright | logsync metrics/rollups ×5 |
| SG-MCP-Duo-Write | MCP | T2 | requestable | duo write ×19 · SoD ≠ Admin |
| SG-MCP-Duo-Auth | MCP | T2 | requestable | auth challenge/verify/token ×4 |
| SG-MCP-Duo-Admin | MCP | T3 | JIT · .adm | destructive ×13 · SoD ≠ Write |
| SG-MCP-Duo-DNG | MCP | T3 | JIT · .adm | DNG relay config ×6 |
| SG-MCP-Duo-Intel | MCP | T3 | JIT · .adm | posture/diagnostics ×7 |
| SG-MCP-Duo-IAMData | MCP | T4 | JIT+alert · .adm | log PII mine + export ×6 |
| SG-MCP-Duo-Secrets | MCP | T4 | JIT+alert · .adm | integration secrets + bypass codes ×4 |
| SG-LLM-Local | LLM | T0 | birthright | Ollama (no egress) |
| SG-LLM-External | LLM | T2 | requestable | Anthropic/OpenAI · DLP-gated |
| SG-LLM-Frontier | LLM | T3 | JIT | frontier models · budget-bound |
| SG-AGW-Fabric-Read | API | T1 | requestable | GET · hris/iga/itsm/cmdb |
| SG-AGW-Fabric-Operator | API | T3 | JIT · .adm | control endpoints |
| SG-MCP-AgentGW-Admin | admin | T3 | JIT · .adm | agentgateway console/config |
| SG-MCP-EnvoyGW-Admin | admin | T3 | JIT · .adm | Envoy admin (planned) |
| SG-MCP-SecureAccess-Admin | admin | T3 | JIT · .adm | Secure Access admin (planned) |
Groups = f(roles × tiers) — independent of gateway count and tool count. A new tool is auto-tiered by the onboarding rubric into an existing group; a new gateway renders the same intent to its PDP. T3/T4 bind to an elevated .adm identity, so neither a human on their daily account nor an agent acting on-behalf-of them can reach destructive or data-exfil tools. Compliance maps clean: NIST 800-53 AC-2/3/5/6, 800-171/CMMC 3.1.x, ISO 27001 A.5/A.8, SOC 2 CC6, HIPAA §164.312.
← conceptual: Agentic AI Gateways & Access (page 5)
Lane: personal lab · synthetic data — reference architecture over synthetic identities only, no customer data.