Master Data Services must be run under a domain account and the credentials provided are used (in part) by configuring an IIS Application Pool to use them; which means one day the passwords are likely going to expire and need to be reset in IIS.

While you can do this in the GUI it's probably best to organise a way to do this in PowerShell code. This has to be run directly on the server or through WinRM; there are .NET equivalents in [Microsoft.Web.Administration.ServerManager]::OpenRemote() but I don't have that working anywhere yet.

Import-Module WebAdministration

$newUserName = "" # Domain\User
$newPassword = "" # Password

# You need to go through Sites to get to Pools
foreach ($site in (Get-ChildItem IIS:\Sites)) {
	foreach ($application in (Get-ChildItem $site.PSPath | Where { $_ -is [Microsoft.IIs.PowerShell.Framework.ConfigurationElement] })) {
		$globalPath = Join-Path $application.PhysicalPath Global.asax

		# Determine which pools are MDS ones
		if ((Test-Path $globalPath) -and (Get-Content $globalPath | Where { $_ -like "*Microsoft.MasterDataServices.WebUI.MDMGlobal*" })) {
			$poolPath = Join-Path "IIS:\AppPools" $application.applicationPool
			$pool = Get-Item $poolPath
			$mdsPoolName = $application.applicationPool

			$identityType = $pool.processModel.identityType
			$userName = $pool.processModel.userName
			$password = $pool.processModel.password

			"Application: $($application.Path)"
			"Pool:        $mdsPoolName"
			"             Auth $identityType, User $userName, Password $password"

			# IIS doesn't store password hashes, it stores the real thing :-(
			if ($userName -ne $newUserName -or $password -ne $newPassword) {
				# Set new username and password
				Set-ItemProperty IIS:\AppPools\$mdsPoolName -Name processModel -Value @{
				    userName = $newUserName
				    password = $newPassword
				    identityType = "SpecificUser"

				# Restart this application pool (or start if it already failed due to a password expiry)
				if ((Get-WebAppPoolState $mdsPoolName).Value -eq "Started") {
				    Restart-WebAppPool $mdsPoolName
				    Start-Sleep -Seconds 1
				} else {
				    Start-WebAppPool $mdsPoolName

			# Test it's up, even if we didn't change anything
			try {
			    Invoke-WebRequest http://localhost$($application.Path)
			} catch {
				if ($_.Exception -like "*503*") { # HTTP Error 503. The service is unavailable.
					Write-Error "http://localhost$($application.Path) is no longer functioning and needs to be investigated."

I've tried to get around the MDS service account requirement by setting up local Windows accounts and manually configuring them in IIS. However this does not end up working properly (MDS believes the local server is the "domain" and the GUI only permits granting access to local users and groups instead of those on the real domain).

With that said, all of this is way more clunky than it should be.