问题描述
使用以下 DSC 配置(仅资源部分的片段,删除 SO 的前导码、诊断和 Start-DscConfiguration 部分):
With the following DSC configuration (snippet of the resources section only, cut out preamble, diagnostics, and Start-DscConfiguration parts for SO):
Package TFSServer2013 {
Name = "Microsoft Team Foundation Server 2013 Update 3 (x64)"
Path = '$InstallerPath\Team Foundation Server 2013\tfs_server.exe'
Arguments = "/quiet"
Credential = $Credential
Ensure = "Present"
ProductID = "B516BA7C-3C20-3FCC-B130-B42058ABF87A"
}
File TFSUserFile {
DestinationPath = "$Env:TEMP\TFSConfig\TfsUserName.clixml"
Attributes = "Hidden"
SourcePath = $TFSUsernameFile
Ensure = "Present"
Force = $true
Credential = $Credential
Type = "File"
MatchSource = $true
}
File TFSPasswordFile {
DestinationPath = "$Env:TEMP\TFSConfig\TfsUserPassword.clixml"
Attributes = "Hidden"
SourcePath = $TFSUserPasswordFile
Ensure = "Present"
Force = $true
Credential = $Credential
Type = "File"
MatchSource = $true
}
File TfsBuildAgentConfigureScript {
DestinationPath = "$LocalInstallerPath\PowerShell\Configure-TfsBuildService.ps1"
SourcePath = "$POSModulePath\Configure-TfsBuildService.ps1"
Ensure = "Present"
Force = $true
Credential = $Credential
Type = "File"
MatchSource = $true
}
Script TFSConfigure {
SetScript = "
. C:\BuildAgent\Installers\PowerShell\Configure-TfsBuildService.ps1
Setup-TfsBuildService -ConfigIniFile 'C:\BuildAgent\Logs\TfsConfig.ini' -TfsBuildControllerName 'TFSMASTER' -TfsServiceUri 'http://mytfsservice:8080/tfs/My_Collection' -TfsUsernameClixml ""`$Env:TEMP\TFSConfig\TfsUserName.clixml"" -LogFilesPath 'C:\BuildAgent\Logs' -TfsUserPasswordClixml ""`$Env:TEMP\TFSConfig\TfsUserPassword.clixml""
if (`$false) { Remove-Item -Force -Path ""$Env:TEMP\TFSConfig\TfsUserPassword.clixml"" }
"
TestScript = "
New-EventLog -LogName 'Windows Powershell' -Source DSC -ErrorAction SilentlyContinue
Write-EventLog -LogName 'Windows PowerShell' -Source DSC -EntryType Information -EventId 1 -Message ""Testing if TFS build service is up and running.""
`$srv = Get-WmiObject -Class Win32_Service | Where-Object -FilterScript { (`$PSItem.Name -ne `$null) -and (`$PSItem.Name.Equals(""TFSBuildServiceHost.2013"")) }
return (`$srv -ne `$null)
"
GetScript = "
New-EventLog -LogName 'Windows Powershell' -Source DSC -ErrorAction SilentlyContinue
`$ensure='Absent'
if (Test-Path 'C:\BuildAgent\Logs\TfsConfig.ini' -ErrorAction Ignore) { `$ensure = 'Present' }
Write-EventLog -LogName 'Windows PowerShell' -Source DSC -EntryType Information -EventId 1 -Message ""TFSConfigure GetScript (C:\BuildAgent\Logs\TfsConfig.ini): Ensure=`$ensure""
@{Ensure=`$ensure}
"
Credential = $Credential
DependsOn = "[File]TFSPasswordFile","[File]TFSUserFile","[Package]TFSServer2013","[File]TfsBuildAgentConfigureScript"
}
我在无人参与模式下配置 TFS 构建服务的脚本如下(出于 SO 的目的,我删除了日志记录、错误检查和诊断):
My script to configure the TFS Build Service in unattended mode is as follows (I've taken out logging, error checking, and diagnostics for the purpose of SO):
Function Setup-TfsBuildService
{
Param(
[Parameter(Mandatory=$true)]
[string]
$ConfigIniFile,
[Parameter(Mandatory=$true)]
[string]
$TfsBuildControllerName,
[Parameter(Mandatory=$true)]
[string]
$TfsServiceUri,
[Parameter(Mandatory=$true)]
[string]
$TfsUsernameClixml,
[Parameter(Mandatory=$true)]
[string]
$LogFilesPath,
[Parameter(Mandatory=$true)]
[string]
$TfsUserPasswordClixml,
[Parameter()]
[string]
$TfsConfigExePath="$Env:ProgramFiles\Microsoft Team Foundation Server 12.0\Tools\TfsConfig.exe"
)
if (Test-Path -Path $TfsUsernameClixml)
{
$tfsuser = (Import-CliXml -Path $TfsUsernameClixml)
}
else { return }
Remove-Item -Force -Path $ConfigIniFile -ErrorAction SilentlyContinue
# Stop any existing TFS 2013 build service
if (Get-Service -Name "TFSBuildServiceHost.2013" -ErrorAction Ignore)
{
$srv = Get-WmiObject -Class Win32_Service | Where-Object -FilterScript { ($PSItem.Name -ne $null) -and ($PSItem.Name.Equals("TFSBuildServiceHost.2013")) }
$srv.StopService() | Out-Null
$srv.Delete() | Out-Null
}
# Create the unattend file:
$inputparams = "ConfigurationType=scale;AgentCount=1;ExistingControllerName=$TfsBuildControllerName;CleanResources=True;CollectionUrl=$TfsServiceUri;IsServiceAccountBuiltIn=False;ServiceAccountName=$tfsuser"
$tfsconfoutput = & $TfsConfigExePath unattend /create /type:build /unattendfile:"$ConfigIniFile" /inputs:$inputparams 2>&1
$tfsconfoutput | Out-File -FilePath (Join-Path $LogFilesPath "TfsConfigUnattendFile.log") -Force
# Install the service:
$Error.Clear()
$tfsuserpswd = (Import-CliXml -Path $TfsUserPasswordClixml)
$tfsconfoutput = & $TfsConfigExePath unattend /configure /unattendfile:"$ConfigIniFile" /inputs:"ServiceAccountPassword=$tfsuserpswd" /continue 2>&1
Remove-Variable tfsuserpswd
$tfsconfoutput | Out-File -FilePath (Join-Path $LogFilesPath "TfsInstallUnattend.log") -Force
}
只要我在本地登录,我就可以在我的任何构建 Windows 2012 R2 代理上成功运行脚本 Configure-TfsBuildService.ps1.
I can run the script Configure-TfsBuildService.ps1 successfully on any of my build Windows 2012 R2 agents successfully as long as I'm logged in locally.
除了 TFS 构建服务配置块之外,我还可以针对我的所有构建代理成功运行我的 DSC 配置.
Apart from the TFS Build Service configuration block, I can run my DSC configuration successfully against all of my build agents.
但是,当我尝试运行我的 TFS 构建服务配置块时,我的 DSC 配置成功"但是该服务的无人值守配置失败并显示以下日志消息:
However, when I attempt to run my TFS Build Service configuration block, my DSC configuration 'succeeds' however the unattended configuration of the service fails with the following log message:
[Info @15:40:47.754] +-+-+-+-+-| Verifying that the running account has required Team Foundation Server permissions |+-+-+-+-+-
[Info @15:40:47.754] Starting Node: TBPERMISSIONS
[Info @15:40:47.754] NodePath : VINPUTS/Progress/Conditional/TBPERMISSIONS
[Error @15:40:47.920]
Exception Message: TF30063: You are not authorized to access http://mytfsservice:8080/tfs/My_Collection. (type TeamFoundationServerUnauthorizedException)
Exception Stack Trace: at Microsoft.TeamFoundation.Client.Channels.TfsHttpWebRequest.SendRequest()
at Microsoft.TeamFoundation.Client.Channels.TfsHttpRequestChannel.Request(TfsMessage message, TimeSpan timeout)
at Microsoft.TeamFoundation.Client.Channels.TfsHttpClientBase.Invoke(TfsClientOperation operation, Object[] parameters, TimeSpan timeout, Object[]& outputs)
at Microsoft.TeamFoundation.Framework.Client.LocationWebService.Connect(Int32 connectOptions, Int32 lastChangeId, Int32 features)
at Microsoft.TeamFoundation.Framework.Client.FrameworkServerDataProvider.Connect(ConnectOptions connectOptions)
at Microsoft.TeamFoundation.Admin.AuthenticatedCollectionProvider.Microsoft.TeamFoundation.Admin.IAuthenticatedCollectionProvider.GetAuthenticatedConnection()
at Microsoft.TeamFoundation.Admin.VerifyPermissionsToConfigure.Run(ActivityContext context)
Inner Exception Details:
Exception Message: The remote server returned an error: (401) Unauthorized. (type WebException)Status: ProtocolError
Response Status Code: Unauthorized
Response Status Message: Unauthorized
Exception Stack Trace: at System.Net.HttpWebRequest.GetResponse()
at Microsoft.TeamFoundation.Client.Channels.TfsHttpWebRequest.SendRequestAndGetResponse(HttpWebRequest webRequest, WebException& webException)
[Info @15:40:47.920] Node returned: Error
[Error @15:40:47.920] TF30063: You are not authorized to access http://mytfsservice:8080/tfs/My_Collection.
[Info @15:40:47.920] Completed BuildServicePermissions: Error
[Info @15:40:47.920] -----------------------------------------------------
由于我使用自己的凭据运行 DSC 配置,并且我是 TFS 服务的项目集合管理员,因此没有权限问题.我已经通过在代理机器上本地成功运行配置脚本并在那里成功证明了这一点.
Since I am running the DSC configuration with my own credentials, and I am a Project Collection Administrator on the TFS service, there is no issue with permissions. I've proven that by successfully running the configuration script locally on an agent machine and being successful there.
我意识到 PowerShell 不允许双跳权限,但由于 DSC 在所涉及的代理上执行,因此不应该存在双跳凭据问题,并且允许将权限中继到 TFS注册服务.
I realize that there is no double-hop permissions allowed with PowerShell, but since DSC executes on the agent involved, there shouldn't be an issue of double-hop credentials and the permissions would be allowed to be relayed to the TFS service for registration.
也许我错过了一些更琐碎的事情?
Maybe I've missed something more trivial?
TFS 2012/2013 无人值守安装的说明可在此处找到:http://blogs.msdn.com/b/visualstudioalm/archive/2012/10/12/unattended-installation-of-team-foundation-server-2012.aspx
A description of unattended installation of TFS 2012/2013 is found here: http://blogs.msdn.com/b/visualstudioalm/archive/2012/10/12/unattended-installation-of-team-foundation-server-2012.aspx
推荐答案
您可能仍会遇到双跳问题.DSC 需要 WinRM,即使在推送模式下运行时也是如此,因为无论它在执行配置时远程"进入机器的内容.这仍然算作一跳.
You may still be running into double-hop issues. DSC requires WinRM, even when run in Push mode, because no matter what it's "remoting" into the machine when it executes the configuration. That still counts as a hop.
考虑这 2 次执行:
$sb = { Get-Content \\server\share\file.txt }
Invoke-Command -ScriptBlock $sb
Invoke-Command -ComputerName . -ScriptBlock $sb
第一次调用应该可以工作(没有使用该参数集进行远程处理).第二个应该失败并出现权限错误.
The first invocation should work (no remoting is being done with that parameter set). The second should fail with a permission error.
这篇关于为什么我不能通过 Powershell DSC 在无人参与模式下配置 TFS 构建服务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!