Skip to content

Commit

Permalink
Switch to use token service instead of SPS for exchanging oauth token. (
Browse files Browse the repository at this point in the history
actions#325)

* Gracefully switch the runner to use Token Service instead of SPS.

* PR feedback.

* feedback2

* report error.
  • Loading branch information
TingluoHuang authored Mar 5, 2020
1 parent 0cba425 commit 6bec1e3
Show file tree
Hide file tree
Showing 13 changed files with 1,915 additions and 282 deletions.
35 changes: 34 additions & 1 deletion src/Runner.Common/ConfigurationStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,10 @@ public interface IConfigurationStore : IRunnerService
bool IsServiceConfigured();
bool HasCredentials();
CredentialData GetCredentials();
CredentialData GetMigratedCredentials();
RunnerSettings GetSettings();
void SaveCredential(CredentialData credential);
void SaveMigratedCredential(CredentialData credential);
void SaveSettings(RunnerSettings settings);
void DeleteCredential();
void DeleteSettings();
Expand All @@ -90,9 +92,11 @@ public sealed class ConfigurationStore : RunnerService, IConfigurationStore
private string _binPath;
private string _configFilePath;
private string _credFilePath;
private string _migratedCredFilePath;
private string _serviceConfigFilePath;

private CredentialData _creds;
private CredentialData _migratedCreds;
private RunnerSettings _settings;

public override void Initialize(IHostContext hostContext)
Expand All @@ -114,6 +118,9 @@ public override void Initialize(IHostContext hostContext)
_credFilePath = hostContext.GetConfigFile(WellKnownConfigFile.Credentials);
Trace.Info("CredFilePath: {0}", _credFilePath);

_migratedCredFilePath = hostContext.GetConfigFile(WellKnownConfigFile.MigratedCredentials);
Trace.Info("MigratedCredFilePath: {0}", _migratedCredFilePath);

_serviceConfigFilePath = hostContext.GetConfigFile(WellKnownConfigFile.Service);
Trace.Info("ServiceConfigFilePath: {0}", _serviceConfigFilePath);
}
Expand All @@ -123,7 +130,7 @@ public override void Initialize(IHostContext hostContext)
public bool HasCredentials()
{
Trace.Info("HasCredentials()");
bool credsStored = (new FileInfo(_credFilePath)).Exists;
bool credsStored = (new FileInfo(_credFilePath)).Exists || (new FileInfo(_migratedCredFilePath)).Exists;
Trace.Info("stored {0}", credsStored);
return credsStored;
}
Expand Down Expand Up @@ -154,6 +161,16 @@ public CredentialData GetCredentials()
return _creds;
}

public CredentialData GetMigratedCredentials()
{
if (_migratedCreds == null && File.Exists(_migratedCredFilePath))
{
_migratedCreds = IOUtil.LoadObject<CredentialData>(_migratedCredFilePath);
}

return _migratedCreds;
}

public RunnerSettings GetSettings()
{
if (_settings == null)
Expand Down Expand Up @@ -188,6 +205,21 @@ public void SaveCredential(CredentialData credential)
File.SetAttributes(_credFilePath, File.GetAttributes(_credFilePath) | FileAttributes.Hidden);
}

public void SaveMigratedCredential(CredentialData credential)
{
Trace.Info("Saving {0} migrated credential @ {1}", credential.Scheme, _migratedCredFilePath);
if (File.Exists(_migratedCredFilePath))
{
// Delete existing credential file first, since the file is hidden and not able to overwrite.
Trace.Info("Delete exist runner migrated credential file.");
IOUtil.DeleteFile(_migratedCredFilePath);
}

IOUtil.SaveObject(credential, _migratedCredFilePath);
Trace.Info("Migrated Credentials Saved.");
File.SetAttributes(_migratedCredFilePath, File.GetAttributes(_migratedCredFilePath) | FileAttributes.Hidden);
}

public void SaveSettings(RunnerSettings settings)
{
Trace.Info("Saving runner settings.");
Expand All @@ -206,6 +238,7 @@ public void SaveSettings(RunnerSettings settings)
public void DeleteCredential()
{
IOUtil.Delete(_credFilePath, default(CancellationToken));
IOUtil.Delete(_migratedCredFilePath, default(CancellationToken));
}

public void DeleteSettings()
Expand Down
1 change: 1 addition & 0 deletions src/Runner.Common/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public enum WellKnownConfigFile
{
Runner,
Credentials,
MigratedCredentials,
RSACredentials,
Service,
CredentialStore,
Expand Down
6 changes: 6 additions & 0 deletions src/Runner.Common/HostContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,12 @@ public string GetConfigFile(WellKnownConfigFile configFile)
".credentials");
break;

case WellKnownConfigFile.MigratedCredentials:
path = Path.Combine(
GetDirectory(WellKnownDirectory.Root),
".credentials_migrated");
break;

case WellKnownConfigFile.RSACredentials:
path = Path.Combine(
GetDirectory(WellKnownDirectory.Root),
Expand Down
19 changes: 19 additions & 0 deletions src/Runner.Common/RunnerServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ public interface IRunnerServer : IRunnerService

// agent update
Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, int agentId, string currentState);

// runner authorization url
Task<string> GetRunnerAuthUrlAsync(int runnerPoolId, int runnerId);
Task ReportRunnerAuthUrlErrorAsync(int runnerPoolId, int runnerId, string error);
}

