Skip to content

Provision A365 proxy app on develop-mcp publish - #499

Open
deepaligargms wants to merge 6 commits into
microsoft:mainfrom
deepaligargms:deepaligarg-microsoft-publish-a365-proxy-app
Open

deepaligargms wants to merge 6 commits into
microsoft:mainfrom
deepaligargms:deepaligarg-microsoft-publish-a365-proxy-app

Conversation

@deepaligargms

@deepaligargms deepaligargms commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Wire develop-mcp publish to provision the A365 proxy Entra app (confidential app + secret) and forward its credentials to the platform, so custom (non-Dataverse) MCP servers actually get a Power Platform connector created at publish time. Previously publish created only the PublicClients app, so the platform's connector-creation step logged A365ProxyConnectorCreation=SkippedNoCredentials and skipped. The register flow already provisions this proxy app; this mirrors it in publish. - CreateEntraAppsAsync now creates {server}-A365Proxy (confidential, with secret) first, failing the publish if it can't be created; CreateProxyAppAsync self-cleans its own orphan on partial failure. - PublishMcpServerRequest carries a365ProxyClientId / a365ProxyClientSecret; PublishMcpServerResponse reads A365ProxyRedirectUri (+ A365ProxyConnectorId). - After publish, the proxy app's redirect URIs are set from A365ProxyRedirectUri (tc/non-tc list), mirroring register; warns if absent. - The McpServer required-resource-access grant is added onto both the A365 proxy app and the PublicClients app. The platform wires the connector with the proxy app as its OAuth client and McpServerAppId as the resource, so the proxy app must hold this grant or Entra rejects the connector token request with AADSTS650057. - a365ProxyClientSecret is added to RedactSecretFields so the new secret is masked as ***REDACTED*** in verbose request-payload logging (alongside the other client secrets). - RollbackEntraAppsAsync now deletes both apps. Paired MCP-Platform change (connector create at publish, tenant-publish at approve) is already merged. Tests: new PublishCommandExecutorEntraAppTests (incl. grant-on-both-apps assertion), RedactSecretsFromPayload_RedactsA365ProxyClientSecret; updated regression + dry-run tests. Full suite green (2019 passed).

Before installing the version with this change(correct error message)

Correct error

After installing the latest version of a365 cli with this change
New app created

Publish now creates the confidential A365 proxy Entra app (app + secret) alongside the PublicClients app and forwards its credentials to the platform, so custom (non-Dataverse) MCP servers get a Power Platform connector created at publish time instead of the platform logging A365ProxyConnectorCreation=SkippedNoCredentials. Mirrors the register flow: proxy app created first (fatal on failure, with self-cleanup), request carries the proxy clientId/secret, proxy redirect URIs are updated post-publish, and rollback deletes both apps.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@deepaligargms
deepaligargms requested review from a team as code owners September 22, 2026 04:55
Copilot AI lite review requested due to automatic review settings September 22, 2026 04: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

🟡 Changes recommended

One or more issues must be addressed before approval.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 2 High severity

Open (2)
What changed in this PR

Adds A365 proxy app provisioning to develop-mcp publish, forwards credentials for connector creation, configures redirect URIs, and adds rollback/test coverage.

Changes:

  • Provisions confidential proxy apps with secrets.
  • Extends publish request/response models.
  • Updates rollback, redirect URI handling, tests, and changelog.
File Description
src/​Tests/​Microsoft.Agents.A365.DevTools.Cli.Tests/​Commands/​PublishCommandExecutorEntraAppTests.cs Updated as part of this pull request.
src/​Tests/​Microsoft.Agents.A365.DevTools.Cli.Tests/​Commands/​PublishCommandExecutorDryRunTests.cs Updated as part of this pull request.
src/​Tests/​Microsoft.Agents.A365.DevTools.Cli.Tests/​Commands/​DevelopMcpCommandRegressionTests.cs Updated as part of this pull request.
src/​Microsoft.Agents.A365.DevTools.Cli/​Models/​PublishMcpServerResponse.cs Updated as part of this pull request.
src/​Microsoft.Agents.A365.DevTools.Cli/​Models/​PublishMcpServerRequest.cs Updated as part of this pull request.
src/​Microsoft.Agents.A365.DevTools.Cli/​Commands/​PublishCommandExecutor.cs Updated as part of this pull request.
CHANGELOG.md Updated as part of this pull request.

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

The platform wires the A365 proxy connector with the proxy app as its OAuth client and McpServerAppId as the resource, so the proxy app must hold the McpServerScope required-resource-access grant or Entra rejects the connector's token request with AADSTS650057. ConfigureEntraAppsAsync previously granted this only on the PublicClients app; now it grants on both the proxy app and the PublicClients app, mirroring register.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 22, 2026 05:39

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

🟡 Changes recommended

Address the cleanup, secret-redaction, and failing dry-run assertion issues.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 3 High severity

Open (3)

The publish request now carries the newly created A365 proxy Entra app secret as a365ProxyClientSecret. RedactSecretFields only masked clientApp1Secret/clientApp2Secret/clientSecret, so verbose request-payload logging wrote the live client secret in plaintext. Add a365ProxyClientSecret to the redaction key set with a regression test.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings September 22, 2026 18:00

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

Unresolved moderate findings affect cleanup, dry-run accuracy, permission handling, and cancellation behavior.

