Skip to content

refactor: add drift detection caused by env vars - #291

Open
shirasassoon wants to merge 20 commits into
microsoft:mainfrom
shirasassoon:add-user-drift-detection-env-vars
Open

shirasassoon wants to merge 20 commits into
microsoft:mainfrom
shirasassoon:add-user-drift-detection-env-vars

Conversation

@shirasassoon

@shirasassoon shirasassoon commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

This pull request introduces robust detection and handling of identity drift when using environment variable authentication tokens in the Fabric CLI. It ensures that all tokens belong to the same identity and tenant, and that session consistency is maintained. The implementation includes new validation logic, improved error messaging, and updates to the logout process. Documentation has also been updated to explain the new behavior.

Identity drift detection and enforcement:

  • Added _validate_direct_token_identity method in fab_auth.py to verify that all environment variable tokens (FAB_TOKEN, FAB_TOKEN_ONELAKE, FAB_TOKEN_AZURE) belong to the same identity and tenant, and match the current session; otherwise, the CLI logs out and raises an error.
  • Updated _get_access_token_from_env_vars_if_exist to call the new identity validation method before using tokens.
  • Improved error handling for missing FAB_TOKEN_AZURE and provided clearer error messages for token-related issues. [1] [2]

Session and logout handling:

  • Introduced a logout_session method in fab_auth.py to centralize logout logic, including clearing caches and context, and updated all relevant code paths to use this method instead of duplicating logout logic. [1] [2] [3]
  • Ensured that on identity drift, the CLI logs out and clears session state before raising errors.

Token acquisition flow improvements:

  • Refactored token acquisition logic in acquire_token to defer environment variable token retrieval until after checking other identity types, and to properly set tenant and principal IDs when acquiring tokens interactively. [1] [2] [3]

Documentation updates:

  • Updated docs/essentials/env_vars.md to document the new identity drift detection behavior, including troubleshooting steps and caveats for different authentication modes.

Testing and maintenance:

  • Updated test helper to clear the new FAB_SPN_FEDERATED_TOKEN environment variable for completeness.

Shira Sassoon and others added 8 commits September 24, 2026 11:02
Validate direct access token env vars against the active session identity
(tenant/principal baseline), logging out and failing on mismatch. Persist
the user principal on interactive login so same-tenant principal drift is
caught, and unify the Azure CLI drift path on logout_session().

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Record the direct access token tenant/principal as the baseline on first
use when no prior identity exists, so any later identity change (including
a swap to a different direct token) is detected as drift and logs out,
matching Azure CLI authentication mode. Treats all identity changes as
drift regardless of source.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Guard the Azure scope in _get_access_token_from_env_vars_if_exist with a membership check before decoding so a missing FAB_TOKEN_AZURE raises a FabricCLIError (azure_token_required) instead of a raw KeyError that terminated the REPL.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@shirasassoon
shirasassoon marked this pull request as ready for review October 7, 2026 11:26
@shirasassoon
shirasassoon requested a review from a team as a code owner October 7, 2026 11:26
Copilot AI balanced review requested due to automatic review settings October 7, 2026 11:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Security-sensitive authentication changes require Fabric CLI team review, and correctness issues remain unresolved.

Review effort: Balanced
Findings: 3 Medium severity

Open (3)
What changed in this PR

Adds identity-drift detection for Fabric CLI environment-token authentication.

Changes:

  • Compares token identities with each other and the saved session.
  • Centralizes logout cleanup and improves authentication errors.
  • Documents drift handling and adds regression tests.
File Description
tests/​test_core/​test_fab_auth.py Adds token identity tests and environment cleanup.
src/​fabric_cli/​errors/​auth.py Adds identity-mismatch and invalid-token messages.
src/​fabric_cli/​core/​fab_auth.py Implements identity checks and shared session cleanup.
src/​fabric_cli/​commands/​auth/​fab_auth.py Uses centralized logout handling.
docs/​essentials/​env_vars.md Explains drift detection and recovery.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/fabric_cli/core/fab_auth.py Outdated
Comment thread src/fabric_cli/core/fab_auth.py
Comment thread src/fabric_cli/core/fab_auth.py Outdated
_validate_direct_token_identity decoded every present FAB_TOKEN* env var with full validation (including expiry), so an expired non-selected token (e.g. FAB_TOKEN_AZURE) blocked commands using a different, still-valid token. Decode identity claims with verify_exp=False in the drift loop while keeping full expiry validation for the selected token.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 7, 2026 12:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Security-sensitive authentication changes require Fabric CLI team review, and token-validation ordering remains unresolved.

Review effort: Balanced
Findings: 2 Medium severity

Open (2)
Resolved since last review (1)

…n drift

User sessions restored from disk or refreshed only via silent acquisition could lack a recorded FAB_PRINCIPAL_ID. Environment tokens for a different user in the same tenant then passed the session-identity comparison and were pinned without logout. Record the principal after both silent and interactive acquisition, and recover the cached principal before accepting an environment-token baseline.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings October 7, 2026 12:44
When multiple accounts are cached, recover the principal from the account whose home tenant matches the recorded session tenant instead of the first account.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Security-sensitive authentication changes require Fabric CLI team review, and identity-drift enforcement gaps remain unresolved.

