support authenticated package download (#920)

This commit is contained in:
eric sciple
2021-01-23 14:19:59 -05:00
committed by GitHub
parent 5972bd0060
commit 9efcec38cc
4 changed files with 48 additions and 13 deletions

View File

@@ -45,8 +45,8 @@ namespace GitHub.Runner.Common
Task<TaskAgentJobRequest> FinishAgentRequestAsync(int poolId, long requestId, Guid lockToken, DateTime finishTime, TaskResult result, CancellationToken cancellationToken); Task<TaskAgentJobRequest> FinishAgentRequestAsync(int poolId, long requestId, Guid lockToken, DateTime finishTime, TaskResult result, CancellationToken cancellationToken);
// agent package // agent package
Task<List<PackageMetadata>> GetPackagesAsync(string packageType, string platform, int top, CancellationToken cancellationToken); Task<List<PackageMetadata>> GetPackagesAsync(string packageType, string platform, int top, bool includeToken, CancellationToken cancellationToken);
Task<PackageMetadata> GetPackageAsync(string packageType, string platform, string version, CancellationToken cancellationToken); Task<PackageMetadata> GetPackageAsync(string packageType, string platform, string version, bool includeToken, CancellationToken cancellationToken);
// agent update // agent update
Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, int agentId, string currentState); Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, int agentId, string currentState);
@@ -317,16 +317,16 @@ namespace GitHub.Runner.Common
//----------------------------------------------------------------- //-----------------------------------------------------------------
// Agent Package // Agent Package
//----------------------------------------------------------------- //-----------------------------------------------------------------
public Task<List<PackageMetadata>> GetPackagesAsync(string packageType, string platform, int top, CancellationToken cancellationToken) public Task<List<PackageMetadata>> GetPackagesAsync(string packageType, string platform, int top, bool includeToken, CancellationToken cancellationToken)
{ {
CheckConnection(RunnerConnectionType.Generic); CheckConnection(RunnerConnectionType.Generic);
return _genericTaskAgentClient.GetPackagesAsync(packageType, platform, top, cancellationToken: cancellationToken); return _genericTaskAgentClient.GetPackagesAsync(packageType, platform, top, includeToken, cancellationToken: cancellationToken);
} }
public Task<PackageMetadata> GetPackageAsync(string packageType, string platform, string version, CancellationToken cancellationToken) public Task<PackageMetadata> GetPackageAsync(string packageType, string platform, string version, bool includeToken, CancellationToken cancellationToken)
{ {
CheckConnection(RunnerConnectionType.Generic); CheckConnection(RunnerConnectionType.Generic);
return _genericTaskAgentClient.GetPackageAsync(packageType, platform, version, cancellationToken: cancellationToken); return _genericTaskAgentClient.GetPackageAsync(packageType, platform, version, includeToken, cancellationToken: cancellationToken);
} }
public Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, int agentId, string currentState) public Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, int agentId, string currentState)

View File

