Installation, recovery and removal
Before the first registration on any machine, read section 1. A credential provider
that fails to load, or a filter that hides every usable tile, produces a machine nobody
can sign in to. That is an expected outcome several times during bring-up, not a rare
one.
1. Before you install anything
Three things, in this order, on every machine:
- Take a VM snapshot. Reverting takes seconds. Recovering a wedged logon screen by
hand takes an afternoon. If the machine is not a VM, do not arm enforcement on it yet.
- Create and pin a local recovery account, and use it once before arming anything.
An account that has never signed in is not a rehearsed recovery route.
- Rehearse the independent route — the one that works when the DLL itself is broken.
An account exemption inside our credential provider does not help if the DLL fails to
load. See section 5.
Never install this on a workstation you rely on. Build and test in disposable VMs.
2. What the installer places
| Path | Contents | Protection |
|---|---|---|
%ProgramFiles%\Enpoint Trust\ | EnpointTrustCP.dll, etadmin.exe, trust.json, license.jws | Administrator-writable only, by the default Program Files ACL |
%ProgramData%\EnpointTrust\State\ | identity.bin, state.bin, credential.bin, audit.bin | Explicit DACL: SYSTEM and Administrators, full control, inheritance blocked |
%ProgramData%\EnpointTrust\Logs\ | endpoint.log and up to two rotated files, about 15 MiB total | The same explicit DACL. Established before the provider is registered, so a registration or arming failure is itself logged. |
HKLM\...\Credential Providers\{E7B4C1A2-…} | The provider registration | Written by the MSI |
HKLM\...\Credential Provider Filters\{4C1E9A73-…} | The filter registration | Written by etadmin arm, after validation |
trust.json holds public keys and license.jws is signed configuration. Neither is a
secret. Both are integrity-critical, which is why they live behind an administrator-only
ACL.
The enrollment credential is not packaged. build.ps1 refuses to build an MSI with a
credential-looking file in the deployment directory: an MSI is readable by anyone who can
read the installer.
3. Install
# Elevated. From a snapshot. On a disposable VM.
msiexec /i EnpointTrustEndpoint-0.1.0-x64.msi /l*v install.log
The installer lays down files, creates and ACLs the state directory, registers the
provider, and then runs etadmin arm, which validates the configuration and only then
registers the filter.
For a lab machine, follow ../lab/README.md instead of improvising
an order from this document: on a fresh machine with recovery enabled and no pinned
account, that arm attempt refuses, and the sequence is install → pin → activate →
armagain →status.
If validation fails, the filter is never armed and the install still succeeds. That is
deliberate: failing the install would roll back the very tooling needed to diagnose it.
The machine's logon screen is unchanged except for one additional tile.
& "$env:ProgramFiles\Enpoint Trust\etadmin.exe" status
Read the coverage lines. alternate_paths_allowed means this deployment permits a
sign-in route around this product — which may be exactly what you intended, and must not
be described as mandatory MFA.
4. Activate
The enrollment credential is tenant-scoped, activation-only, expiring and revocable. It is
never a command-line argument: a command line is visible to every process on the
machine and is captured in MSI and transcript logs.
# Place the credential in a file readable only by administrators.
$file = "$env:ProgramData\EnpointTrust\enrollment.txt"
# ...write it there by whatever protected means your deployment tooling uses...
& "$env:ProgramFiles\Enpoint Trust\etadmin.exe" pin
& "$env:ProgramFiles\Enpoint Trust\etadmin.exe" activate --credential-file $file
activate overwrites and deletes the file on success. Pass --keep-credential-file only
if your tooling needs it for a second machine, and remove it yourself afterwards.
Run pin before activate, so the resolved recovery SIDs are reported to Core and
so arm will not refuse for want of a pinned account.
If activation is refused
| Core says | What it means | What to do |
|---|---|---|
reenrollment_required (409) | This device_id is already registered | Ask Core to authorize re-enrollment. Do not purge and retry hoping for a new identity: that creates a second registration for one machine. |
enrollment_expired | The deployment credential has expired | Get a new one |
invalid_credential (401) | Wrong or revoked credential | Not an outage; check the credential |
transport tls_trust_failure | Certificate or TLS configuration | Not an outage either; fix the trust chain |
5. Recovery
Four routes, from least to most destructive. Try them in order.
5.1 The recovery account
The designated local account on the console. It takes precedence over a blocked path and
over MFA, and it still requires its real Windows password.
This is the route to have rehearsed. If it has never been used, it is not a route.
5.2 Break glass: disable filtering
HKLM\SOFTWARE\EnpointTrust -> DisableFilter (REG_DWORD, non-zero)
Every credential provider becomes visible again. The Enpoint Trust provider still runs,
and MFA still applies to sign-ins that come through it — this restores alternatives, it
does not disable enforcement.
Needs local administrator, so it repairs a machine an administrator can still reach.
5.3 Remove the filter registration
& "$env:ProgramFiles\Enpoint Trust\etadmin.exe" disarm
or, offline, delete exactly this key:
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Provider Filters\{4C1E9A73-6D28-4B55-9F81-3A7C05E2D164}
Every tile returns; the provider stays installed. **This is the least destructive step
that fully restores a usable logon screen, and it is the one to try first when a machine
is unreachable.**
5.4 Remove the provider registration
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{E7B4C1A2-9F3D-4E6B-8A75-2C1D0F5E8B34}
Deleting that key returns the machine to a stock logon screen. It is the whole
registration.
5.5 The independent route — when the DLL itself is broken
If the DLL fails to load, crashes during enumeration, or faults inside
GetSerialization, an account exemption inside it cannot help. Rehearse one of:
- VM snapshot revert. Seconds, and the reason section 1 insists on it.
- Offline registry edit. Boot WinRE or another OS, load
Windows\System32\config\SOFTWARE as a hive, and delete the two keys above. This needs
the disk to be readable: on a BitLocker volume you need the recovery key, and you need
it before you need it.
- Another local administrator account, created before installation, so an
administrator can still reach the machine to apply 5.2.
The previous version of this repository claimed that putting the filter and the provider
in one DLL made recovery structural — a broken DLL creates neither object, so no
filtering happens. That is only half true and the claim has been removed. It holds
when the DLL fails to load. It does not hold when the DLL loads, filters successfully,
and then fails during enumeration or serialization: filtering has already taken effect.
Rehearse the independent route.
6. Upgrade and repair
msiexec /i EnpointTrustEndpoint-0.2.0-x64.msi /l*v upgrade.log
Device identity, the accepted policy snapshot, the grace ledger and learned denials live
in %ProgramData% and are not owned by any MSI component, so an upgrade leaves them
alone. An upgrade must not hand back consumed grace, and this is how that is
arranged.
If the DLL is loaded in LogonUI, MSI cannot replace it in place. It schedules a reboot
and says so. It does not attempt an unsafe replacement.
etadmin repair re-applies BOTH protected directories' ACLs — the diagnostic log
directory first, then the state directory. Run it if either directory's permissions have
been changed, or if the log directory is missing.
The device's API credential is not removed by an upgrade. The removal half of a major
upgrade runs with REMOVE="ALL" set, so the custom action that deletes it is additionally
guarded with NOT UPGRADINGPRODUCTCODE; without that guard an upgrade left the device
holding an identity marked activated with no secret to authenticate with, and a missing
credential is deliberately not an outage, so no grace applied to it either.
The diagnostic log files are kept through an upgrade, and through an uninstall. See
diagnostics.md section 7.
7. Uninstall
msiexec /x EnpointTrustEndpoint-0.1.0-x64.msi
In order:
etadmin disarmremoves the filter registration first. If everything after this
fails, the machine has every tile back.
- The device API credential is removed.
- The provider registration and the files go.
What uninstall deliberately keeps
The device identity and bounded consumption metadata in %ProgramData%.
A reinstallation on this Windows installation is then recognised as the same device, and
a spent offline grace budget is not handed back by the simple expedient of uninstalling
and reinstalling. This is a security property, and it is why uninstall is not a full
cleanup.
Explicit purge
& "$env:ProgramFiles\Enpoint Trust\etadmin.exe" purge --yes
Removes identity, credential, state and the audit queue.
What purge does not do: it does not return consumed grace (Core is the authority on
what this device is entitled to next), it does not cancel the registration at Core, and it
does not remove the provider registration. A purged machine needs **Core-authorized
re-enrollment**, not a second identity.
8. Diagnostics
& "$env:ProgramFiles\Enpoint Trust\etadmin.exe" status
Reports the device and tenant, whether it is activated, the policy version and where it
came from, the effective action and honest coverage per channel, whether grace and
recovery are enabled, how many recovery accounts are pinned, how many grants and denials
are held, whether offline authorization is quarantined, whether a clock rollback is
latched, and the audit backlog.
It also prints the local diagnostic log level, where it came from, the log directory, and
any sink problem this process has seen — and it says plainly that it cannot report the
live health of the LogonUI instance on the secure desktop.
It also prints what it does not establish. An unactivated endpoint prints
NOT ACTIVATED and says in words that this is not an MFA success. An endpoint whose
identity record is missing or unreadable while its other state proves it registered prints
REGISTRATION INCONSISTENT and refuses to authorize or bypass sign-ins until it is
repaired — it does not fall back to fresh-install behaviour. An activation whose answer
was never seen prints ACTIVATION OUTCOME UNKNOWN and says to retry with the same
enrollment credential rather than re-enrolling.
Local diagnostic logs
Get-Content C:\ProgramData\EnpointTrust\Logs\endpoint.log -Tail 40 |
ForEach-Object { $_ | ConvertFrom-Json } | Format-Table ts, level, component, event, reason
The default level is trace, on a fresh Release installation, with nothing configured. To
change it:
reg add HKLM\SOFTWARE\EnpointTrust\Diagnostics /v LogLevel /t REG_SZ /d info /f /reg:64
A running LogonUI instance keeps its level until it exits. Full detail — format, fields,
limits, what is never written, how to collect, and how to correlate with Core — is in