【问题标题】:VSTS Release Management deployment failing due to security issues由于安全问题,VSTS 发布管理部署失败
【发布时间】:2025-11-23 17:30:01
【问题描述】:

问题

几天来,我一直在为 VSTS 发布管理上的部署失败而苦苦挣扎。我基于包含 cskpg 和 cscfg 文件的工件制定了发布定义以部署 Azure 云服务。起初,我没有使用托管构建控制器获得太多信息。部署的日志是空的,只有消息“在此环境上的部署已取消”。显示在发布日志中。

为了获得更多有用的调试信息,我下载了 Windows 构建代理并将其作为服务安装在我的本地计算机上。在日志中,我看到一个安全异常:Microsoft.VisualStudio.Services.Common.VssUnauthorizedException。 以下是 Windows Build Agent 日志的摘录:

09:36:41.217088 WorkerRunner.RunJobOnWorker - enter
09:36:41.232710 WorkerRunner.RunJobOnWorker - starting the job
09:36:41.232710 BaseLogger.LogStatus(scope.JobId = b85840a5-bbf5-4c92-8b46-414ea85e29fa, scope.TimelineRecordId = 77c25a08-adf0-44e9-a546-7115ebc413f8, record.Name = Release)
09:36:41.232710 JobManager.LogStatus (scope.JobId = b85840a5-bbf5-4c92-8b46-414ea85e29fa, record.Name = Release)
09:36:41.232710 JobManager.LogStatus - job not found in dictionary (scope.JobId = b85840a5-bbf5-4c92-8b46-414ea85e29fa)
09:36:41.232710 [77c25a08-adf0-44e9-a546-7115ebc413f8][b85840a5-bbf5-4c92-8b46-414ea85e29fa]Record: t=Job, n=Release, s=InProgress, st=12/4/2015 9:36:41 AM, 0%, ft=, r=: Starting
09:36:41.232710 BaseLogger.LogConsoleMessage(scope.JobId = b85840a5-bbf5-4c92-8b46-414ea85e29fa, message = Agent version: 1.91.1)
09:36:41.232710 JobManager.LogConsoleMessage (scope.JobId = b85840a5-bbf5-4c92-8b46-414ea85e29fa, message = Agent version: 1.91.1)
09:36:41.232710 JobManager.LogConsoleMessage - job not found in dictionary (scope.JobId = b85840a5-bbf5-4c92-8b46-414ea85e29fa)
09:36:41.232710 [77c25a08-adf0-44e9-a546-7115ebc413f8][b85840a5-bbf5-4c92-8b46-414ea85e29fa]Agent version: 1.91.1
09:36:41.232710 BaseLogger.LogConsoleMessage(scope.JobId = b85840a5-bbf5-4c92-8b46-414ea85e29fa, message = Starting job)
09:36:41.232710 JobManager.LogConsoleMessage (scope.JobId = b85840a5-bbf5-4c92-8b46-414ea85e29fa, message = Starting job)
09:36:41.232710 JobManager.LogConsoleMessage - job not found in dictionary (scope.JobId = b85840a5-bbf5-4c92-8b46-414ea85e29fa)
09:36:41.232710 [77c25a08-adf0-44e9-a546-7115ebc413f8][b85840a5-bbf5-4c92-8b46-414ea85e29fa]Starting job
09:36:41.232710 JobManager.StartJob(job.JobId = b85840a5-bbf5-4c92-8b46-414ea85e29fa)
09:36:41.232710 JobInfo.ctor
09:36:41.232710 JobInfo.ctor - leave
09:36:41.232710 JobManager.StartJob - calling JobWriter.StartJob
09:36:41.232710 JobWriter.StartJob - enter
09:36:41.232710 JobWriter.StartJob - (SKIPPING)first renew
09:36:41.326473 JobWriter.StartJob - start continual renewing
09:36:41.326473 AuthorizationType : OAuth
09:36:41.748960 ConsoleTimer_Callback - enter (22)
09:36:41.748960 ConsoleTimer_Callback - Inside Lock
09:36:41.748960 ConsoleTimer_Callback - processing job b85840a5-bbf5-4c92-8b46-414ea85e29fa
09:36:41.748960 ConsoleTimer_Callback - leave
09:36:41.986477 StatusTimer_Callback - enter (26)
09:36:41.986477 StatusTimer_Callback - processing job b85840a5-bbf5-4c92-8b46-414ea85e29fa
09:36:41.986477 StatusTimer_Callback - leave
09:36:42.232703 LogFileTimer_Callback - enter (21)
09:36:42.232703 LogFileTimer_Callback - processing job b85840a5-bbf5-4c92-8b46-414ea85e29fa
09:36:42.232703 LogFileTimer_Callback - found 0 records for job b85840a5-bbf5-4c92-8b46-414ea85e29fa
09:36:42.232703 LogFileTimer_Callback - leave
09:36:42.263938 ConsoleTimer_Callback - enter (18)
09:36:42.263938 ConsoleTimer_Callback - Inside Lock
09:36:42.263938 ConsoleTimer_Callback - processing job b85840a5-bbf5-4c92-8b46-414ea85e29fa
09:36:42.263938 ConsoleTimer_Callback - leave
09:36:42.518076 ---------------------------------------------------------------------------
09:36:42.523266 Microsoft.VisualStudio.Services.Common.VssUnauthorizedException: TF400813: The user 'Build\{guid_removed_intentionally}' is not authorized to access this resource.