Review effort: Lite
Findings: None

Resolved since last review (3)
Previously missed (2)

In code that hasn't changed since last review

Medium severity Include proxy configuration in dry-run output

src/​Microsoft.Agents.A365.DevTools.Cli/​Commands/​PublishCommandExecutor.cs:92

The real publish path now also grants the MCP server permission to both apps and, when returned, writes the proxy redirect URIs, but this dry-run output still says it only back-fills the PPMI scope. That makes --dry-run under-report the changes users are previewing; update this message and its assertion to describe the new proxy configuration as well.

Medium severity Roll back proxy app when public client creation fails

src/​Microsoft.Agents.A365.DevTools.Cli/​Commands/​PublishCommandExecutor.cs:335

The proxy app is now created before CreatePublicClientsAppAsync, but an exception from that call can escape CreateEntraAppsAsync: its Graph app-creation call is outside the provisioner's catch, and ExecuteAsync has no rollback around app creation. A transient Graph/network failure here therefore leaves the newly created A365 proxy registration and secret orphaned. Catch this failure (while preserving cancellation), delete the proxy app, and return a failed publish; add a regression test for this partial-creation path.

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.

Requesting changes. The main concern is credential hygiene: publish now mints a confidential app with a secret on every run, and it can be left behind on partial failure. Details inline.

Comment thread src/Microsoft.Agents.A365.DevTools.Cli/Commands/PublishCommandExecutor.cs Outdated
Comment thread src/Microsoft.Agents.A365.DevTools.Cli/Commands/PublishCommandExecutor.cs Outdated
Comment thread src/Microsoft.Agents.A365.DevTools.Cli/Commands/PublishCommandExecutor.cs Outdated
Comment thread src/Microsoft.Agents.A365.DevTools.Cli/Commands/PublishCommandExecutor.cs Outdated
Comment thread CHANGELOG.md Outdated
…cleanup

Publish still forwards the A365 proxy app credentials on every call (the
CLI can't classify custom vs first-party before the platform does), but
now reconciles after publish: when the response shows no connector was
created, the unused proxy app is deleted so no orphaned credential lingers.

- Post-publish cleanup of the unused proxy app for first-party/Dataverse
  servers, gated on the platform returning a connector id / redirect URI.
- Redirect-URI warning now fires only when a connector was actually
  created but no URI came back, not on every first-party publish.
- Proxy required-resource-access grant applied only when a connector
  exists; Public Clients grant unchanged.
- New --service-tree-id and --secret-lifetime-months options on publish,
  threaded to both created Entra apps, mirroring register.
- Orphaned proxy app is deleted if Public Clients creation throws after
  the proxy app was created.
- Dry-run output now describes proxy creation, permission/redirect config,
  and cleanup.
- CHANGELOG entry references (microsoft#499).

Tests: proxy grant on both apps only when a connector exists, unused-proxy
deletion, orphan-cleanup-on-throw, option flow-through, and updated publish
option/dry-run assertions with documented requirement changes.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings September 29, 2026 19:17

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

🟡 Changes recommended

Secret-lifetime validation, option-forwarding coverage, and cancellation-safe cleanup remain unresolved.

Review effort: Lite
Findings: 1 High severity · 1 Low severity

Open (2)

Comment thread CHANGELOG.md Outdated
Copilot AI lite review requested due to automatic review settings September 29, 2026 19:26
@deepaligargms
deepaligargms force-pushed the deepaligarg-microsoft-publish-a365-proxy-app branch from 7fe23fd to 9c97cc0 Compare September 29, 2026 19:26

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

🟡 Changes recommended

Unresolved moderate issues affect option propagation, orphan cleanup, and redirect-warning behavior.

Review effort: Lite
Findings: 1 High severity · 3 Medium severity · 1 Low severity

Open (5)

Comment thread src/Microsoft.Agents.A365.DevTools.Cli/Commands/PublishCommandExecutor.cs Outdated
Comment thread src/Microsoft.Agents.A365.DevTools.Cli/Commands/PublishCommandExecutor.cs Outdated
Comment thread src/Microsoft.Agents.A365.DevTools.Cli/Commands/PublishCommandExecutor.cs Outdated
…ndense CHANGELOG

- Reject --secret-lifetime-months outside 1-24 before any Entra app or platform call, matching register's pre-flight guard (copilot review).
- Condense the [Unreleased] entry to one consumer-facing sentence (copilot review).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings September 29, 2026 23:29

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 AI lite review requested due to automatic review settings October 1, 2026 17: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

🟡 Changes recommended

Address the identified provisioning, cancellation cleanup, connector-response handling, required-grant failure, and changelog issues.

Review effort: Lite
Findings: 1 High severity · 1 Medium severity · 2 Low severity

Open (4)
Resolved since last review (1)

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

🟡 Changes recommended

Rollback reuses a cancelled publish token, preventing cleanup of the proxy app and its secret.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
Resolved since last review (4)

Comment on lines +401 to +402
await TryDeleteEntraAppAsync(tenantId, apps.PublicClientsObjectId, apps.PublicClientsClientId, apps.PublicClientsAppName, ct);
await TryDeleteEntraAppAsync(tenantId, apps.A365AppObjectId, apps.A365AppClientId, apps.A365AppName, ct);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants