Add Test Connection to OpenAPI, Azure Maps, Blob Storage, Databricks, Log Analytics, MCP, Snowflake, and Tableau actions - #1269
Merged
Paul Lizer (paullizer) merged 1 commit intoAug 18, 2026
Conversation
Only SQL and Cosmos DB actions could be validated before saving. A wrong warehouse ID, container name, subscription key, PAT, or MCP endpoint only surfaced as a tool failure during a chat. Adds a Test Connection button to OpenAPI, Azure Maps, Blob Storage, Databricks, Log Analytics, MCP, Snowflake, and Tableau actions. Each test authenticates with the credentials entered in the modal and performs one lightweight read against the configured resource, then reports an actionable success or failure. Backend: - New functions_action_connection_tests.py with one tester per action type plus shared error sanitization, result, and timeout helpers. - Eight POST routes on the admin_plugins Blueprint, matching the existing test-sql-connection naming, each delegating through the shared _prepare_action_test_manifest and _run_action_connection_test helpers. - Masked secrets and reusable workspace identities resolve server-side, so an existing action can be tested without retyping credentials. - The MCP route enforces the same stdio scope restriction and outbound destination policy as MCP tool discovery, and does not overwrite discovered tool metadata. Frontend: - One shared test runner drives all eight buttons, so the loading, success, failure, and missing-field states are identical everywhere. Server text is rendered through DOM text nodes rather than innerHTML. - Log Analytics gains a dedicated Step 3 configuration section, replacing the generic endpoint form and the dynamically generated Step 4 fields. Stored additionalFields such as query_history are preserved on edit. Security hardening: - Action Key Vault references are now resolved strictly within the owning action's scope and source. A reference name arrives in the request body, so the previous unscoped resolution would let an authenticated user read another user's, group's, or global action's secret and forward it to an endpoint they control. The unscoped resolver is removed, and MCP discovery, Cosmos, and SQL test paths now share the single scope-checked chokepoint. - Loading a global action for a connection test requires the Admin role at the shared loader, so every test route inherits the check. Fixes microsoft#1267 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Paul Lizer (paullizer)
force-pushed
the
paullizer-action-test-connection-buttons
branch
from
August 18, 2026 12:46
d8475c3 to
3bc606b
Compare
Paul Lizer (paullizer)
merged commit Aug 18, 2026
b88ae40
into
microsoft:Development
12 checks passed
12 tasks
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.
Fixes #1267
Summary
Only SQL, Cosmos DB, and Yamcs actions could be validated before saving. Everything else forced a save-then-fail-at-runtime loop: a wrong warehouse ID, container name, subscription key, PAT, or MCP endpoint only surfaced as a tool failure during a chat.
This adds a Test Connection button to eight more action types —
openapi,azure_maps_openlayers,blob_storage,databricks,log_analytics,mcp,snowflake,tableau— following the existing SQL/Cosmos pattern.Each test authenticates with the credentials entered in the modal and performs one lightweight read against the configured resource:
GETto the base URL0/0/0ofmicrosoft.base.roadwith the subscription keyGET /api/2.0/sql/warehouses/{id}; report warehouse name and stateLogsQueryClient.query_workspace(..., "print TestConnection = 1")McpPluginFactory.probe_server_from_config; report transport, auth method, tool countSELECT CURRENT_VERSION(), closeChanges
Backend
functions_action_connection_tests.py— one tester per type, plus shared error sanitization, result, and timeout helpers. Routes stay thin.POST /api/plugins/test-{type}-connectionroutes onbpap, matching the existingtest-sql-connectionnaming, delegating through shared_prepare_action_test_manifestand_run_action_connection_testhelpers.Frontend
innerHTML.additionalFieldssuch asquery_historyare preserved on edit.getOpenApiAuthConfiguration/getAzureMapsConfiguration/getBlobStorageConfigurationout ofgetFormData()so the save path and the test path share one source of truth.Security
A code review of this PR surfaced a pre-existing cross-scope credential exfiltration path that the new routes would have widened, so it is fixed here.
_resolve_secret_value_for_plugin_testresolved any string that merely looked like a SimpleChat Key Vault reference, with no scope or source check — and that value came straight off the request body. Reference names are deterministic, so an authenticated user could submit another user's, group's, or global action's reference name and have the plaintext secret forwarded to an endpoint the same request controls.resolve_secret_reference_for_contextnow has exactly one call site in the module, inside_resolve_secret_value_for_action_test, which requires an explicit scope and per-fieldallowed_sources(no defaults) and fails closed when the scope cannot be determined._resolve_plugin_secret_context(existing_plugin, user_id), never from the request body.keyvault_plugin_get_helper:auth.*→action,additionalFields.*and MCP custom headers →action-addset.globalsecret scope through the Cosmos route.Only affects deployments with Key Vault secret storage enabled. Normal editing is unchanged — testing an existing action still works without retyping stored credentials.
Additionally, no credential value is ever returned to the browser:
sanitize_connection_errorstrips every literal manifest secret (including base64 forms) plus genericpassword/AccountKey=/SharedAccessSignature/Authorizationpatterns from all error text.Testing
Functional (all passing locally)
test_action_test_connection_endpoints.py— all eight routes registered onbpap, POST-only, full decorator stack, delegate to a dedicated tester; MCP retains discovery's stdio + destination policy; secret references resolve only within the owning action's scope and source; the resolver chokepoint is single.test_action_connection_test_secret_redaction.py— manifest secrets, generic credential patterns, and base64-encoded credentials are stripped; result helpers and the timeout clamp behave correctly.test_action_test_connection_modal_wiring.py— markup exists for all eight types, each button maps to a registered route, results avoidinnerHTML, Log Analytics is a structured config type and preservesquery_history.The source-mismatch guard is verified non-vacuous: flipping
ACTION_AUTH_SECRET_SOURCESto the wrong value makes the test fail with a specific message.UI (Playwright)
test_workspace_action_test_connection_controls.py, parametrized over all eight types: warning state without required fields, success alert on a mocked 200, danger alert on a mocked 403, plus the submitted payload shape.test_workspace_log_analytics_action_modal.pycovering the new section, conditional custom-cloud and service-principal fields, validation, and the saved manifest.Also fixed:
test_tableau_action_modal_workflow.pywas already failing onDevelopment— the Yamcs section added a second "Server URL" label, breaking that test's ambiguousget_by_labellocators under Playwright strict mode. Those assertions are now scoped by id.Guardrails:
check_swagger_routes.py,check_broken_access_control.py, andcheck_xss_sinks.py(diff-scoped, as CI runs it) all pass.route_tests12/12 pass.Notes
config.pyVERSION→0.250.215.docs/explanation/features/ACTION_TEST_CONNECTION.md.deployers/changed, sodeployers/version.txtis untouched.