@@ -110,7 +110,7 @@ namespace GitHub.Runner.Listener
// old server won't send target version as part of update message. // old server won't send target version as part of update message.
if (string.IsNullOrEmpty(targetVersion)) if (string.IsNullOrEmpty(targetVersion))
{ {
var packages = await _runnerServer.GetPackagesAsync(_packageType, _platform, 1, token); var packages = await _runnerServer.GetPackagesAsync(_packageType, _platform, 1, true, token);
if (packages == null || packages.Count == 0) if (packages == null || packages.Count == 0)
{ {
Trace.Info($"There is no package for {_packageType} and {_platform}."); Trace.Info($"There is no package for {_packageType} and {_platform}.");
@@ -121,7 +121,7 @@ namespace GitHub.Runner.Listener
} }
else else
{ {
_targetPackage = await _runnerServer.GetPackageAsync(_packageType, _platform, targetVersion, token); _targetPackage = await _runnerServer.GetPackageAsync(_packageType, _platform, targetVersion, true, token);
if (_targetPackage == null) if (_targetPackage == null)
{ {
Trace.Info($"There is no package for {_packageType} and {_platform} with version {targetVersion}."); Trace.Info($"There is no package for {_packageType} and {_platform} with version {targetVersion}.");
@@ -211,12 +211,22 @@ namespace GitHub.Runner.Listener
//open zip stream in async mode //open zip stream in async mode
using (HttpClient httpClient = new HttpClient(HostContext.CreateHttpClientHandler())) using (HttpClient httpClient = new HttpClient(HostContext.CreateHttpClientHandler()))
using (FileStream fs = new FileStream(archiveFile, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true))
using (Stream result = await httpClient.GetStreamAsync(_targetPackage.DownloadUrl))
{ {
//81920 is the default used by System.IO.Stream.CopyTo and is under the large object heap threshold (85k). if (!string.IsNullOrEmpty(_targetPackage.Token))
await result.CopyToAsync(fs, 81920, downloadCts.Token); {
await fs.FlushAsync(downloadCts.Token); Trace.Info($"Adding authorization token ({_targetPackage.Token.Length} chars)");
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", _targetPackage.Token);
}
Trace.Info($"Downloading {_targetPackage.DownloadUrl}");
using (FileStream fs = new FileStream(archiveFile, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true))
using (Stream result = await httpClient.GetStreamAsync(_targetPackage.DownloadUrl))
{
//81920 is the default used by System.IO.Stream.CopyTo and is under the large object heap threshold (85k).
await result.CopyToAsync(fs, 81920, downloadCts.Token);
await fs.FlushAsync(downloadCts.Token);
}
} }
Trace.Info($"Download runner: finished download"); Trace.Info($"Download runner: finished download");

View File

@@ -587,6 +587,7 @@ namespace GitHub.DistributedTask.WebApi
/// <param name="packageType"></param> /// <param name="packageType"></param>
/// <param name="platform"></param> /// <param name="platform"></param>
/// <param name="version"></param> /// <param name="version"></param>
/// <param name="includeToken"></param>
/// <param name="userState"></param> /// <param name="userState"></param>
/// <param name="cancellationToken">The cancellation token to cancel operation.</param> /// <param name="cancellationToken">The cancellation token to cancel operation.</param>
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
@@ -594,6 +595,7 @@ namespace GitHub.DistributedTask.WebApi
string packageType, string packageType,
string platform, string platform,
string version, string version,
bool? includeToken = null,
object userState = null, object userState = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
@@ -601,11 +603,18 @@ namespace GitHub.DistributedTask.WebApi
Guid locationId = new Guid("8ffcd551-079c-493a-9c02-54346299d144"); Guid locationId = new Guid("8ffcd551-079c-493a-9c02-54346299d144");
object routeValues = new { packageType = packageType, platform = platform, version = version }; object routeValues = new { packageType = packageType, platform = platform, version = version };
List<KeyValuePair<string, string>> queryParams = new List<KeyValuePair<string, string>>();
if (includeToken != null)
{
queryParams.Add("includeToken", includeToken.Value.ToString());
}
return SendAsync<PackageMetadata>( return SendAsync<PackageMetadata>(
httpMethod, httpMethod,
locationId, locationId,
routeValues: routeValues, routeValues: routeValues,
version: new ApiResourceVersion(5.1, 2), version: new ApiResourceVersion(5.1, 2),
queryParameters: queryParams,
userState: userState, userState: userState,
cancellationToken: cancellationToken); cancellationToken: cancellationToken);
} }
@@ -616,6 +625,7 @@ namespace GitHub.DistributedTask.WebApi
/// <param name="packageType"></param> /// <param name="packageType"></param>
/// <param name="platform"></param> /// <param name="platform"></param>
/// <param name="top"></param> /// <param name="top"></param>
/// <param name="includeToken"></param>
/// <param name="userState"></param> /// <param name="userState"></param>
/// <param name="cancellationToken">The cancellation token to cancel operation.</param> /// <param name="cancellationToken">The cancellation token to cancel operation.</param>
[EditorBrowsable(EditorBrowsableState.Never)] [EditorBrowsable(EditorBrowsableState.Never)]
@@ -623,6 +633,7 @@ namespace GitHub.DistributedTask.WebApi
string packageType, string packageType,
string platform = null, string platform = null,
int? top = null, int? top = null,
bool? includeToken = null,
object userState = null, object userState = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
@@ -635,6 +646,10 @@ namespace GitHub.DistributedTask.WebApi
{ {
queryParams.Add("$top", top.Value.ToString(CultureInfo.InvariantCulture)); queryParams.Add("$top", top.Value.ToString(CultureInfo.InvariantCulture));
} }
if (includeToken != null)
{
queryParams.Add("includeToken", includeToken.Value.ToString());
}
return SendAsync<List<PackageMetadata>>( return SendAsync<List<PackageMetadata>>(
httpMethod, httpMethod,

View File

@@ -59,6 +59,16 @@ namespace GitHub.DistributedTask.WebApi
set; set;
} }
/// <summary>
/// Auth token to download the package
/// </summary>
[DataMember]
public String Token
{
get;
set;
}
/// <summary> /// <summary>
/// MD5 hash as a base64 string /// MD5 hash as a base64 string
/// </summary> /// </summary>