banshee is under active development: collectors will keep changing, and a version you publish will likely need adjustments. For stable use, wait for version 1.0.0.

Active Directory

banshee/active-directory-collection/active-directory/winrm/

service-accounts

The days left before the password of each service account of a domain expires, by WinRM, PowerShell and LDAP

  • active-directory
  • accounts
  • service-accounts
  • password
  • winrm
  • powershell

by banshee1 installation2 versions

v2Latest

Published on October 28, 2026. One naming convention across collections; documentation completed.

Service account passwords, by WinRM

Returns, for each service account of the domain of a domain controller, whether its password expires and, when it does, the days left before it does. A service whose password expires stops at its next logon. Two watches are proposed, both checked: a password that expires soon, and a service account that is no longer found.

Versions

A domain controller running Windows Server 2012 or later, with Windows PowerShell 3.0 or later, as the prerequisites name them. Generic: no folder of version. That every release answers alike is assumed, not yet checked on a real domain controller.

How it works

A service account, here, is an enabled user account that carries a service principal name (servicePrincipalName): the mark of an account a service logs on with, and the definition that needs no list kept by hand. The selection of the probe then narrows it to "Only" the accounts to watch.

The collector runs one PowerShell script, by WinRM, that searches the directory over LDAP, on the domain controller itself:

$ErrorActionPreference = 'Stop'; [Console]::OutputEncoding = New-Object System.Text.UTF8Encoding; $computer = Get-CimInstance Win32_ComputerSystem; $server = $computer.DNSHostName + '.' + $computer.Domain; $rootDSE = [ADSI]('LDAP://' + $server + '/RootDSE'); $domain = [ADSI]('LDAP://' + $server + '/' + $rootDSE.Properties['defaultNamingContext'][0]); $searcher = New-Object DirectoryServices.DirectorySearcher($domain, '(&(objectCategory=person)(objectClass=user)(servicePrincipalName=*)(!(sAMAccountName=krbtgt*))(!(userAccountControl:1.2.840.113556.1.4.803:=2)))', @('sAMAccountName', 'userAccountControl')); $searcher.PageSize = 1000; $never = [DateTime]::MaxValue.ToFileTimeUtc(); $now = [DateTime]::UtcNow; $accounts = @($searcher.FindAll() | ForEach-Object { $account = @{name = [string]$_.Properties['samaccountname'][0]; expires = $false; days = 0}; if (([long]$_.Properties['useraccountcontrol'][0] -band 65536) -eq 0) { $base = New-Object DirectoryServices.DirectorySearcher($_.GetDirectoryEntry(), '(objectClass=*)', @('msDS-UserPasswordExpiryTimeComputed'), 'Base'); $time = [long]$base.FindOne().Properties['msds-userpasswordexpirytimecomputed'][0]; if ($time -lt $never) { $account.expires = $true; $account.days = [long]([DateTime]::FromFileTimeUtc($time) - $now).TotalDays } }; $account }); ConvertTo-Json -Compress -Depth 4 -InputObject @{accounts = $accounts}
  • WinRM hands the script to PowerShell itself: the script is the one of active-directory/ssh/service-accounts, without the powershell -Command "…" that cmd.exe needs there.
  • The search keeps the users with a servicePrincipalName whose bit 0x2 (ACCOUNTDISABLE) of userAccountControl is unset, by the bitwise matching rule 1.2.840.113556.1.4.803 of LDAP in Active Directory; it leaves out the krbtgt accounts, which carry a service principal name of their own and are watched by krbtgt. It is paged, by a thousand.
  • A password with the bit 0x10000 (DONT_EXPIRE_PASSWORD) of userAccountControl never expires: expires is no, and no days-left is returned for the account.
  • Otherwise the time of expiry is msDS-UserPasswordExpiryTimeComputed, an attribute the directory computes when it is read, from the password policy of the domain or the password settings of the user (Microsoft, Active Directory schema). It is read on the account itself. A time beyond the last that Windows writes means it never expires. days-left is counted in whole days on the domain controller, negative once the password has expired.
  • Group managed service accounts are not users: Windows changes their password itself, and they are not returned.
  • No account at all stops the collector as misconfigured, as does an answer that is not the expected JSON.

Nothing is written to the Windows or to the directory: the script only reads.

Prerequisites

  • A domain controller running Windows Server 2012 or later, with Windows PowerShell 3.0 or later.
  • The WinRM service listening in HTTPS, on TCP 5986 or the port set in protocol:winrm:port, open in the Windows firewall to the poller, with a certificate the poller judges by the TLS profile of the probe or pins in protocol:winrm:fingerprint: the steps are those of the windows/winrm/services collector of banshee/windows-collection. NTLM authentication, which the WinRM service accepts as installed.
  • An account of the domain for monitoring, without administrator rights, set in protocol:winrm:user (DOMAIN\account or account@domain) with its password in protocol:winrm:password, member of the group "Remote Management Users" of the domain (on a domain controller, the built-in group of the Builtin container). No other group is given here (see Limits).

Outputs

NameLabelUnitPer instance
expiresPassword expires—yes, per account: yes or no
days-leftBefore the password expiresdyes, per account whose password expires

Watches

NameTitleKindDefaultsChecked by default
expiringPassword expiringlow threshold, on days-leftwarning below 14 d, critical below 3 dyes
missingService account missingexpected instances, on expiresno account named: it raises nothing until names are set on the probeno

Set the selection of the probe to "Only" the accounts the services depend on, and name them in "Service account missing": an account renamed or deleted then raises.

Limits

  • An account that runs a service without any service principal name is not found: a service that logs on with an ordinary user account. Giving it a service principal name is a change to the directory, an administrator's choice.
  • Not yet checked on a real domain controller: the execution; that an account of the domain without administrator rights reads userAccountControl and msDS-UserPasswordExpiryTimeComputed of the users; that the directory returns msDS-UserPasswordExpiryTimeComputed to a search based on the account, as the script asks.