如何使用PowerShell指定应用程序池身份验证的用户和密码

43

我一直在尝试自动化Web应用程序的设置,并使用应用程序池标识适当地配置IIS,但困难重重。 我正在使用PowerShell编写的Web应用程序部署脚本来完成这项工作。我的要求是需要我的PowerShell脚本将应用程序池身份用户设置为特定的服务帐户mydomain\svcuser和密码。以下是示例代码:

$pool = New-Item "IIS:\AppPools\MyAppPool" -Force
$svcuser = "mydomain\svcuser"
$pool.processModel.userName = $svcuser
$password = "somepassword"
$pool.processModel.password = $password
$pool.processModel.identityType = 3
$pool | Set-Item -ErrorAction Stop
当我运行这段代码时,一切似乎都正常——没有出现错误,并且应用程序标识用户名出现在IIS中——但由于某种原因密码没有被正确地设置,如果有设置的话,我无法验证其是否已被设置。 我可以得出结论,即使已经设置了密码,它也不正确。 直到我手动进入IIS并输入密码,它才能对导致应用程序池用户进行身份验证。 因此,部署到Web服务器后应用程序失败,并需要手动干预。
我错过了什么吗?

3
如果你使用PowerShell检查processmodel对象上设置的密码,实际上可以验证它。只需尝试运行命令:get-itemproperty 'IIS':\AppPools\myapppoolnamehere' "ProcessModel" - Robert Westerlund
太好了,谢谢。现在至少我可以验证它实际上是如何处理密码的。希望这能让我更接近解决方案的路径。 - paulyphonic
我已确认密码确实被正确设置。因此唯一可能的结论是,这要么是某种重复的用户错误,要么是当您在UI中手动指定密码与使用PowerShell中的Web管理模块时,IIS在幕后执行其他操作。基本症状是,在运行Web应用程序的部署后,应用程序池会在第一次访问时失败并停止。然后手动重新输入相同的密码即可解决问题。 - paulyphonic
1
事实证明,整个问题都是一个误导。密码输入不正确的原因是我没有预料到的。当我从PowerShell控制台运行脚本时,它可以正常运行,但在我的实际脚本中,我从文件中获取加密密码,然后使用注册表中的密钥进行解密,并且所有这些都是通过PSExec远程调用的。当我在PowerShell中运行时,它可以正确解密,但是当我通过PSExec执行时,同一用户无法访问注册表中的密钥,因此无法解密密码并将其设置为错误值。 - paulyphonic
1
很不幸,我无法重复我上面提到的PSExec声明,并且手动运行PSExec时,我肯定可以在机器上读取注册表(相同的机器,相同的帐户),因此搜索继续进行。一旦我获得所需的详细信息以便提出正确的问题,我可能会关闭或编辑该问题。 :( - paulyphonic
显示剩余4条评论
4个回答

75

1
这个回答实际上已经是问题的一部分了。我已经设置了用户名和密码。如上面的评论所述,实际问题在于运行代码时密码被正确设置,但在我的特定情况下(即TFSDeployer调用PowerShell调用PSExec调用PowerShell),密码未被正确设置。在这里有些东西丢失了。我已经转到另一个公司的不同角色,并且不太可能再回到这个问题并找出是什么原因导致的,所以我希望它能够在某个地方为某人提供一些用处。 - paulyphonic
4
如果不使用 Import-Module WebAdministration,则使用此回答将导致出现 Set-ItemProperty : Cannot find drive. A drive with the name 'IIS' does not exist. 错误。参考链接:https://dev59.com/WWAf5IYBdhLWcg3wqUSN。 - Loftx
谢谢。这不是我遇到的问题。对我来说,这可能是将建议的解决方案与使用PSExec和TFSDeployer相结合导致的问题,因此PowerShell由第三方远程运行,导致某些内容在传输中丢失并导致空参数。当我直接运行相同的脚本时,它按预期工作。该工具的目的是在Visual Studio中构建Web应用程序,然后使用TFSDeployer将构建部署到特定环境,并根据该环境的属性远程配置IIS。 - paulyphonic
2
请注意,这不像通过 UI 进行的那样加密密码。(我不确定这是否会使其更安全,但我也不确定裸文密码的存在是否让我感到舒适。) - jpmc26
这个答案帮助解决了我遇到的问题。我一直在尝试使用三个单独的Set-ItemProperty调用(如@vishnu的答案所描述的)来尝试为应用程序池分配自定义标识 - 不知何故,使用三合一的“-Value”语法让它起作用了。 - Mass Dot Net
显示剩余2条评论

10

经过几次实验,这是我的答案,希望能有所帮助。我曾在IIS 8.5上工作过。

$credentials = (Get-Credential -Message "Please enter the Login credentials including Domain Name").GetNetworkCredential()

$userName = $credentials.Domain + '\' + $credentials.UserName

Set-ItemProperty IIS:\AppPools\$app_pool_name -name processModel.identityType -Value SpecificUser 

Set-ItemProperty IIS:\AppPools\$app_pool_name -name processModel.userName -Value $username

Set-ItemProperty IIS:\AppPools\$app_pool_name -name processModel.password -Value $credentials.Password

以这种方式修改的应用程序池在下一次使用时会失败,并且它们的相关Web应用程序也会停止。我一直无法使其正常工作。 - DWRoelands

4

现在看来你可以更直接地做到这一点

appcmd set apppool junkapp /processmodel.password:junkpassword

0

我正在使用 PowerShell v4,它没有 'ConvertFrom-SecureString',最终我找到了以下方法适用于我:

Import-Module WebAdministration

$cred = Get-Credential -Message "Please enter username and new password to reset IIS app pool password (for app pools running as username)"

$bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($cred.Password)
$plaintext = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr)

$applicationPools = Get-ChildItem IIS:\AppPools | where { $_.processModel.userName -eq 
$cred.UserName }

foreach($pool in $applicationPools)
{
    $apppool = "IIS:\AppPools\" + $pool.Name

    Set-ItemProperty $apppool -name processModel.password -Value $plaintext
}

Write-Host "Application pool passwords updated..." -ForegroundColor Magenta 
Write-Host "" 
Read-Host -Prompt "Press Enter to exit"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接