Compare commits

...

1 Commits

Author SHA1 Message Date
TingluoHuang
25cd3d808c Revoke GITHUB_TOKEN at the end of the job. 2020-04-09 13:35:01 -04:00
4 changed files with 110 additions and 9 deletions

View File

@@ -0,0 +1,67 @@
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using GitHub.Services.Common;
namespace GitHub.Runner.Common
{
public class GitHubResult
{
public HttpStatusCode StatusCode { get; set; }
public String Message { get; set; }
public HttpResponseHeaders Headers { get; set; }
}
[ServiceLocator(Default = typeof(GitHubServer))]
public interface IGitHubServer : IRunnerService
{
Task<GitHubResult> RevokeInstallationToken(string GithubApiUrl, string AccessToken);
}
public class GitHubServer : RunnerService, IGitHubServer
{
public async Task<GitHubResult> RevokeInstallationToken(string GithubApiUrl, string AccessToken)
{
var result = new GitHubResult();
var requestUrl = new UriBuilder(GithubApiUrl);
requestUrl.Path = requestUrl.Path.TrimEnd('/') + "/installation/token";
using (var httpClientHandler = HostContext.CreateHttpClientHandler())
using (var httpClient = HttpClientFactory.Create(httpClientHandler, new VssHttpRetryMessageHandler(3)))
{
httpClient.DefaultRequestHeaders.UserAgent.Add(HostContext.UserAgent);
var base64EncodingToken = Convert.ToBase64String(Encoding.UTF8.GetBytes($"x-access-token:{AccessToken}"));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", base64EncodingToken);
var count = 1;
while (true)
{
try
{
using (HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Delete, requestUrl.Uri))
{
requestMessage.Headers.Add("Accept", "application/vnd.github.gambit-preview+json");
var response = await httpClient.SendAsync(requestMessage, CancellationToken.None);
result.StatusCode = response.StatusCode;
result.Headers = response.Headers;
result.Message = await response.Content.ReadAsStringAsync();
return result;
}
}
catch (Exception ex) when (count++ < 3)
{
Trace.Error("Fail to revoke GITHUB_TOKEN, will try again later");
Trace.Error(ex);
var backoff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(15));
await Task.Delay(backoff);
}
}
}
}
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Net;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
@@ -33,7 +34,7 @@ namespace GitHub.Runner.Worker
public interface IJobExtension : IRunnerService
{
Task<List<IStep>> InitializeJob(IExecutionContext jobContext, Pipelines.AgentJobRequestMessage message);
void FinalizeJob(IExecutionContext jobContext, Pipelines.AgentJobRequestMessage message, DateTime jobStartTimeUtc);
Task FinalizeJobAsync(IExecutionContext jobContext, Pipelines.AgentJobRequestMessage message, DateTime jobStartTimeUtc);
}
public sealed class JobExtension : RunnerService, IJobExtension
@@ -311,7 +312,7 @@ namespace GitHub.Runner.Worker
}
}
public void FinalizeJob(IExecutionContext jobContext, Pipelines.AgentJobRequestMessage message, DateTime jobStartTimeUtc)
public async Task FinalizeJobAsync(IExecutionContext jobContext, Pipelines.AgentJobRequestMessage message, DateTime jobStartTimeUtc)
{
Trace.Entering();
ArgUtil.NotNull(jobContext, nameof(jobContext));
@@ -325,6 +326,39 @@ namespace GitHub.Runner.Worker
context.Start();
context.Debug("Starting: Complete job");
// Revoke GITHUB_TOKEN
context.Debug("Revoking GITHUB_TOKEN");
var githubApiUrl = context.GetGitHubContext("api_url");
if (string.IsNullOrEmpty(githubApiUrl))
{
githubApiUrl = "https://api.github.com";
}
var githubToken = context.GetGitHubContext("token");
try
{
var githubServer = HostContext.GetService<IGitHubServer>();
var result = await githubServer.RevokeInstallationToken(githubApiUrl, githubToken);
if (result.StatusCode == HttpStatusCode.NoContent)
{
context.Debug("GITHUB_TOKEN revoked");
}
else if (result.StatusCode == HttpStatusCode.Unauthorized)
{
context.Debug("GITHUB_TOKEN already expired");
}
else
{
Trace.Error("Fail to revoke GITHUB_TOKEN");
Trace.Error(result.Message);
}
}
catch (Exception ex)
{
Trace.Error("Fail to revoke GITHUB_TOKEN");
Trace.Error(ex);
}
// Evaluate job outputs
if (message.JobOutputs != null && message.JobOutputs.Type != TokenType.Null)
{

View File

@@ -184,7 +184,7 @@ namespace GitHub.Runner.Worker
finally
{
Trace.Info("Finalize job.");
jobExtension.FinalizeJob(jobContext, message, jobStartTimeUtc);
await jobExtension.FinalizeJobAsync(jobContext, message, jobStartTimeUtc);
}
Trace.Info($"Job result after all job steps finish: {jobContext.Result ?? TaskResult.Succeeded}");

View File

@@ -207,7 +207,7 @@ namespace GitHub.Runner.Common.Tests.Worker
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public void UploadDiganosticLogIfEnvironmentVariableSet()
public async Task UploadDiganosticLogIfEnvironmentVariableSet()
{
using (TestHostContext hc = CreateTestContext())
{
@@ -220,7 +220,7 @@ namespace GitHub.Runner.Common.Tests.Worker
_jobEc.Initialize(hc);
_jobEc.InitializeJob(_message, _tokenSource.Token);
jobExtension.FinalizeJob(_jobEc, _message, DateTime.UtcNow);
await jobExtension.FinalizeJobAsync(_jobEc, _message, DateTime.UtcNow);
_diagnosticLogManager.Verify(x =>
x.UploadDiagnosticLogs(
@@ -235,7 +235,7 @@ namespace GitHub.Runner.Common.Tests.Worker
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public void DontUploadDiagnosticLogIfEnvironmentVariableFalse()
public async Task DontUploadDiagnosticLogIfEnvironmentVariableFalse()
{
using (TestHostContext hc = CreateTestContext())
{
@@ -248,7 +248,7 @@ namespace GitHub.Runner.Common.Tests.Worker
_jobEc.Initialize(hc);
_jobEc.InitializeJob(_message, _tokenSource.Token);
jobExtension.FinalizeJob(_jobEc, _message, DateTime.UtcNow);
await jobExtension.FinalizeJobAsync(_jobEc, _message, DateTime.UtcNow);
_diagnosticLogManager.Verify(x =>
x.UploadDiagnosticLogs(
@@ -263,14 +263,14 @@ namespace GitHub.Runner.Common.Tests.Worker
[Fact]
[Trait("Level", "L0")]
[Trait("Category", "Worker")]
public void DontUploadDiagnosticLogIfEnvironmentVariableMissing()
public async Task DontUploadDiagnosticLogIfEnvironmentVariableMissing()
{
using (TestHostContext hc = CreateTestContext())
{
var jobExtension = new JobExtension();
jobExtension.Initialize(hc);
jobExtension.FinalizeJob(_jobEc, _message, DateTime.UtcNow);
await jobExtension.FinalizeJobAsync(_jobEc, _message, DateTime.UtcNow);
_diagnosticLogManager.Verify(x =>
x.UploadDiagnosticLogs(