public sealed class RunnerServer : RunnerService, IRunnerServer
Expand Down Expand Up @@ -334,5 +338,20 @@ public Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, int agentId,
CheckConnection(RunnerConnectionType.Generic);
return _genericTaskAgentClient.UpdateAgentUpdateStateAsync(agentPoolId, agentId, currentState);
}

//-----------------------------------------------------------------
// Runner Auth Url
//-----------------------------------------------------------------
public Task<string> GetRunnerAuthUrlAsync(int runnerPoolId, int runnerId)
{
CheckConnection(RunnerConnectionType.MessageQueue);
return _messageTaskAgentClient.GetAgentAuthUrlAsync(runnerPoolId, runnerId);
}

public Task ReportRunnerAuthUrlErrorAsync(int runnerPoolId, int runnerId, string error)
{
CheckConnection(RunnerConnectionType.MessageQueue);
return _messageTaskAgentClient.ReportAgentAuthUrlMigrationErrorAsync(runnerPoolId, runnerId, error);
}
}
}
14 changes: 12 additions & 2 deletions src/Runner.Listener/Configuration/CredentialManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace GitHub.Runner.Listener.Configuration
public interface ICredentialManager : IRunnerService
{
ICredentialProvider GetCredentialProvider(string credType);
VssCredentials LoadCredentials();
VssCredentials LoadCredentials(bool preferMigrated = true);
}

public class CredentialManager : RunnerService, ICredentialManager
Expand All @@ -40,7 +40,7 @@ public ICredentialProvider GetCredentialProvider(string credType)
return creds;
}

public VssCredentials LoadCredentials()
public VssCredentials LoadCredentials(bool preferMigrated = true)
{
IConfigurationStore store = HostContext.GetService<IConfigurationStore>();

Expand All @@ -50,6 +50,16 @@ public VssCredentials LoadCredentials()
}

CredentialData credData = store.GetCredentials();

if (preferMigrated)
{
var migratedCred = store.GetMigratedCredentials();
if (migratedCred != null)
{
credData = migratedCred;
}
}

ICredentialProvider credProv = GetCredentialProvider(credData.Scheme);
credProv.CredentialData = credData;

Expand Down
5 changes: 2 additions & 3 deletions src/Runner.Listener/Configuration/OAuthCredential.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using GitHub.Runner.Common;
using GitHub.Runner.Common.Util;
using GitHub.Runner.Sdk;
using GitHub.Services.Common;
using GitHub.Services.OAuth;
Expand Down Expand Up @@ -29,7 +28,7 @@ public override VssCredentials GetVssCredentials(IHostContext context)
var authorizationUrl = this.CredentialData.Data.GetValueOrDefault("authorizationUrl", null);

// For back compat with .credential file that doesn't has 'oauthEndpointUrl' section
var oathEndpointUrl = this.CredentialData.Data.GetValueOrDefault("oauthEndpointUrl", authorizationUrl);
var oauthEndpointUrl = this.CredentialData.Data.GetValueOrDefault("oauthEndpointUrl", authorizationUrl);

ArgUtil.NotNullOrEmpty(clientId, nameof(clientId));
ArgUtil.NotNullOrEmpty(authorizationUrl, nameof(authorizationUrl));
Expand All @@ -39,7 +38,7 @@ public override VssCredentials GetVssCredentials(IHostContext context)
var keyManager = context.GetService<IRSAKeyManager>();
var signingCredentials = VssSigningCredentials.Create(() => keyManager.GetKey());
var clientCredential = new VssOAuthJwtBearerClientCredential(clientId, authorizationUrl, signingCredentials);
var agentCredential = new VssOAuthCredential(new Uri(oathEndpointUrl, UriKind.Absolute), VssOAuthGrant.ClientCredentials, clientCredential);
var agentCredential = new VssOAuthCredential(new Uri(oauthEndpointUrl, UriKind.Absolute), VssOAuthGrant.ClientCredentials, clientCredential);

// Construct a credentials cache with a single OAuth credential for communication. The windows credential
// is explicitly set to null to ensure we never do that negotiation.
Expand Down
Loading

0 comments on commit 6bec1e3

Please sign in to comment.