09:36:42.523266    at Microsoft.VisualStudio.Services.Common.VssHttpMessageHandler.<SendAsync>d__17.MoveNext()

09:36:42.523266 --- End of stack trace from previous location where exception was thrown ---

09:36:42.523266    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)

09:36:42.523266    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

09:36:42.523266    at Microsoft.VisualStudio.Services.WebApi.VssHttpRetryMessageHandler.<SendAsync>d__3.MoveNext()

09:36:42.523266 --- End of stack trace from previous location where exception was thrown ---

09:36:42.523266    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)

09:36:42.523266    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

09:36:42.523266    at Microsoft.VisualStudio.Services.WebApi.VssHttpClientBase.<SendAsync>d__50.MoveNext()

09:36:42.523266 --- End of stack trace from previous location where exception was thrown ---

09:36:42.523266    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)

09:36:42.523266    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

09:36:42.523266    at Microsoft.VisualStudio.Services.WebApi.VssHttpClientBase.<SendAsync>d__47`1.MoveNext()

09:36:42.523266 --- End of stack trace from previous location where exception was thrown ---

09:36:42.523266    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)

09:36:42.523790    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

09:36:42.523790    at Microsoft.VisualStudio.Services.Location.Client.LocationHttpClient.<GetConnectionDataAsync>d__6.MoveNext()

09:36:42.523790 --- End of stack trace from previous location where exception was thrown ---

09:36:42.523790    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)

09:36:42.523790    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

09:36:42.523790    at Microsoft.VisualStudio.Services.Client.VssServerDataProvider.<ConnectAsync>d__39.MoveNext()

09:36:42.523790 --- End of stack trace from previous location where exception was thrown ---

09:36:42.523790    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)

09:36:42.523790    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

09:36:42.523790    at Microsoft.TeamFoundation.DistributedTask.Agent.Common.ConnectionHelper.GetConnection(Uri serverUri, VssCredentials credentials)

09:36:42.523790    at Microsoft.TeamFoundation.DistributedTask.Agent.JobWriter.StartJob()
09:36:42.523790    at Microsoft.VisualStudio.Services.Common.VssHttpMessageHandler.<SendAsync>d__17.MoveNext()

09:36:42.523790 --- End of stack trace from previous location where exception was thrown ---

09:36:42.523790    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)

09:36:42.523790    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

09:36:42.523790    at Microsoft.VisualStudio.Services.WebApi.VssHttpRetryMessageHandler.<SendAsync>d__3.MoveNext()

09:36:42.523790 --- End of stack trace from previous location where exception was thrown ---

09:36:42.523790    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)

09:36:42.523790    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

09:36:42.523790    at Microsoft.VisualStudio.Services.WebApi.VssHttpClientBase.<SendAsync>d__50.MoveNext()

09:36:42.523790 --- End of stack trace from previous location where exception was thrown ---

09:36:42.523790    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)

09:36:42.523790    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

09:36:42.523790    at Microsoft.VisualStudio.Services.WebApi.VssHttpClientBase.<SendAsync>d__47`1.MoveNext()

