Skip to content

Provision the CLI service principal via Agent 365 on first tenant use - #481

Draft
Krishnadheeraj (DheerajPannala) wants to merge 1 commit into
mainfrom
kpannala/a365-cli-sp-provisioning
Draft

Provision the CLI service principal via Agent 365 on first tenant use#481
Krishnadheeraj (DheerajPannala) wants to merge 1 commit into
mainfrom
kpannala/a365-cli-sp-provisioning

Conversation

@DheerajPannala

@DheerajPannala Krishnadheeraj (DheerajPannala) commented Jul 28, 2026

Copy link
Copy Markdown

Draft. Paired with a corresponding service-side change; this PR cannot function until that
ships
, so please treat it as design review rather than merge-ready.

Problem

In a newly onboarded tenant, the CLI's service principal does not yet exist, so a365 setup
fails at sign-in until an administrator creates it by hand. That manual step is easy to miss and
the resulting error is not self-explanatory.

The CLI cannot create it itself: service principals are provisioned just-in-time only for
applications that authenticate with a credential, and the CLI is a public client by design.

Change

ServicePrincipalProvisioningService asks the Agent 365 service to perform the provisioning on
the CLI's behalf, and the CLI calls it the first time it operates against a tenant.

The call is made from BootstrapConfigResolver.ResolveAsync, the shared entry point behind the
setup, cleanup and publish flows, so one insertion point covers every command.

Behaviour:

  • Runs at most once per tenant per process, deduplicated through a ConcurrentDictionary of
    in-flight tasks, so concurrent callers share a single attempt
  • Never throws. Failures are logged at debug level and the command continues and reports its
    own errors; provisioning is a convenience, not a precondition
  • Skipped when no tenant id is available or it is not a well-formed GUID
  • Opt-out via A365_DISABLE_SP_PROVISIONING=true, for CI and restricted environments

Token used — feedback welcome

The request carries a delegated user token with audience https://api.powerplatform.com.

The client id falls through to AuthenticationConstants.PowershellClientId, the existing default
in AuthenticationService. That is deliberate: the CLI cannot authenticate as itself here,
because its service principal not yet existing is precisely the condition being resolved. Azure
PowerShell is present in every tenant, so it is usable before the CLI is.

Two review questions:

  1. Should the client id be passed explicitly with a comment rather than inherited from the
    default? It is load-bearing here, and a silent default makes that invisible. I lean yes.
  2. Can anyone confirm Azure PowerShell is consented for the Power Platform API resource in a
    clean tenant? If not this returns AADSTS65001, and the CLI would need a different actor.

For context, this matches existing behaviour: TeamsGraphBackendConfigurator and other callers
also rely on the same default.

Testing

Suite Result
New ServicePrincipalProvisioningServiceTests 12 passed
Full CLI suite 1933 passed, 12 skipped

Covered: status mapping, request shape (route, api-version, bearer scheme), once-per-tenant
deduplication, invalid tenant ids skipping without any HTTP call, 403 and transport failures
degrading without throwing, and the opt-out switch.

Not covered: end-to-end. The service-side dependency is not deployed, so no part of this has
run against a live tenant. That is the main risk in this change.

Notes for reviewers

  • Tenant id is GUID-validated before it is interpolated into a request URL
  • HttpClient and HttpResponseMessage are disposed via using throughout
  • Endpoint overrides follow the existing convention (A365_PROVISIONING_ENDPOINT,
    A365_PROVISIONING_ENDPOINT_{ENV})
  • CHANGELOG entry added under [Unreleased]
  • The hook is placed after config resolution so it never runs before a tenant is known

@github-actions

Copy link
Copy Markdown

⚠️ Deprecation Warning: The deny-licenses option is deprecated for possible removal in the next major release. For more information, see issue 997.

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Jul 28, 2026
In a newly onboarded tenant the CLI service principal does not exist yet,
so setup fails at sign-in until an administrator creates it by hand. The
CLI cannot create it itself: service principals are provisioned just in
time only for applications that authenticate with a credential, and the
CLI is a public client.

The CLI now asks the Agent 365 service to provision it, once per tenant
per process, from BootstrapConfigResolver.ResolveAsync - the shared entry
point behind the setup, cleanup and publish flows. The call is best
effort: it never throws, is deduplicated per tenant, and can be disabled
with A365_DISABLE_SP_PROVISIONING=true.

Requires a corresponding service-side change before it has any effect.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: f8ba1b67-3303-43fd-935f-81941a9e9ef3
@DheerajPannala
Krishnadheeraj (DheerajPannala) force-pushed the kpannala/a365-cli-sp-provisioning branch from 46d0d82 to 669b6b5 Compare July 28, 2026 20:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants