使用 Chocolatey CSE 的 ARM 模板部署在 PS 脚本上失败
ARM template deploy w/ Chocolatey CSE fails on PS script
我一直在按照这个 ARM 模板构建 VM 并通过 Chocolatey 部署应用程序:
https://github.com/Azure/azure-quickstart-templates/tree/master/visual-studio-dev-vm-chocolatey
尽管 GitHub 上的扩展显示为 Linux 扩展,而不是 MS 扩展(我在我的中更改了它),但我成功部署了 VM。但是,用于安装 Chocolatey 的 PowerShell 自动化脚本失败。
长话短说,我发现它在 Server 2012 上运行良好,但在 Server 2016 上无法运行。
这是 PowerShell 脚本:
param([Parameter(Mandatory=$true)][string]$chocoPackages)
cls
#New-Item "c:\jdchoco" -type Directory -force | Out-Null
#$LogFile = "c:\jdchoco\JDScript.log"
#$chocoPackages | Out-File $LogFile -Append
# Get username/password & machine name
$userName = "artifactInstaller"
[Reflection.Assembly]::LoadWithPartialName("System.Web") | Out-Null
$password = $([System.Web.Security.Membership]::GeneratePassword(12,4))
$cn = [ADSI]"WinNT://$env:ComputerName"
# Create new user
$user = $cn.Create("User", $userName)
$user.SetPassword($password)
$user.SetInfo()
$user.description = "Choco artifact installer"
$user.SetInfo()
# Add user to the Administrators group
$group = [ADSI]"WinNT://$env:ComputerName/Administrators,group"
$group.add("WinNT://$env:ComputerName/$userName")
# Create pwd and new $creds for remoting
$secPassword = ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential("$env:COMPUTERNAME$($username)", $secPassword)
# Ensure that current process can run scripts.
#"Enabling remoting" | Out-File $LogFile -Append
Enable-PSRemoting -Force -SkipNetworkProfileCheck
#"Changing ExecutionPolicy" | Out-File $LogFile -Append
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force
# Install Choco
#"Installing Chocolatey" | Out-File $LogFile -Append
$sb = { iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')) }
Invoke-Command -ScriptBlock $sb -ComputerName $env:COMPUTERNAME -Credential $credential | Out-Null
#"Disabling UAC" | Out-File $LogFile -Append
$sb = { Set-ItemProperty -path HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System -name EnableLua -value 0 }
Invoke-Command -ScriptBlock $sb -ComputerName $env:COMPUTERNAME -Credential $credential
#"Install each Chocolatey Package"
$chocoPackages.Split(";") | ForEach {
$command = "cinst " + $_ + " -y -force"
$command | Out-File $LogFile -Append
$sb = [scriptblock]::Create("$command")
# Use the current user profile
Invoke-Command -ScriptBlock $sb -ArgumentList $chocoPackages -ComputerName $env:COMPUTERNAME -Credential $credential | Out-Null
}
Disable-PSRemoting -Force
# Delete the artifactInstaller user
$cn.Delete("User", $userName)
# Delete the artifactInstaller user profile
gwmi win32_userprofile | where { $_.LocalPath -like "*$userName*" } | foreach { $_.Delete() }
如果我直接在 Server 2016 机器上打开 PowerShell ISE 并运行它,我会收到以下错误提示:
[asdf] Connecting to remote server asdf failed with the following error message : Access is denied. For more information,
see the about_Remote_Troubleshooting Help topic.
+ CategoryInfo : OpenError: (asdf:String) [], PSRemotingTransportException
+ FullyQualifiedErrorId : AccessDenied,PSSessionStateBroken
[asdf] Connecting to remote server asdf failed with the following error message : Access is denied. For more information,
see the about_Remote_Troubleshooting Help topic.
+ CategoryInfo : OpenError: (asdf:String) [], PSRemotingTransportException
+ FullyQualifiedErrorId : AccessDenied,PSSessionStateBroken
Out-File : Cannot bind argument to parameter 'FilePath' because it is null.
At line:48 char:25
+ $command | Out-File $LogFile -Append
+ ~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Out-File], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.OutFileCommand
[asdf] Connecting to remote server asdf failed with the following error message : Access is denied. For more information,
see the about_Remote_Troubleshooting Help topic.
+ CategoryInfo : OpenError: (asdf:String) [], PSRemotingTransportException
+ FullyQualifiedErrorId : AccessDenied,PSSessionStateBroken
'asdf'是机器名
我可以 运行 一步一步地编写代码,但总是会失败:
Invoke-Command -ScriptBlock $sb -ComputerName $env:COMPUTERNAME -Credential $credential
我可以看到帐户已创建,密码已创建,并为其分配了管理员权限,但我猜它只是不喜欢将凭据传递到命令中的方式。为什么这适用于 2012 年而不适用于 2016 年,我不知道。我不是 PowerShell 专家,所以请提供任何帮助。
为了回答我自己的问题,我似乎必须 运行 winrm quickconfig
启用以下注册表项:
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\"
-Name 'LocalAccountTokenFilterPolicy' -Value '1' -PropertyType 'DWord'
所以我调整了脚本以在操作前后包含以下片段。
之前:
# Enable LocalAccountTokenFilterPolicy
$LocalAccToken1 = Get-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\"
If(!($LocalAccToken1.GetValue("LocalAccountTokenFilterPolicy") -eq 1)) {
New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System' `
-Name 'LocalAccountTokenFilterPolicy' -Value '1' -PropertyType 'DWord' -Force
}
之后(我删除了可能源于它的邪恶 activity 的设置 'just in case'):
# Disable LocalAccountTokenFilterPolicy
$LocalAccToken2 = Get-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\"
If($LocalAccToken2.GetValue("LocalAccountTokenFilterPolicy") -eq 1) {
Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System' `
-Name 'LocalAccountTokenFilterPolicy' -Force
}
...希望MS更新他们的模板。
我一直在按照这个 ARM 模板构建 VM 并通过 Chocolatey 部署应用程序:
https://github.com/Azure/azure-quickstart-templates/tree/master/visual-studio-dev-vm-chocolatey
尽管 GitHub 上的扩展显示为 Linux 扩展,而不是 MS 扩展(我在我的中更改了它),但我成功部署了 VM。但是,用于安装 Chocolatey 的 PowerShell 自动化脚本失败。
长话短说,我发现它在 Server 2012 上运行良好,但在 Server 2016 上无法运行。
这是 PowerShell 脚本:
param([Parameter(Mandatory=$true)][string]$chocoPackages)
cls
#New-Item "c:\jdchoco" -type Directory -force | Out-Null
#$LogFile = "c:\jdchoco\JDScript.log"
#$chocoPackages | Out-File $LogFile -Append
# Get username/password & machine name
$userName = "artifactInstaller"
[Reflection.Assembly]::LoadWithPartialName("System.Web") | Out-Null
$password = $([System.Web.Security.Membership]::GeneratePassword(12,4))
$cn = [ADSI]"WinNT://$env:ComputerName"
# Create new user
$user = $cn.Create("User", $userName)
$user.SetPassword($password)
$user.SetInfo()
$user.description = "Choco artifact installer"
$user.SetInfo()
# Add user to the Administrators group
$group = [ADSI]"WinNT://$env:ComputerName/Administrators,group"
$group.add("WinNT://$env:ComputerName/$userName")
# Create pwd and new $creds for remoting
$secPassword = ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential("$env:COMPUTERNAME$($username)", $secPassword)
# Ensure that current process can run scripts.
#"Enabling remoting" | Out-File $LogFile -Append
Enable-PSRemoting -Force -SkipNetworkProfileCheck
#"Changing ExecutionPolicy" | Out-File $LogFile -Append
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force
# Install Choco
#"Installing Chocolatey" | Out-File $LogFile -Append
$sb = { iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')) }
Invoke-Command -ScriptBlock $sb -ComputerName $env:COMPUTERNAME -Credential $credential | Out-Null
#"Disabling UAC" | Out-File $LogFile -Append
$sb = { Set-ItemProperty -path HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System -name EnableLua -value 0 }
Invoke-Command -ScriptBlock $sb -ComputerName $env:COMPUTERNAME -Credential $credential
#"Install each Chocolatey Package"
$chocoPackages.Split(";") | ForEach {
$command = "cinst " + $_ + " -y -force"
$command | Out-File $LogFile -Append
$sb = [scriptblock]::Create("$command")
# Use the current user profile
Invoke-Command -ScriptBlock $sb -ArgumentList $chocoPackages -ComputerName $env:COMPUTERNAME -Credential $credential | Out-Null
}
Disable-PSRemoting -Force
# Delete the artifactInstaller user
$cn.Delete("User", $userName)
# Delete the artifactInstaller user profile
gwmi win32_userprofile | where { $_.LocalPath -like "*$userName*" } | foreach { $_.Delete() }
如果我直接在 Server 2016 机器上打开 PowerShell ISE 并运行它,我会收到以下错误提示:
[asdf] Connecting to remote server asdf failed with the following error message : Access is denied. For more information,
see the about_Remote_Troubleshooting Help topic.
+ CategoryInfo : OpenError: (asdf:String) [], PSRemotingTransportException
+ FullyQualifiedErrorId : AccessDenied,PSSessionStateBroken
[asdf] Connecting to remote server asdf failed with the following error message : Access is denied. For more information,
see the about_Remote_Troubleshooting Help topic.
+ CategoryInfo : OpenError: (asdf:String) [], PSRemotingTransportException
+ FullyQualifiedErrorId : AccessDenied,PSSessionStateBroken
Out-File : Cannot bind argument to parameter 'FilePath' because it is null.
At line:48 char:25
+ $command | Out-File $LogFile -Append
+ ~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Out-File], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.OutFileCommand
[asdf] Connecting to remote server asdf failed with the following error message : Access is denied. For more information,
see the about_Remote_Troubleshooting Help topic.
+ CategoryInfo : OpenError: (asdf:String) [], PSRemotingTransportException
+ FullyQualifiedErrorId : AccessDenied,PSSessionStateBroken
'asdf'是机器名
我可以 运行 一步一步地编写代码,但总是会失败:
Invoke-Command -ScriptBlock $sb -ComputerName $env:COMPUTERNAME -Credential $credential
我可以看到帐户已创建,密码已创建,并为其分配了管理员权限,但我猜它只是不喜欢将凭据传递到命令中的方式。为什么这适用于 2012 年而不适用于 2016 年,我不知道。我不是 PowerShell 专家,所以请提供任何帮助。
为了回答我自己的问题,我似乎必须 运行 winrm quickconfig
启用以下注册表项:
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\"
-Name 'LocalAccountTokenFilterPolicy' -Value '1' -PropertyType 'DWord'
所以我调整了脚本以在操作前后包含以下片段。
之前:
# Enable LocalAccountTokenFilterPolicy
$LocalAccToken1 = Get-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\"
If(!($LocalAccToken1.GetValue("LocalAccountTokenFilterPolicy") -eq 1)) {
New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System' `
-Name 'LocalAccountTokenFilterPolicy' -Value '1' -PropertyType 'DWord' -Force
}
之后(我删除了可能源于它的邪恶 activity 的设置 'just in case'):
# Disable LocalAccountTokenFilterPolicy
$LocalAccToken2 = Get-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\"
If($LocalAccToken2.GetValue("LocalAccountTokenFilterPolicy") -eq 1) {
Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System' `
-Name 'LocalAccountTokenFilterPolicy' -Force
}
...希望MS更新他们的模板。