09:36:42.523790 --- End of stack trace from previous location where exception was thrown ---

09:36:42.523790    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)

09:36:42.523790    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

09:36:42.523790    at Microsoft.VisualStudio.Services.Location.Client.LocationHttpClient.<GetConnectionDataAsync>d__6.MoveNext()

09:36:42.523790 --- End of stack trace from previous location where exception was thrown ---

09:36:42.523790    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)

09:36:42.523790    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

09:36:42.523790    at Microsoft.VisualStudio.Services.Client.VssServerDataProvider.<ConnectAsync>d__39.MoveNext()

09:36:42.523790 --- End of stack trace from previous location where exception was thrown ---

09:36:42.523790    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)

09:36:42.523790    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

09:36:42.523790    at Microsoft.TeamFoundation.DistributedTask.Agent.Common.ConnectionHelper.GetConnection(Uri serverUri, VssCredentials credentials)

09:36:42.523790    at Microsoft.TeamFoundation.DistributedTask.Agent.JobWriter.StartJob()
09:36:42.523790 ---------------------------------------------------------------------------
09:36:42.525271 Process logging event with context handler.
09:36:42.525271 BaseLogger.LogConsoleMessage(scope.JobId = b85840a5-bbf5-4c92-8b46-414ea85e29fa, message = ##[error]The Agent failed to start this job. Error: TF400813: The user 'Build\985376fd-d1bd-45eb-b657-a7fd22d51cb9' is not authorized to access this resource.)
09:36:42.525271 JobManager.LogConsoleMessage (scope.JobId = b85840a5-bbf5-4c92-8b46-414ea85e29fa, message = ##[error]The Agent failed to start this job. Error: TF400813: The user 'Build\985376fd-d1bd-45eb-b657-a7fd22d51cb9' is not authorized to access this resource.)
09:36:42.525271 JobManager.LogConsoleMessage - message enqueued
09:36:42.525271 [77c25a08-adf0-44e9-a546-7115ebc413f8][b85840a5-bbf5-4c92-8b46-414ea85e29fa]##[error]The Agent failed to start this job. Error: TF400813: The user 'Build\985376fd-d1bd-45eb-b657-a7fd22d51cb9' is not authorized to access this resource.
09:36:42.525271 JobManager.FinishJob(jobId = b85840a5-bbf5-4c92-8b46-414ea85e29fa, result = Failed)
09:36:42.748347 StatusTimer_Callback - enter (22)
09:36:42.748347 StatusTimer_Callback - processing job b85840a5-bbf5-4c92-8b46-414ea85e29fa
09:36:42.748347 StatusTimer_Callback - leave
...
09:36:53.551559 JobInfo.Dispose - leave
09:36:53.551559 JobManager.FinishJob - Removing JobId b85840a5-bbf5-4c92-8b46-414ea85e29fa from Jobs
09:36:53.551559 Failed to start the job, could not create the http client with the given credentials.

其他信息

我应该提到,我在从 Azure 云服务部署任务中的下拉框中访问存储帐户和云服务时也遇到了问题。

Azure 云服务部署

我不知道这两个问题是否相互关联,但它可能是有用的信息。我已在 VSTS 服务配置选项卡中创建了必要的服务端点。为了进行测试,我制作了每个版本中的一个:凭据、基于证书和服务主体身份验证。不幸的是,他们似乎都无法列出存储帐户和服务名称。 (仅基于凭据和证书的端点显示在 Azure 云服务部署任务的 Azure 订阅下拉菜单中)。当我在此下拉列表中切换帐户时,我在网络日志中看到 HTTP 错误,一个用于存储帐户下拉列表,一个用于云服务下拉列表,这让我相信它无法对 Azure 帐户进行身份验证。基于服务主体的服务连接不会显示在 Azure 订阅下拉列表中。 Azure 资源是使用 Azure 资源管理器创建的。

对于基于证书的服务端点,我得到以下响应:

HTTP/1.1 500 Internal Server Error
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.5
X-TFS-ProcessId: {guid}
Strict-Transport-Security: max-age=31536000; includeSubDomains
Access-Control-Allow-Origin: https://<accountName>.visualstudio.com
Access-Control-Max-Age: 3600
Access-Control-Allow-Methods: OPTIONS,GET,POST,PATCH,PUT,DELETE
Access-Control-Expose-Headers: ActivityId,X-TFS-Session,X-MS-ContinuationToken
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: authorization
Set-Cookie: Tfs-SessionId={guid}; path=/; secure
Set-Cookie: Tfs-SessionActive=2015-12-04T10:14:11; path=/; secure
X-VSS-UserData: {guid}:{userName}
ActivityId: {guid}
X-TFS-Session: {guid}
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
P3P: CP="CAO DSP COR ADMa DEV CONo TELo CUR PSA PSD TAI IVDo OUR SAMi BUS DEM NAV STA UNI COM INT PHY ONL FIN PUR LOC CNT"
X-Content-Type-Options: nosniff
Date: Fri, 04 Dec 2015 10:14:11 GMT
Content-Length: 262

{"$id":"1","innerException":null,"message":"The remote server returned an error: (403) Forbidden.","typeName":"System.Net.WebException, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089","typeKey":"WebException","errorCode":0,"eventId":0}

控制台日志:

POST https://{accountName}.visualstudio.com/DefaultCollection/_apis/distributedtask/endpoint 500 (Internal Server Error)
TFS.WebApi.Exception: The remote server returned an error: (403) Forbidden.
    at k (https://{accountName}.visualstudio.com/_static/tfs/20151124T220927/_scripts/TFS/min/corejs?v=orNy3-42L65GzhafvD4v3Rya12botjCuxnjQZ8VrhzI1:40:375)
    at https://{accountName}.visualstudio.com/_static/tfs/20151124T220927/_scripts/TFS/min/corejs?v=orNy3-42L65GzhafvD4v3Rya12botjCuxnjQZ8VrhzI1:40:2955
    at d (https://{accountName}.visualstudio.com/_static/tfs/20151124T220927/_scripts/TFS/min/corejs?v=orNy3-42L65GzhafvD4v3Rya12botjCuxnjQZ8VrhzI1:40:635)
    at https://{accountName}.visualstudio.com/_static/tfs/20151124T220927/_scripts/TFS/min/corejs?v=orNy3-42L65GzhafvD4v3Rya12botjCuxnjQZ8VrhzI1:40:2888
    at l (https://{accountName}.visualstudio.com/_static/tfs/20151124T220927/_scripts/TFS/min/q.js:27:8122)
    at https://{accountName}.visualstudio.com/_static/tfs/20151124T220927/_scripts/TFS/min/q.js:27:8348
    at t.when (https://{accountName}.visualstudio.com/_static/tfs/20151124T220927/_scripts/TFS/min/q.js:27:3780)
    at t.u.promiseDispatch (https://{accountName}.visualstudio.com/_static/tfs/20151124T220927/_scripts/TFS/min/q.js:27:2824)
    at https://{accountName}.visualstudio.com/_static/tfs/20151124T220927/_scripts/TFS/min/q.js:27:1649
    at MessagePort.t (https://{accountName}.visualstudio.com/_static/tfs/20151124T220927/_scripts/TFS/min/q.js:27:5773)

对于基于凭据的服务端点,我得到以下响应:

HTTP/1.1 500 Internal Server Error
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.5
X-TFS-ProcessId: {guid}
Strict-Transport-Security: max-age=31536000; includeSubDomains
Access-Control-Allow-Origin: https://{accountName}.visualstudio.com
Access-Control-Max-Age: 3600
Access-Control-Allow-Methods: OPTIONS,GET,POST,PATCH,PUT,DELETE
Access-Control-Expose-Headers: ActivityId,X-TFS-Session,X-MS-ContinuationToken
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: authorization
Set-Cookie: Tfs-SessionId={guid}; path=/; secure
Set-Cookie: Tfs-SessionActive=2015-12-04T10:21:01; path=/; secure
X-VSS-UserData: {guid}:{userName}
ActivityId: {guid}
X-TFS-Session: {guid}
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
P3P: CP="CAO DSP COR ADMa DEV CONo TELo CUR PSA PSD TAI IVDo OUR SAMi BUS DEM NAV STA UNI COM INT PHY ONL FIN PUR LOC CNT"
X-Content-Type-Options: nosniff
Date: Fri, 04 Dec 2015 10:21:02 GMT
Content-Length: 327

{"$id":"1","innerException":null,"message":"TF400898: An Internal Error Occurred. Activity Id: {guid}.","typeName":"System.Net.Http.HttpRequestException, System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a","typeKey":"HttpRequestException","errorCode":0,"eventId":0}

控制台日志:

POST https://{accountName}.visualstudio.com/DefaultCollection/_apis/distributedtask/endpoint 500 (Internal Server Error)
TFS.WebApi.Exception: TF400898: An Internal Error Occurred. Activity Id: {guid}.
    at k (https://{accountName}.visualstudio.com/_static/tfs/20151124T220927/_scripts/TFS/min/corejs?v=orNy3-42L65GzhafvD4v3Rya12botjCuxnjQZ8VrhzI1:40:375)
    at https://{accountName}.visualstudio.com/_static/tfs/20151124T220927/_scripts/TFS/min/corejs?v=orNy3-42L65GzhafvD4v3Rya12botjCuxnjQZ8VrhzI1:40:2955
    at d (https://{accountName}.visualstudio.com/_static/tfs/20151124T220927/_scripts/TFS/min/corejs?v=orNy3-42L65GzhafvD4v3Rya12botjCuxnjQZ8VrhzI1:40:635)
    at https://{accountName}.visualstudio.com/_static/tfs/20151124T220927/_scripts/TFS/min/corejs?v=orNy3-42L65GzhafvD4v3Rya12botjCuxnjQZ8VrhzI1:40:2888
    at l (https://{accountName}.visualstudio.com/_static/tfs/20151124T220927/_scripts/TFS/min/q.js:27:8122)
    at https://{accountName}.visualstudio.com/_static/tfs/20151124T220927/_scripts/TFS/min/q.js:27:8348
    at t.when (https://{accountName}.visualstudio.com/_static/tfs/20151124T220927/_scripts/TFS/min/q.js:27:3780)
    at t.u.promiseDispatch (https://{accountName}.visualstudio.com/_static/tfs/20151124T220927/_scripts/TFS/min/q.js:27:2824)
    at https://{accountName}.visualstudio.com/_static/tfs/20151124T220927/_scripts/TFS/min/q.js:27:1649
    at MessagePort.t (https://{accountName}.visualstudio.com/_static/tfs/20151124T220927/_scripts/TFS/min/q.js:27:5773)

非常感谢任何指导或帮助!

【问题讨论】:

  • 为了缩小问题范围,您能否检查一下 Build 中的部署是否可以成功完成?
  • Eddie,我可以确认我可以从构建过程中部署工件,因为我现在在我们的 Octopus 服务器中实现了发布部分,并且从那里部署好了。
  • 我的意思是您能否在构建过程中从 VSO 托管的构建代理成功部署到 Azure 云服务。您可以单击“以zip格式下载所有日志”以检查其中是否包含任何其他日志?
  • 嗨,Eddie,我还没有时间尝试这个,因为我们现在使用 Octopus 作为解决方法。一旦我们来到我们迁移到 VSTS 版本的部分,我会立即更新这个线程。

标签: tfsbuild azure-cloud-services ms-release-management azure-devops


【解决方案1】:

Azure 云服务任务仅适用于基于证书或凭据的 Azure 服务端点。这就是为什么任务只显示这两种类型的原因。

您可以在 Azure 中创建两种类型的存储帐户 - ARM 和 Classic。可能是您创建了 ARM 存储帐户。你可以尝试创建一个经典的并在任务输入中提供它吗?

任务中的下拉菜单存在问题。我们将在接下来的几周内解决这些问题。理想情况下,该任务应仅在下拉列表中显示经典存储帐户。

【讨论】:

  • 你好 Vijay,这也是我尝试过的。我创建了一个经典的存储帐户,但我仍然遇到同样的错误。可以肯定的是:由于我不能使用下拉菜单,我不确定我是否只需要指定存储帐户名称,或者是否应该使用“.core.windows.net?指定 uri?现在我只指定名称存储帐户。