web,ci: make Grant-AutopilotMonitorAddOn.ps1 actually downloadable

The docs page and the admin UI both told customers to run
Grant-AutopilotMonitorAddOn.ps1, but the script was never published
anywhere -- it only exists in this private repo. Publish it on the
download alias next to the agent artifacts and reference it:

- build-agent.yml: upload the script on publish_as_stable runs
- admin UI: copied grant command now starts with an irm -OutFile
  download line; prose links the script directly
- utils/config.ts: new AGENT_DOWNLOAD_URL registry constant

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Oliver Kieselbach
2026-08-10 13:33:59 +02:00
parent 13dd6723da
commit 283c2ed214
3 changed files with 26 additions and 3 deletions
+6
View File
@@ -270,6 +270,12 @@ jobs:
if (Test-Path "scripts/Bootstrap/Test-ShouldBootstrapAgent.ps1") {
Send-Blob -Local "scripts/Bootstrap/Test-ShouldBootstrapAgent.ps1" -BlobName "Test-ShouldBootstrapAgent.ps1" -ContentType "text/plain; charset=utf-8"
}
# Customer-side Graph add-on grant script -- docs and admin UI link
# https://download.autopilotmonitor.com/agent/Grant-AutopilotMonitorAddOn.ps1
if (Test-Path "scripts/CustomerSetup/Grant-AutopilotMonitorAddOn.ps1") {
Send-Blob -Local "scripts/CustomerSetup/Grant-AutopilotMonitorAddOn.ps1" -BlobName "Grant-AutopilotMonitorAddOn.ps1" -ContentType "text/plain; charset=utf-8"
}
}
# Update AdminConfiguration LatestAgentV2* -- ONLY on stable cutover. The hash-oracle
@@ -4,6 +4,7 @@ import { useCallback, useEffect, useState } from "react";
import { useAuth } from "../../../../contexts/AuthContext";
import { useTenant } from "../../../../contexts/TenantContext";
import { api } from "@/lib/api";
import { AGENT_DOWNLOAD_URL } from "@/utils/config";
import { authenticatedFetch } from "@/lib/authenticatedFetch";
import { trackEvent } from "@/lib/appInsights";
@@ -111,8 +112,9 @@ export function SectionOptionalGraphCapabilities() {
const allPermissions = Array.from(new Set(featureRows.flatMap(f => f.requiredPermissions)));
const allPermissionsLine = allPermissions.map(p => `"${p}"`).join(",");
const scriptDownloadUrl = `${AGENT_DOWNLOAD_URL}/Grant-AutopilotMonitorAddOn.ps1`;
const psCommand = status?.clientId
? `.\\Grant-AutopilotMonitorAddOn.ps1 \`\n -ClientId "${status.clientId}" \`\n -Permissions ${allPermissionsLine} \`\n -TenantId "${tenantId ?? "<your-tenant-id>"}"`
? `irm '${scriptDownloadUrl}' -OutFile .\\Grant-AutopilotMonitorAddOn.ps1\n.\\Grant-AutopilotMonitorAddOn.ps1 \`\n -ClientId "${status.clientId}" \`\n -Permissions ${allPermissionsLine} \`\n -TenantId "${tenantId ?? "<your-tenant-id>"}"`
: "";
return (
@@ -205,8 +207,16 @@ export function SectionOptionalGraphCapabilities() {
<div className="bg-white shadow rounded-lg p-6">
<h3 className="text-md font-semibold text-gray-900 mb-2">PowerShell grant command</h3>
<p className="text-sm text-gray-600 mb-3">
Open a Windows PowerShell or PowerShell 7 prompt as a tenant administrator and run the script
below. It is idempotent — re-running it skips permissions that are already granted.
Open a Windows PowerShell or PowerShell 7 prompt as a tenant administrator and run the commands
below — the first line downloads the script (
<a
href={scriptDownloadUrl}
className="text-green-700 underline hover:text-green-800"
download
>
direct download
</a>
), the second runs it. It is idempotent — re-running it skips permissions that are already granted.
</p>
<pre className="bg-gray-900 text-gray-100 text-xs font-mono p-3 rounded overflow-x-auto">
@@ -49,6 +49,13 @@ export const API_URL_PROD = "https://autopilotmonitor-api-eu.azurewebsites.net";
/** Production blob origin (CSP connect-src: diagnostics SAS uploads). */
export const BLOB_URL_PROD = "https://autopilotmonitoreu.blob.core.windows.net";
/**
* Customer-facing download alias for agent artifacts and helper scripts
* (Front Door in front of the blob origin). Counterpart of
* Constants.AgentDownloadBaseUrl on the C# side.
*/
export const AGENT_DOWNLOAD_URL = "https://download.autopilotmonitor.com/agent";
/**
* Hostnames the portal accepts in a bootstrap response's agentDownloadUrl.
* Keep in sync with ValidateBootstrapCodeFunction.cs, which builds that URL