Lab Identity Governance Fabric · Learn

Standards-Based Integration Architecture

what you'll learn: the two planes — provisioning (SCIM) and signaling (SSF/CAEP/RISC) — and how every system plugs in through open standards
flowchart LR
  HRIS[HRIS
source of record] --> IGA[IGA-Lite
governance / JML] REQ[Self-service
access request]:::req --> IGA CMDB[CMDB-Lite
CI / device trust] -.enriches.-> IGA IGA -->|F3 · RFC| ITSM{ITSM-Lite
change gate} ITSM -->|Duo push · approver-group RBAC
serialized · SoD| CAB([CAB approver]):::cab CAB -->|approve / deny · F4| ITSM ITSM -->|SCIM / Admin API| DUO[Duo] ITSM -->|SCIM / LDAPS| AD[AD / Entra] PAM[Privileged access broker
JIT elevation + vault]:::pam -->|JIT time-boxed| AD subgraph SIG[Signaling plane — SSF] TX[SSF
transmitter] end IGA -->|lifecycle → RISC| TX IGA -->|grant applied → assurance-level-change| TX CMDB -->|posture → CAEP| TX TX -->|CAEP / RISC| DUO TX -->|CAEP / RISC| CII[CII / Oort] TX -->|CAEP / RISC| APPS[Apps / RPs] PAM -->|JIT expiry / check-in → session-revoked| TX TX -->|CAEP / RISC| XDR[Cisco XDR
detect + respond]:::xdr CII -.identity vector.-> XDR XDR -.session-kill / quarantine.-> DUO classDef req fill:#160f22,stroke:#3b3170,color:#e6edf3; classDef cab fill:#201a10,stroke:#a98f2a,color:#f0f6fc; classDef xdr fill:#25161a,stroke:#7a3038,color:#e6edf3; classDef pam fill:#1a1224,stroke:#6b4a9e,color:#e6edf3;
Provisioning grants access (blue path, ITSM-gated) — every grant is approved by a Duo push to a CAB approver resolved from the approver group (serialized, SoD-routed). SSF broadcasts change to every receiver in real time (green plane); an applied grant emits a CAEP assurance-level-change. A privileged-access broker brokers time-boxed privileged access (JIT elevation + vault checkout) and, on expiry or check-in, emits the session-revoked the green plane fans out — de-elevating the edge in real time.
What we're solving for

One identity truth governs every system, and everything integrates through open standards — not bespoke connectors. HRIS is the source of who-is-who; every downstream system (Duo, AD/Entra, and apps) is granted through the same provisioning standard and re-evaluated through the same signaling standard. Add a system by speaking the standard, not by writing a one-off integration.

Two planes, two standards

Identity integration splits cleanly into a slow, stateful provisioning plane and a fast, event-driven signaling plane. Governance lives on the first; real-time reaction lives on the second. Every hook into the fabric uses one or both.

Plane 1 · Provisioning (state)

SCIM 2.0

The governed, slow path — establishes who has what. HRIS → IGA reconcile → ITSM change gate → grant/revoke on Duo and AD/Entra. Inbound SCIM to IGA-Lite is already ITSM-gated; outbound writes are the Admin-API / directory legs.

RFC 7643/7644 · create · update · deactivate · delete
Plane 2 · Signaling (events)

SSF — OpenID Shared Signals

The real-time path — broadcasts what just changed. One transmitter, many receivers; each re-evaluates in real time. CAEP carries session/security events, RISC carries account lifecycle. This is the "everyone integrates the same way" layer.

SSF 1.0 · CAEP 1.0 (Final) · RISC · SET (secevent+jwt)

The Change Approval Board — how the gate approves

The ITSM gate doesn't auto-approve grants — it requires a human CAB decision, authenticated by a Duo push. The push goes only to members of the approver group — the RBAC source of truth, resolved from AD and stamped into every RFC — so approver identity is governed, not hardcoded.

MechanismWhat it doesWhy
Duo-push approvala change in awaiting_approval sends an async Duo push; the approver's allow/deny on-device is the decision (F4)phishing-resistant, on-device CAB approval
group RBACiga resolves the approver group members → Duo usernames → RFC approvers[]; itsm pushes only to themwho-may-approve is an AD group, governed like any entitlement
Serialized pushesat most one push outstanding per approver; the next sends only after the current resolvesa multi-grant persona never fires simultaneous pushes (Duo anti-fraud)
SoD routinga privileged group grant routes as normal + SOD-PRIV, not the auto-approvable standardsegregation of duties on privileged access
Grant → SSFon an applied grant, iga fans a CAEP assurance-level-change to CII + downstream receiversa posture increase re-evaluates downstream in real time

Requests arrive two ways — birthright (persona-derived) and self-service (the /request intake) — and both flow through the same gate: RFC → Duo-push CAB → approve → apply → assurance-level-change. Every decision lands on the tamper-evident audit spine and the Grafana Change Approval Board row.

Where SSF fits — and how

You don't have to build the hard part. SSF/CAEP-capable signaling is a native product capability — Duo and CII speak these shared signals directly (SSF 1.0 / CAEP 1.0). Session events (CAEP) and account-lifecycle events (RISC) flow from one transmitter to many receivers, and the SCIM→RISC leg maps lifecycle changes to RISC events. So SSF isn't something to add — it's the spine that turns the fabric from a set of point integrations into a broadcast bus.

The role each standard plays

LayerStandardCarriesFabric hookStatus
ProvisioningSCIM 2.0account create·update·deactivate·deleteinbound → IGA (ITSM-gated); outbound → Duo/ADlive (inbound gated)
Session signalsSSF · CAEPsession-revoked · credential-change · assurance-level-change · device-compliance-changeSSF transmitter → receivers (Duo, CII, apps)native (Duo · CII)
Lifecycle signalsSSF · RISCaccount-disabled · account-purged · account-enabled · identifier-changed/recycledIGA lifecycle → RISC leg → transmitternative

Lane: the SSF/CAEP stack is standards plumbing only — this fabric carries signals over open standards.

Duo on the lab's AD — and how CII sees it

Open standards cover the new systems; the lab's legacy AD is covered by Duo's on-prem protection surfaces, and Cisco Identity Intelligence ingests AD directly.

SurfaceProtects / ingestsHow
Duo · Windows LogonInteractive console + RDP logonDuo Authentication for Windows Logon (credential provider)
Duo · Legacy AD ProtectionLegacy on-prem apps that auth via AD (Kerberos / NTLM)Sub-auth filter DLL on the DCs → Duo MFA (Push / phone) · fail-open configurable
Duo · Command-Line ProtectionRemote non-interactive: PS-Remoting · SSH · SFTPMFA on command-line logons (user must pre-exist in Duo)
CII · AD integrationAD users / groups / attributes · stale + guest · password hygieneLightweight PowerShell → SCIM to Cisco Identity Intelligence (no DC agent)

Windows Logon + Legacy AD + Command-Line Protection close the MFA gap across every AD logon path — interactive, legacy-app, and remote shell — while the CII AD ingest folds on-prem AD into the same identity-intelligence plane (Oort · Astrix · BHE) as cloud and SaaS.

Credential vaulting — a secrets vault, CyberArk-style

Governance decides who may hold a credential; a vault holds the secret itself and brokers every checkout. The lab runs a secrets vault as its PAM/vault tier — the same split CyberArk draws between PVWA (people) and CCP / AAM (machines):

User-front · human checkout

Vault app + op CLI

People retrieve elevated and break-glass credentials from a scoped secrets vault — the CyberArk PVWA equivalent. Checkout is Duo-gated, per-vault access follows the tier model, and use is audited. The break-glass secret lives here dormant, not in a config file.

secrets vault · per-lane scopes · Duo-gated · audited retrieval
Machine storage · app-to-app

Vault Connect API + Service Accounts

Services and CI fetch secrets programmatically from a self-hosted vault Connect API (the API the consoles already health-check) and Service Accounts — no secret in the image, none in git. This is the CyberArk CCP / AAM / Conjur equivalent: the machine authenticates, the vault releases only the secret it's entitled to.

vault Connect API · Service Accounts · secret-refs, not secrets
CyberArk workflowsecrets-vault equivalentFabric use
PVWA — human credential checkoutvault app + op CLIelevated / break-glass retrieval · Duo-gated · audited
CPM — rotation / managed accountsvault item rotationservice-account secrets rotated in the vault, not hand-edited
CCP / AAM / Conjur — app-to-appvault Connect API + Service Accountsconsoles & CI fetch op:// refs at runtime — no secret in image/git

This closes the loop with the ownership model: a service account's identity is governed in the NHI registry while its secret is vaulted in a secrets vault — human-checkout for break-glass, machine-fetch via Connect for the account itself. personal lab; secrets never land in the repo.

Egress & ingress — the network boundary

The fabric runs behind an enterprise network boundary that mirrors the identity planes: nothing is implicitly trusted, every crossing is mediated and logged. Outbound is forced through a tiered Secure Web Gateway (servers locked to an allowlist; workstations browse behind a threat-intel denylist); inbound arrives only through the Cloudflare edge — there are no open inbound ports on the lab. The Cisco customer-telemetry lane and the personal lane stay direct by design — a hard lane boundary, never proxied.

Egress — outbound through the tiered Squid SWG

A forward proxy at the lab gateway filters on the CONNECT / SNI host — no TLS interception, so cert-pinned APIs work untouched — and is tiered by listener port to match the healthcare-SWG standard (HIPAA / HITRUST / NIST 800-207) without breaking normal browsing:

:3128 · Service lane

default-deny + allowlist

The container fabric (HTTPS_PROXY=squid:3128), host scripts, and infra VMs reach only enumerated destinations. Servers never browse the open web — arbitrary server egress is the #1 exfiltration / C2 signal, so it's the tightest lane.

LLM APIs · Duo · Entra/Graph · Intune · CII · registries · PKI · lab services
:3129 · User browse lane

default-allow − threat-intel denylist

GPO-PAC workstations (fail-closed) browse the open web on 80/443 — but anonymizers, ad-hoc tunnels, and anon file-drop (exfil) are blocked, CONNECT is TLS-only, and every request is logged. Standard browsing works; known-bad doesn't.

tor2web · ngrok / trycloudflare / serveo · anonfiles / transfer.sh · temp-mail
flowchart LR
  WS[Workstations · GPO PAC
fail-closed]:::src --> BROWSE FAB[Service containers
HTTPS_PROXY → SWG]:::src --> SVC subgraph SWG[Forward SWG · tiered by port · no TLS intercept] SVC[Service lane
default-deny + allowlist] BROWSE[User browse lane
default-allow − denylist] end SVC -->|allowlisted only| NET[Allowlisted internet
LLM · Duo · Graph · Intune
CII · registries · PKI · services]:::ok SVC -->|off-allowlist| DENY[TCP_DENIED]:::deny BROWSE -->|standard 80/443| WEB[Open web]:::ok BROWSE -->|known-bad · tunnels · exfil| BLOCK[denylist → TCP_DENIED]:::deny SWG -.per-request JSON log.-> SPL[SIEM
egress detections]:::src CISCO[Cisco lane]:::direct -.DIRECT · lane boundary.-> NET classDef src fill:#1b2838,stroke:#3d6ea5,color:#e6edf3; classDef ok fill:#101b16,stroke:#2c623a,color:#e6edf3; classDef deny fill:#25161a,stroke:#7a3038,color:#e6edf3; classDef direct fill:#201a10,stroke:#a98f2a,color:#f0f6fc;
Two lanes, one proxy: servers on the service lane reach only the allowlist (everything else TCP_DENIED); workstations on the browse lane browse freely minus a threat-intel denylist. Both log every request to the SIEM, where egress detections (denylist hits, beaconing, direct-to-IP, service-lane escape) carry the monitoring load the permissive lane needs. The Cisco customer-telemetry lane bypasses the proxy by design.

Ingress — inbound through the Cloudflare edge

No inbound ports. Every request hits the Cloudflare edge — real certs, WAF, and CF Access → Duo SSO in front of every console — then rides a cloudflared tunnel down to a loopback origin on the internal host. The portal itself is static on CF Pages; a reverse proxy only terminates TLS for internal-name services.

flowchart LR
  CLIENT[Internet clients
browser · agents · SIEM]:::src --> EDGE subgraph EDGE[Cloudflare edge] ACC[CF Access → Duo SSO
consoles · Grafana] PAGES[CF Pages · static
identity portal] TUN[Tunnels · cloudflared
infra · scim · ssf] end EDGE --> ORIGIN subgraph ORIGIN[Internal origin host] ORIG[tunnel origins → loopback
consoles · SSF receiver] NPM[Reverse proxy 80 / 443
TLS for internal names] end ORIGIN --> SVC[Internal + fronted services
Splunk · consoles · Grafana
Uptime-Kuma · Portainer · gateways · SSF]:::ok SPLK[Splunk web
own Duo SAML · app-layer]:::direct -.no CF Access double-gate.-> SVC classDef src fill:#1b2838,stroke:#3d6ea5,color:#e6edf3; classDef ok fill:#101b16,stroke:#2c623a,color:#e6edf3; classDef direct fill:#201a10,stroke:#a98f2a,color:#f0f6fc;
Clients only ever touch Cloudflare; Access gates each console with a Duo SSO redirect (302), tunnels reach loopback origins so nothing is exposed directly, and the portal is static on CF Pages. Splunk web carries its own Duo SAML at the app layer, so it isn't double-gated at the edge.

Lane: Personal / Lab. Egress is the tiered SWG (service allowlist + browse denylist, no TLS-bump yet — payload DLP is the next step); ingress is zero-inbound-port via the Cloudflare edge. A forward proxy governs only outbound — inbound "no unapproved traffic" is the host firewall (default-block) + the CF Zero-Trust edge. The Cisco customer-telemetry lane and the personal lane are deliberately excluded from both — a hard lane boundary, direct and out of scope.