databrickslabs / databrickslabs/ontos

[PRD]: Entra ID / Microsoft Graph integration & unified Principal Picker

Open
#335 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

meta/epic scope/settings type/prd
Dominant language
Python
Stars
212
Forks
71
Avg merge
4d 10h
Merged PRs (30d)
43

Description

Summary

Add an optional Entra ID (Azure AD) integration via a Unity Catalog HTTP Connection, plus a unified PrincipalPicker component that replaces ~14 inconsistent principal-entry UIs across the app with a Gmail-style badge input.

  • Configured mode: type-ahead + popup search dialog backed by Microsoft Graph (Users + Groups). Each result row shows displayName on top and email/UPN (users) or GUID (groups) underneath, so homonyms are always disambiguated.
  • Unconfigured mode: typed values become removable badges; clicking a badge reverts it to editable text.
  • Auth: UC HTTP Connection only — UC handles OAuth2 client credentials and token refresh via ws.serving_endpoints.http_request(conn=name, ...). No app-side token cache, no client secret stored in the app database.
  • Storage: keep existing string / List[str] fields untouched. No Alembic migration for v1.

Full PRD: docs/prds/prd-entra-id-graph-integration.md

Why

Today, ~14 different forms each implement principal entry differently (plain Input, comma-separated string, hard-coded Select, even unwired wizard placeholders). There is no validation, no display-name resolution, and no defense against typos. Operators with an Entra tenant cannot pick from a directory; consumers are guessing whether a group is data-eng or data_engineering.

The existing UC HTTP Connection plumbing (used by the workflow webhook step) already gives us a clean, secret-free path to Microsoft Graph. The pieces are in place; what is missing is one shared component, a small Graph search backend, and migration of every call site.

Decisions locked in (from PRD Q&A)

  • Replacement scope: all ~14 call sites in v1.
  • Principal types: Users + Groups (defer service principals).
  • Storage: keep strings (List[str] of emails / group names).
  • Search UI: both type-ahead AND popup dialog in the same component.
  • Pre-existing data: no re-validation; renders as plain badges.
  • Manual-mode badges: click to edit (true Gmail-like).
  • Disambiguation: two-line rows (name + email/GUID) plus tooltip on selected badges.

Sub-issues (to be filed)

Backend
  • Extract shared list_http_connections(ws) helper from workflows_routes.py and expose GET /api/settings/uc-http-connections
  • New EntraIdManager (src/backend/src/controller/entra_id_manager.py) with search_users, search_groups, get_user, get_group, test, OData escaping, in-memory TTL cache
  • New routes GET /api/entra/status, GET /api/entra/search, POST /api/entra/test
  • Persist new setting ENTRA_UC_HTTP_CONNECTION_NAME in SettingsManager (`_load_persisted_settings` + `update_settings` + `get_settings`)
  • Pydantic Principal model + tests for normalisation
Frontend — shared component
  • PrincipalPicker component at src/frontend/src/components/common/principal-picker.tsx with both modes, two-line result rows, tooltip on badges, Zustand entra-store for status
  • Settings UI: new "Entra ID" tab under Integrations (entra-settings.tsx + view) with UC connection select + test button + clear button
  • i18n keys in all 8 locales (entra namespace + common.principalPicker.*)
Frontend — call-site migration (15 fields across 13 files)
  • Group 1 (single user): `assign-owner-dialog.tsx`, `create-review-request-dialog.tsx`, `mdm/create-review-dialog.tsx`, `data-products/team-member-form-dialog.tsx`, `data-contracts/team-member-form-dialog.tsx`
  • Group 2 (multi user/group): `role-form-dialog.tsx` (groups + users), `entitlements.tsx` persona groups, `comments/comment-sidebar.tsx` audience
  • Group 3 (group only): `tags-settings.tsx` permissionForm.group_id, `teams/team-form-dialog.tsx` member_identifier
  • Group 4 (workflow designer): notification `recipients` + approval `approvers` via "Custom principals…" toggle
  • Group 5 (wizard placeholders): `data-contract-wizard-dialog.tsx` dc-owner / stakeholders / groups / primary support email
Testing
  • Backend unit tests for `EntraIdManager` against mocked `serving_endpoints.http_request`
  • Backend route tests for `/api/entra/*`
  • Frontend tests for `PrincipalPicker` (both modes, accepts filter, badge tooltip)
  • Frontend tests for `entra-settings.tsx` test button toast behaviour

Out of scope (v1)

  • Service principals
  • Storage migration to structured Principal records
  • Bulk re-validation of pre-existing values
  • OBO / delegated Graph queries
  • Server-side display-name caching beyond the 5-min query cache
  • Replacing existing role/team Selects in the workflow designer (additive toggle only)

Acceptance criteria

  1. Admin can configure a UC HTTP Connection in Settings → Integrations → Entra ID and the test button reports success/failure of a real Graph probe.
  2. With Entra configured, every principal-entry field across the app uses the new picker; type-ahead returns results after 2 chars, debounced 250ms.
  3. Every search result row shows the friendly name plus the email/UPN/GUID underneath; selected badges expose the email/UPN/GUID via tooltip + `title` attribute.
  4. With Entra not configured, every field falls back to the same picker in manual mode (Enter/Tab/comma → badge, click badge → editable text).
  5. Existing API payloads continue to use the same string identifiers; existing DB rows render as plain badges with no error decoration.
  6. No client secret is stored in the app database; UC handles OAuth.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read docs/prds/prd-entra-id-graph-integration.md first, then inspect workflows_routes.py, the listed frontend call sites, and the proposed PrincipalPicker entry point. Treat this as an umbrella design task requiring separate backend, frontend, migration, and test work. Done means the acceptance criteria are met across all listed fields without changing stored string identifiers.

Written by the indexing model from the issue text.

Assessment

Tech stack
azure, python, typescript
Domain
api, authentication, backend, cloud, frontend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.