Review effort: Balanced
Findings: 2 High severity · 2 Medium severity

Open (4)
Resolved since last review (1)

Comment thread src/fabric_cli/core/fab_auth.py
Comment thread src/fabric_cli/core/fab_auth.py Outdated
Comment thread src/fabric_cli/core/fab_auth.py Outdated
Copilot AI balanced review requested due to automatic review settings October 7, 2026 12:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

These security-sensitive authentication changes require Fabric CLI team review and have unresolved correctness issues.

Review effort: Balanced
Findings: 2 High severity · 2 Medium severity

Open (4)
Resolved since last review (1)
Previously missed (1)

In code that hasn't changed since last review

Medium severity Principal-only baseline update resets workspace navigation

src/​fabric_cli/​core/​fab_auth.py:391

A principal-only baseline update also resets navigation to the tenant root. If a tenant is already configured, no principal is recorded, and the current context is a workspace, the first direct-token request discards that workspace even though the tenant has not changed. Subsequent relative paths resolve from root, and context persistence can save the reset. Refresh navigation only when establishing the tenant baseline, not when merely recording its principal.

Comment thread src/fabric_cli/core/fab_auth.py Outdated
Comment thread docs/essentials/env_vars.md Outdated
Comment thread src/fabric_cli/core/fab_auth.py Outdated
Copilot AI balanced review requested due to automatic review settings October 8, 2026 06:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

These security-sensitive authentication and session teardown changes require Fabric CLI team review.

5 open findings

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

Comment thread src/fabric_cli/core/fab_auth.py
Copilot AI balanced review requested due to automatic review settings October 8, 2026 07:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Authentication changes require Fabric CLI team review, and a first-use direct-token authentication regression remains unresolved.

2 open findings
4 resolved since last review

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

Comment thread src/fabric_cli/core/fab_auth.py Outdated
Copilot AI balanced review requested due to automatic review settings October 8, 2026 08:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Security-sensitive changes to identity validation and session handling require Fabric CLI team review.

1 open finding
1 resolved since last review

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

Copilot AI balanced review requested due to automatic review settings October 8, 2026 08:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Changes to token validation and persisted authentication state require Fabric CLI team review.

1 open finding
1 resolved since last review

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

Comment thread src/fabric_cli/core/fab_auth.py
Copilot AI balanced review requested due to automatic review settings October 8, 2026 13:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Security-sensitive authentication and session-state changes require final Fabric CLI team review.

0 open findings

1 resolved since last review
Previously missed (1)

In code that hasn't changed since last review

Medium severity Preserve actionable Azure CLI error for missing JWT claims

src/​fabric_cli/​core/​fab_auth.py:938

The Azure CLI caller also uses this decoder before _check_azure_cli_identity(). A token missing tid or oid now raises _JWTIdentityClaimsError, bypassing the existing message that tells users to run az login. In _acquire_token_from_azure_cli(), catch _JWTIdentityClaimsError before FabricCLIError and raise FabricCLIError with azure_cli_identity_claims_missing() and ERROR_AUTHENTICATION_FAILED. This preserves the actionable error without weakening direct-token validation.

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

if metadata_refresh_needed or (
identity_type is None and initial_identity_type == "azure_cli"
):
metadata_refresh_needed = True

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why we set here the variable?

# Reacquire status after drift to discard stale values and allow env token fallback
if identity_type is None and initial_identity_type == "azure_cli":
# Refresh after identity fallback so metadata and tokens use the same identity
metadata_refresh_needed = metadata_lookup_failed and fabric_secret != "N/A"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in what case, metadata lookup will fail and fabric_secret won't fail and have != 'N/A'?

self._verify_valid_guid_parameter(tenant_id, "FAB_TENANT_ID")
self.set_tenant(tenant_id)
# Preserve the saved identity loaded from auth.json until direct tokens are checked for drift
direct_tokens_configured = (

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'd name it as 'enr_var_tokens_configured'

"FAB_SPN_CLIENT_ID" in os.environ
or os.environ.get("FAB_MANAGED_IDENTITY", "").lower() in ("true", "1")
)
direct_tokens_active = (

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

env_vars_tokens_active

Comment on lines +141 to +154
# Preserve the saved identity loaded from auth.json until direct tokens are checked for drift
direct_tokens_configured = (
"FAB_TOKEN" in os.environ or "FAB_TOKEN_ONELAKE" in os.environ
)
alternate_auth_configured = (
"FAB_SPN_CLIENT_ID" in os.environ
or os.environ.get("FAB_MANAGED_IDENTITY", "").lower() in ("true", "1")
)
direct_tokens_active = (
direct_tokens_configured
and not alternate_auth_configured
and self.get_identity_type()
not in ("azure_cli", "service_principal", "managed_identity")
)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please extract to a method, for cleaner code :)

and self.get_identity_type()
not in ("azure_cli", "service_principal", "managed_identity")
)
if not direct_tokens_active:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if they are active, what would be the used tenant id in cli?

# Check for identity drift across tokens and against the configured tenant, if set
token_tenant, token_principal = next(iter(identities))
if len(identities) > 1 or (
configured_tenant and configured_tenant.lower() != token_tenant

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
configured_tenant and configured_tenant.lower() != token_tenant
configured_tenant and configured_tenant.lower() != token_tenant.lower()

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants