-
Notifications
You must be signed in to change notification settings - Fork 1
Serving Manifests and Packages
BootstrapMate needs two things from your web host: one manifest document at a stable URL, and every package the manifest names. This page covers what the client actually requires of a host, what it does not enforce, and how to check a host before you point a fleet at it.
Set the URL once, in policy or in machine settings, rather than passing --url on every
invocation — see Preferences. A single absolute URL is fetched per run.
Requirements the client imposes:
-
The URL must be absolute. It is passed straight to
HttpClient, and the host portion is parsed out and remembered for theAuthorizationscoping rule below. A URL that does not parse as absolute leaves that host unset, which disables the header for every package download in the run. -
The response body must be the manifest itself. It is read as a string and parsed
directly. A login page, an HTML error page returned with a
200, or a directory listing will fail to parse and the run will exit1. -
The file extension decides the format, before the content is examined. If the URL's
path — with anything from the first
?or#onwards stripped — ends in.yamlor.yml, the body is parsed as YAML. Otherwise, if the trimmed body's first character is neither{nor[, it is also parsed as YAML. Everything else is parsed as JSON. The response'sContent-Typeis never consulted, so servingapplication/octet-streamortext/plainis harmless, and serving JSON from a.yamlURL is not.
A query string is fine. If your host needs a signed URL, put the signature in the query and the extension rule still works, because the query is stripped before the extension is tested.
Each manifest item carries its own absolute url and a file name. The file value — not
anything derived from the URL or from a Content-Disposition header — is the name the
download is written under inside C:\ProgramData\ManagedBootstrap\cache. Two items that
share a file value will overwrite each other, so keep them distinct.
Any status outside the 2xx range fails that item with Download failed: {StatusCode} and
the run moves on to the next one. Nothing else about the response is validated: no size
check, no content-type check, and no hash — see
Security and Package Verification.
Package URLs may point at a different host from the manifest. That works, with one consequence, described next.
The only authentication mechanism is a single AuthorizationHeader value, sent verbatim as
the Authorization request header. There is no support for client certificates, for a
second header, for arbitrary custom headers, or for per-item credentials. The GUI emits a
--headers switch, but the CLI has no case for it and discards it; configure the value in
the registry.
The header is attached to:
- the manifest request, always; and
- a package download only when the package URL's host equals the manifest URL's host, compared case-insensitively.
A package on any other host is fetched anonymously, and the run logs
Authorization header withheld for cross-host download: {url} at Debug level — so you will
only see it with --verbose. Plan around this: if your packages need authentication, serve
them from the same host as the manifest. If they are on a different host, that host must
either allow anonymous reads or carry its own authorisation inside the URL, such as a
pre-signed query string.
The reverse case bites too. Some object stores return 403 Forbidden for a public object
requested with an Authorization header they cannot validate. That is the failure the
host-scoping rule was added to prevent; if you see Download failed: Forbidden across a
fleet, check whether the packages are on the same host as the manifest and whether the
header is being attached when it should not be.
Every request carries User-Agent: BootstrapMate/{version}. Do not build access control on
that string, but do allow it through any user-agent filtering on the host.
Redirects are followed. The client uses a default HttpClient, whose default handler
follows redirects, and nothing in the tool changes that.
The FollowRedirects setting — present in the configuration object, in the ADMX template,
and in the GUI — is never read by the command-line tool. Leaving it disabled does not
stop redirects being followed, and enabling it changes nothing. The only place it takes
effect anywhere in the product is the GUI's "Preview manifest" button. See
Troubleshooting and Gotchas.
Two practical notes follow from that. First, a redirect that crosses hosts moves the request
off the manifest host; the Authorization header decision is made from the URL as written
in the manifest, not the final location. Second, HttpClient does not forward an
Authorization header across a redirect to a different origin, so an authenticated endpoint
that redirects elsewhere will not stay authenticated. Prefer serving content directly over
redirecting to it.
Use HTTPS. The client does not require it — an http:// URL is fetched without complaint —
but over plain HTTP the manifest, the packages and any Authorization header are exposed,
and substituting the manifest is equivalent to running code as SYSTEM on the device.
TLS validation is the platform's default: the machine trust store and schannel decide. The tool does not pin certificates and does not relax validation, so a host presenting a certificate the device does not trust will fail the download. That matters during OOBE, when a device may not yet have received an internal root certificate — if you serve from an internally-issued certificate, make sure it is trusted before BootstrapMate runs.
The manifest and package requests use .NET's default 100-second HttpClient timeout.
The NetworkTimeout setting is not applied to those requests. Configuring it, in policy
or anywhere else, does not change how long a slow download is allowed to take. Size your
payloads and your host's throughput against 100 seconds per request, not against whatever
NetworkTimeout says. See Retries and Timeouts.
There is no download retry. A failed download fails its item.
Run these from a machine that is representative of your fleet's network path — a device on the provisioning VLAN, not an admin workstation.
Confirm the manifest is served with a 200 and note the content type and any redirect:
curl -sSI https://example.com/bootstrap/bootstrapmate.json
Confirm the body is the document you expect and not a portal or an error page:
curl -sS https://example.com/bootstrap/bootstrapmate.json
Confirm the manifest parses as the format its extension implies:
curl -sS https://example.com/bootstrap/bootstrapmate.json | ConvertFrom-Json
Confirm each package URL answers, and that its size is what you expect:
curl -sSI https://example.com/bootstrap/packages/Example-1.0.msi
If your host is authenticated, confirm it accepts the exact header value you configured, and confirm the packages are reachable the way BootstrapMate will actually reach them:
curl -sSI -H "Authorization: Bearer <token>" https://example.com/bootstrap/bootstrapmate.json
Then walk the checklist:
- The manifest URL is absolute and HTTPS.
- Its path extension matches the format of the body (
.yaml/.ymlfor YAML, anything else for JSON). - Every package URL in the manifest returns
200on its own. - Every item's
filevalue is unique within the manifest. - If a package host needs authentication, it is the same host as the manifest — otherwise the request will be anonymous.
- If the packages are public, the manifest host is the same host only if it is safe for the header to be sent there.
- The TLS certificate chains to a root the device trusts during OOBE.
- Nothing on the path (proxy, WAF, user-agent filter, conditional access) blocks
BootstrapMate/{version}. - No individual download needs more than 100 seconds.
- Every
msiandexepayload is Authenticode-signed, unless you have deliberately setAllowUnsigned; see Security and Package Verification.
Then do the real check: run the tool once against the host with --verbose on a test
device, and read the newest bootstrap.log under C:\ProgramData\ManagedBootstrap\logs. An empty cache directory
afterwards means every item installed; anything left in
C:\ProgramData\ManagedBootstrap\cache is a failure kept for inspection. Do not rely on the
exit code — see Command Line Reference.