mirror of
https://github.com/prometheus-community/windows_exporter.git
synced 2026-10-17 10:09:05 +02:00
installer: add SERVICE_ACCOUNT and document a least-privilege service account (#2769)
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
This commit is contained in:
@@ -6,6 +6,10 @@ the [Windows exporter mixin](../contrib/mixin/README.md). Preview the runbook si
|
||||
from the repository root with `hugo server --source docs`; its dedicated GitHub
|
||||
Actions workflow publishes default-branch changes to GitHub Pages.
|
||||
|
||||
[Running as a least-privilege service account](permissions.md) describes
|
||||
the rights the exporter needs and which collectors lose data without
|
||||
administrator rights.
|
||||
|
||||
# Collectors
|
||||
- [`ad`](collector.ad.md)
|
||||
- [`adcs`](collector.adcs.md)
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
# Running as a least-privilege service account
|
||||
|
||||
By default, the MSI installs the `windows_exporter` service as `LocalSystem`.
|
||||
Every collector works with that account. The `SERVICE_ACCOUNT` property of the
|
||||
MSI sets another account, but the MSI does not grant that account any rights.
|
||||
|
||||
The exporter only reads data and needs no administrator rights for the common
|
||||
collectors. This page describes how to run the service as an unprivileged
|
||||
account instead, and which collectors then lose data.
|
||||
|
||||
## Choose an account
|
||||
|
||||
- A virtual service account, `NT SERVICE\windows_exporter`. Windows creates and
|
||||
manages it with the service, and it has no password. It gets the "Log on as
|
||||
a service" right through `NT SERVICE\ALL SERVICES`, which Windows includes in
|
||||
that right by default. A group policy that sets "Log on as a service" without
|
||||
`NT SERVICE\ALL SERVICES` stops virtual accounts from starting. This is the
|
||||
simplest choice on a single host.
|
||||
- A group managed service account (gMSA), for example `CONTOSO\svc-exporter$`,
|
||||
when the account needs rights in the domain or the same identity on many
|
||||
hosts. Install it on the host with `Install-ADServiceAccount` first. It needs
|
||||
the "Log on as a service" user right (`SeServiceLogonRight`).
|
||||
- A domain or local user. It needs the "Log on as a service" user right
|
||||
(`SeServiceLogonRight`) and a password that you have to rotate.
|
||||
|
||||
On top of the account itself, add it to the local **Performance Monitor Users**
|
||||
group. Windows uses this group to grant access to performance counter data
|
||||
(PDH), which most collectors read. Users who run the exporter like this in
|
||||
[#594](https://github.com/prometheus-community/windows_exporter/issues/594)
|
||||
report that the group is enough for the default collectors.
|
||||
**Performance Log Users** is not needed: it adds the right to create data
|
||||
collector sets and logs, and the exporter only reads counters.
|
||||
|
||||
## Set up the service
|
||||
|
||||
Install the MSI with the account:
|
||||
|
||||
```powershell
|
||||
msiexec /i <path-to-msi-file> --% SERVICE_ACCOUNT="NT SERVICE\windows_exporter"
|
||||
```
|
||||
|
||||
For a gMSA, set `SERVICE_ACCOUNT="CONTOSO\svc-exporter$"` (not verified through
|
||||
the MSI). For a user, use `CONTOSO\user` or `.\user` for a local user and also
|
||||
set `SERVICE_PASSWORD`; the MSI keeps it out of its log. A gMSA or a user needs
|
||||
"Log on as a service" before you install, because the MSI starts the service
|
||||
right away. The MSI starts it before the account has the other rights below,
|
||||
so restart the service after granting them.
|
||||
|
||||
Then run this in an elevated PowerShell. Windows resolves the virtual account
|
||||
`NT SERVICE\windows_exporter` only once the service exists, so run it after the
|
||||
installation.
|
||||
|
||||
```powershell
|
||||
$service = 'windows_exporter'
|
||||
$account = "NT SERVICE\$service"
|
||||
|
||||
# Only needed if the MSI was installed without SERVICE_ACCOUNT. A virtual
|
||||
# account has no password.
|
||||
sc.exe config $service obj= $account
|
||||
|
||||
# Grant read access to performance counters. S-1-5-32-558 is the Performance
|
||||
# Monitor Users group in every display language. SilentlyContinue lets the script
|
||||
# run again after an MSI upgrade, when the account is already a member.
|
||||
Add-LocalGroupMember -SID 'S-1-5-32-558' -Member $account -ErrorAction SilentlyContinue
|
||||
|
||||
# The default textfile directory and config file below Program Files are readable
|
||||
# by all users. Grant read access to other locations you use, for example:
|
||||
# icacls 'D:\metrics' /grant "${account}:(OI)(CI)RX"
|
||||
# icacls 'D:\windows_exporter\config.yaml' /grant "${account}:R"
|
||||
|
||||
Restart-Service $service
|
||||
```
|
||||
|
||||
`Add-LocalGroupMember` and `Remove-LocalGroupMember` come from the
|
||||
`Microsoft.PowerShell.LocalAccounts` module, which needs 64-bit PowerShell.
|
||||
|
||||
Without `SERVICE_ACCOUNT`, use `sc.exe config windows_exporter obj= 'CONTOSO\svc-exporter$'`
|
||||
for a gMSA, and also add `password= '<password>'` for a user. For both, grant
|
||||
"Log on as a service" with `secpol.msc` or a group policy: neither the MSI nor
|
||||
`sc.exe` grants it, only the Services console (`services.msc`) does when you set
|
||||
the account there.
|
||||
|
||||
The account also needs:
|
||||
|
||||
- Read access to the config file (`--config.file`), the textfile directories
|
||||
(`--collector.textfile.directories`), the files and registry keys that the
|
||||
`file` and `registry` collectors read, and the TLS key and certificate of
|
||||
`--web.config.file`.
|
||||
- Write access to the log file and its directory if `--log.file` is a path. The
|
||||
default for the service, the Windows event log, needs no extra rights.
|
||||
|
||||
Writers of textfile metrics need write access to their directory; the exporter
|
||||
itself only reads it.
|
||||
|
||||
To check the result, look at the account and at the collectors that fail:
|
||||
|
||||
```powershell
|
||||
(Get-CimInstance Win32_Service -Filter "Name='windows_exporter'").StartName
|
||||
(Invoke-WebRequest -Uri 'http://localhost:9182/metrics' -UseBasicParsing).Content -split "`n" |
|
||||
Select-String 'windows_exporter_collector_success'
|
||||
```
|
||||
|
||||
How missing rights show up depends on when the collector reads the data:
|
||||
|
||||
- Some collectors query WMI while they start: `dns` (`wmi_stats`), `fsrmquota`
|
||||
and `storage_spaces`. Access denied there is not an expected startup error,
|
||||
so the exporter exits and the service does not start. The error is in the
|
||||
Application event log (source `windows_exporter`). Grant access or disable
|
||||
the collector.
|
||||
- A collector that fails while scraping has
|
||||
`windows_exporter_collector_success` 0 and logs the error.
|
||||
- Partial data loss, such as skipped services, missing scheduled tasks or empty
|
||||
process labels, leaves `windows_exporter_collector_success` at 1.
|
||||
|
||||
### Reverting and MSI upgrades
|
||||
|
||||
To run the service as `LocalSystem` again:
|
||||
|
||||
```powershell
|
||||
sc.exe config windows_exporter obj= LocalSystem
|
||||
Remove-LocalGroupMember -SID 'S-1-5-32-558' -Member 'NT SERVICE\windows_exporter'
|
||||
Restart-Service windows_exporter
|
||||
```
|
||||
|
||||
The MSI does not remember `SERVICE_ACCOUNT`, like its other properties. An
|
||||
upgrade installs the service again, as `LocalSystem` unless you pass
|
||||
`SERVICE_ACCOUNT` (and `SERVICE_PASSWORD`) again. Pass the same properties to
|
||||
every `msiexec` run. Group memberships and user rights of the account stay.
|
||||
|
||||
## Collectors with limits
|
||||
|
||||
Collectors that are not listed here read performance counters, the registry
|
||||
below `HKLM\SOFTWARE`, or other APIs that all users can read, and are expected
|
||||
to work with the setup above. Only some of them were reported working in the
|
||||
issue linked above (`cpu`, `logical_disk`, `memory`, `mssql`, `os`, `process`,
|
||||
`system`); the others are not verified. A counter set whose provider restricts access itself
|
||||
can still fail.
|
||||
|
||||
| Collector | Without administrator rights | What to grant |
|
||||
|-----------|------------------------------|---------------|
|
||||
| `container` | The `hcs` sub-collector uses the Host Compute Service, the Host Compute Network service for network statistics and the CRI endpoint (containerd named pipe); memory statistics open the container processes. The `hostprocess` sub-collector also uses the CRI endpoint and opens the job objects of HostProcess containers. Not verified, expected to fail. | Not verified. Use `LocalSystem`. |
|
||||
| `dhcp` | `server_metrics` reads counters and works. `scope_metrics` uses the DHCP Server API (`dhcpsapi.dll`), which only allows Administrators, DHCP Administrators and DHCP Users. | Add the account to the local **DHCP Users** group (read-only access to the DHCP server). Not verified live. |
|
||||
| `dns` | `metrics` reads counters and works. `wmi_stats` queries `MicrosoftDNS_Statistic` in `root\MicrosoftDNS`. | WMI namespace security on `root\MicrosoftDNS`, see below. Whether the DNS provider also requires DnsAdmins is not verified. |
|
||||
| `fsrmquota` | Queries `MSFT_FSRMQuota` in `root\Microsoft\Windows\FSRM`. | WMI namespace security on that namespace. Whether the FSRM provider allows non-administrators is not verified. |
|
||||
| `hyperv` | The counter sub-collectors work. `host` uses the Host Compute Service; `replica_vm`, `virtual_hard_disk` and `wmi_health` query `root\virtualization\v2`, and `virtual_hard_disk` also opens the virtual disk files. | Membership in **Hyper-V Administrators** gives access to the Hyper-V WMI provider, but it also grants full control over Hyper-V. Read access to the VHD/VHDX files for `virtual_hard_disk`. Not verified; disable these sub-collectors with `--collector.hyperv.enabled` instead. |
|
||||
| `mscluster` | Reads through the Failover Cluster API (ClusAPI), which requires cluster access. | `Grant-ClusterAccess -User <account> -ReadOnly` on the cluster. Not verified for a virtual account; use a gMSA or domain account, which is the same identity on every node. |
|
||||
| `process` | All metrics work. The `owner`, `cmdline` and `process_group_id` labels of `windows_process_info` are empty for processes of other users and protected processes (see [`collector.process.md`](collector.process.md)). With `--collector.process.iis`, the application pool comes from the `w3wp` command line, which needs access to the worker process; the fallback queries `root\WebAdministration`. | No grant that opens processes of other users is narrower than administrator rights. WMI namespace security on `root\WebAdministration` for the IIS fallback (not verified). |
|
||||
| `scheduled_task` | Lists only the tasks whose security descriptor lets the account read them, so tasks are missing. | Not verified. Use `LocalSystem` to see all tasks. |
|
||||
| `service` | Works for most services. A service whose security descriptor denies the account `SERVICE_QUERY_CONFIG` is skipped with a warning and has no metrics at all, including `windows_service_state`. `windows_service_process` is missing for services whose process the account can't open with `PROCESS_QUERY_LIMITED_INFORMATION`. | Not verified which services are affected. |
|
||||
| `storage_spaces` | Queries `MSFT_StoragePool` and `MSFT_VirtualDisk` in `root\Microsoft\Windows\Storage`. | WMI namespace security on that namespace. Whether the storage provider allows non-administrators is not verified. |
|
||||
| `wmi` | Queries the namespaces that you configure. `root\cimv2` allows all authenticated users. | WMI namespace security for other namespaces. |
|
||||
| `file`, `registry`, `textfile` | Read the paths and registry keys that you configure. | Read access on those files, directories and keys. |
|
||||
| `update` | Uses the Windows Update Agent API. Not verified. | Not verified. |
|
||||
|
||||
The `logical_disk` collector, including `bitlocker_status`, works for
|
||||
non-elevated accounts (see [`collector.logical_disk.md`](collector.logical_disk.md)).
|
||||
`cpu_info` and `diskdrive` query `root\cimv2`, which all authenticated users can
|
||||
read.
|
||||
|
||||
### Granting WMI namespace access
|
||||
|
||||
By default, all authenticated users have the **Enable Account** permission on
|
||||
`root\cimv2`. Other namespaces, such as the ones of the DNS, FSRM, storage and
|
||||
Hyper-V providers, can be limited to administrators. To grant access:
|
||||
|
||||
1. Run `wmimgmt.msc`, right-click **WMI Control (Local)** and select
|
||||
**Properties**.
|
||||
2. On the **Security** tab, select the namespace, for example
|
||||
`Root\MicrosoftDNS`, and select **Security**.
|
||||
3. Add the account (`NT SERVICE\windows_exporter`) and allow **Enable Account**.
|
||||
The exporter queries locally, so **Remote Enable** is not needed.
|
||||
4. Restart the service.
|
||||
|
||||
A provider can check the caller again after the namespace check and still deny
|
||||
the query. If the collector keeps failing with access denied, that provider
|
||||
needs administrator rights or a role-specific group.
|
||||
Reference in New Issue
Block a user