Repository navigation
Azure Files Search action with live file permission checks, and File Sync Azure Files fix - #1704
Draft
Paul Lizer (paullizer) wants to merge 4 commits into
Draft
Paul Lizer (paullizer) wants to merge 4 commits into
Paul Lizer (paullizer) wants to merge 4 commits into
Conversation
Admins can point a global action at an existing Azure AI Search index built by the Azure Files indexer. At query time SimpleChat evaluates each candidate file's NTFS DACL and the share's permissions against the signed-in user's directory identity and returns only files the user can open. Withheld files are recorded in the activity logs, and results that could not be verified raise a deduplicated administrator notification. The action is global only: personal and group type lists exclude it, personal and group saves (including the V2 editors and type aliases) are refused, and the runtime runs only manifests bound to a global origin. Also fixes File Sync Azure Files sources that use managed identity or a service principal (the SDK requires token_intent for OAuth), adds categorized run failure messages and notifications, and adds optional deployer role grants for external storage accounts and search services. Refs #1697 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The V1 action modal's summary step read an undeclared isAzureFilesIndexType variable, which threw a ReferenceError for every action type that is not SQL or Cosmos DB. Declare it with the other type flags, and add a UI test that runs the real modal and stepper in Chromium on the static harness, so the Azure Files Search create, edit, and connection-test flows are exercised without a live app. Azure Files Search access reviews now record the conversation and the invoking agent's ID and name (never other agent configuration), and the V1 Control Center shows them in the table, CSV export, and details. Refs #1697 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Upstream used 0.261.293 for an unrelated change, so this work moves to 0.261.294. Adds release notes for the Azure Files Search action, the deployer role grants, and the File Sync Azure Files managed identity fix. Refs #1697 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CodeQL flagged a partial server-side request forgery: a File Sync Azure Files source's file service URL accepted any HTTPS host. Now that managed identity and service principal sources work, the client would send the app's storage token to that host. Saving or testing a source now accepts only Azure Files service endpoints, and the client re-checks stored sources before creating a credential. Also clears two lesser CodeQL findings (an unused variable in the V1 stepper and an implicit string concatenation in a test). Refs #1697 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
15 of 24 tasks
Paul Lizer (paullizer)
added a commit
to paullizer/simplechat
that referenced
this pull request
Oct 7, 2026
microsoft#1704, an open draft into V2, also claims 0.261.294, so this branch's version moves above every open pull request's claim. V2 is still at 0.261.293. Renumbers the same 20 lines in 15 files as the previous bump: config.py, this branch's release-notes section, the documentation version notes and the new tests' headers. V2's own release-notes sections are untouched. The tests' version floor stays 0.261.253. Refs microsoft#1549 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
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.
Summary
Customers already index file shares into Azure AI Search with the Azure Files indexer and don't want to ingest them into SimpleChat again. Those indexes store no permissions, so this action enforces them live.
azure_files_search_accessactivity-log entry: agent, conversation, counts, reason codes, and up to 25 paths, never content or the question. Unverified results notify admins at most once per action per day. Both are shown in the V1 Control Center.token_intent="backup". That's fixed, with classified errors, run-failure notifications, and Storage File Data Privileged Reader guidance in the V1 and V2 editors.Notes for reviewers:
The security-critical code is
functions_azure_files_acl.py, which parses SDDL and evaluates the DACL in order forFILE_READ_DATA. Every ambiguous case resolves to unverified: an unknown SID, conditional or object ACEs, generic-only rights, a missing DACL, or a parse error. BUILTIN\Users counts as a member only when the admin opts in.The app identity's Storage File Data Privileged Reader role bypasses NTFS, so SimpleChat's evaluation is the only enforcement.
CodeQL flagged a partial SSRF (critical) on the first push. A File Sync Azure Files source accepted any HTTPS host, and once the token path worked, it would have sent the app's storage token there. It's fixed in 2ac3afa:
_normalize_azure_file_urlaccepts only<account>.file.<Azure storage suffix>throughvalidate_azure_file_endpoint, the same validate-and-rebuild pattern the Blob connector uses._get_azure_files_service_clientre-checks stored sources before creating a credential.CodeQL passes on that commit, with no open alerts on the PR.
Background runs without a user session return nothing (
identity_unavailable).The Search API is pinned to 2024-07-01, so index aliases can't be addressed. SimpleChat's own indexes are refused.
A V1 regression introduced during this work was fixed before merge:
populateSummaryread an undeclared variable, which broke the summary step for most action types. The new static-harness UI test caught it. It never shipped, so it has no release note.Test harness fixes:
group_file_source_harness.pyandpublic_file_source_harness.pynow stub the two azure-core exceptions and the group helpers that File Sync imports.test_workspace_authoring_backend.pystubsvalidate_mcp_tool_pinning_for_save. It was missing on the base, so 80 of the file's tests returned 503 there. It also treatsazure_files_indexas global only.test_file_sync_azure_blob_storage.pysupplies the new category messages.The version is 0.261.294 because Fix orchestrated action charts that were drawn but never shown #1703 took 0.261.293.
Linked issue
Refs #1697. It stays open until the in-app checks listed under "Not run" are done.
Release Notes & Latest Features
Is this visible to end users?
Is this admin-facing (Admin Settings, governance, deployment, config)?
Should this become a Latest Feature card?
Screenshot needed for the card?
Version bump
application/single_app/config.pyVERSIONthird segment bumped, or not needed because this is docs-only (0.261.294)deployers/version.txtbumped, or not needed becausedeployers/was not changed (1.0.34)Testing / validation
Python runs use the repo
.venv, on Windows. Results are on 42af198 unless marked with the final commit, 2ac3afa, which adds only the File Sync host check, two CodeQL cleanups, and docs.python -m pytest functional_tests/test_azure_files_acl_evaluator.py -q: 14 passedpython -m pytest functional_tests/test_azure_files_search_pipeline.py -q: 21 passedpython -m pytest functional_tests/test_azure_files_search_integration.py -q: 14 passedpython -m pytest functional_tests/test_file_sync_azure_files_token_intent.py -q: 12 passed (2ac3afa)test_file_sync_azure_files_token_intent.py,test_file_sync_azure_files_identity.py,test_deployers_external_role_grants.py, andtest_action_app_identity_endpoint_hardening.pytest_file_source_credential_round_trip_fix.pyui_tests/test_admin_azure_files_index_action_modal_static.pypython -m pytest functional_tests/test_file_sync_azure_files_identity.py -q: 5 passedpython -m pytest functional_tests/test_deployers_external_role_grants.py -q: 6 passed. This includes a PowerShell run of the CLI resource-ID validator with the empty defaults.python -m pytest functional_tests/test_action_test_connection_modal_wiring.py -q: 5 passedpython -m pytest functional_tests/test_control_center_activity_logs_hardening.py -q: 4 passedpython -m pyteston the six group and public file-source harness files: 191 passedpython -m pytest functional_tests/test_file_sync_azure_blob_storage.py -q: 20 passed, 1 failed.test_file_sync_routes_do_not_disclose_exception_detailsfails identically on the base.python -m pytest functional_tests/test_workspace_authoring_backend.py -q: 141 passed, 1 failed.test_changed_assigned_knowledge_uses_real_personal_scope_policyfails identically on the base.python -m pytest ui_tests/test_admin_azure_files_index_action_modal_static.py -q: 3 passed. It runs the real V1 modal and stepper in Chromium on the static harness, covering create, edit, and connection-test pass, warn, and fail states.npm --prefix application/v2_ui run build, thenpython -m pytest ui_tests/test_v2_admin_azure_files_index_action.py -q: 1 passedui_tests/test_admin_azure_files_index_action_modal.py: skipped, because it needsSIMPLECHAT_UI_BASE_URLand a signed-in storage statenode functional_tests/test_v2_azure_files_index_action_logic.mjs: 4 checks passednpm run typecheckinapplication/v2_ui: passedtest_route_blueprint_policy_inventory.py12/12,test_route_unauthenticated_policy_contract.py7/7,test_route_policy_test_coverage.py3/3test_docs_app_surface_coverage.py7/7 andtest_docs_site_quality.py6/6 (2ac3afa).scripts/build_docs_inventory.pyoutput is committed.python scripts/check_xss_sinks.py --base-sha <merge-base> --head-sha HEAD <changed files>: passed for 48 filespython scripts/check_broken_access_control.py --base-sha <merge-base> <changed .py files>: passed for 30 files (2ac3afa)az bicep build --file deployers/bicep/main.bicep: succeeded, andmain.jsonis regeneratedtest_docs_link_integrity.py(3), with the same broken counts as the base, andtest_docs_release_notes_integrity.py(1, the generated release-notes pages are stale).test_personal_action_save_helper_regression.py(1) andtest_admin_key_vault_reminders_ui.py(1).test_plugin_logging.pycollection error.functions_azure_files_search_runtimeandfunctions_file_syncmodules against a test environment:semantic_kernel_loaderdoes, withPluginHealthChecker.create_plugin_safelyandKernelPlugin.from_object, from a manifest bound to the global origin.query(required string) andtop_n(optional integer).kernel.invokeinside a Flask request context with a signed-in session, against the same environment, it returned only the four files the user can open.Documentation
v0.261.294indocs/explanation/release_notes.md)docs/explanation/features/AZURE_FILES_SEARCH_ACTION.mddocs/reference/actions/azure-files-index.mddocs/admin/knowledge.mddocs/explanation/fixes/AZURE_FILES_FILE_SYNC_MANAGED_IDENTITY_FIX.md, including the host check, with the role guidance inAZURE_FILES_FILE_SYNC.mdcorrected)Security checklist
@swagger_route(security=get_auth_security()). The one new route isPOST /api/plugins/test-azure-files-index-connection, which also has@login_requiredand@admin_requiredand accepts global scope only.sanitize_settings_for_user(). No settings are sent; the connection test returns only reviewed check messages.