예제 #1
0
        public override VssCredentials GetVssCredentials(IHostContext context)
        {
            var clientId         = this.CredentialData.Data.GetValueOrDefault("clientId", null);
            var authorizationUrl = this.CredentialData.Data.GetValueOrDefault("authorizationUrl", null);

            // We expect the key to be in the machine store at this point. Configuration should have set all of
            // this up correctly so we can use the key to generate access tokens.
            var keyManager         = context.GetService <IRSAKeyManager>();
            var signingCredentials = VssSigningCredentials.Create(() => keyManager.GetKey());
            var clientCredential   = new VssOAuthJwtBearerClientCredential(clientId, authorizationUrl, signingCredentials);
            var agentCredential    = new VssOAuthCredential(new Uri(authorizationUrl, 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.
            return(new VssCredentials(null, agentCredential, CredentialPromptType.DoNotPrompt));
        }
예제 #2
0
        public override VssCredentials GetVssCredentials(IHostContext context)
        {
            var clientId         = this.CredentialData.Data.GetValueOrDefault("clientId", null);
            var authorizationUrl = this.CredentialData.Data.GetValueOrDefault("authorizationUrl", null);

            ArgUtil.NotNullOrEmpty(clientId, nameof(clientId));
            ArgUtil.NotNullOrEmpty(authorizationUrl, nameof(authorizationUrl));

            // For TFS, we need make sure the Schema/Host/Port component of the authorization url also match configuration url.
            // We can't do this for VSTS, since its SPS/TFS urls are different.
            var configStore = context.GetService <IConfigurationStore>();

            if (configStore.IsConfigured())
            {
                UriBuilder configServerUrl         = new UriBuilder(configStore.GetSettings().ServerUrl);
                UriBuilder authorizationUrlBuilder = new UriBuilder(authorizationUrl);
                if (!UrlUtil.IsHosted(configServerUrl.Uri.AbsoluteUri) &&
                    Uri.Compare(configServerUrl.Uri, authorizationUrlBuilder.Uri, UriComponents.SchemeAndServer, UriFormat.Unescaped, StringComparison.OrdinalIgnoreCase) != 0)
                {
                    authorizationUrlBuilder.Scheme = configServerUrl.Scheme;
                    authorizationUrlBuilder.Host   = configServerUrl.Host;
                    authorizationUrlBuilder.Port   = configServerUrl.Port;

                    var trace = context.GetTrace(nameof(OAuthCredential));
                    trace.Info($"Replace authorization url's scheme://host:port component with agent configure url's scheme://host:port: '{authorizationUrlBuilder.Uri.AbsoluteUri}'.");

                    authorizationUrl = authorizationUrlBuilder.Uri.AbsoluteUri;
                }
            }

            // We expect the key to be in the machine store at this point. Configuration should have set all of
            // this up correctly so we can use the key to generate access tokens.
            var keyManager         = context.GetService <IRSAKeyManager>();
            var signingCredentials = VssSigningCredentials.Create(() => keyManager.GetKey());
            var clientCredential   = new VssOAuthJwtBearerClientCredential(clientId, authorizationUrl, signingCredentials);
            var agentCredential    = new VssOAuthCredential(new Uri(authorizationUrl, 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.
            return(new VssCredentials(null, agentCredential, CredentialPromptType.DoNotPrompt));
        }
예제 #3
0
        public override VssCredentials GetVssCredentials(IHostContext context)
        {
            var clientId         = this.CredentialData.Data.GetValueOrDefault("clientId", null);
            var authorizationUrl = this.CredentialData.Data.GetValueOrDefault("authorizationUrl", null);

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

            ArgUtil.NotNullOrEmpty(clientId, nameof(clientId));
            ArgUtil.NotNullOrEmpty(authorizationUrl, nameof(authorizationUrl));

            // We expect the key to be in the machine store at this point. Configuration should have set all of
            // this up correctly so we can use the key to generate access tokens.
            var keyManager         = context.GetService <IRSAKeyManager>();
            var signingCredentials = VssSigningCredentials.Create(() => keyManager.GetKey(), StringUtil.ConvertToBoolean(CredentialData.Data.GetValueOrDefault("requireFipsCryptography"), false));
            var clientCredential   = new VssOAuthJwtBearerClientCredential(clientId, authorizationUrl, signingCredentials);
            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.
            return(new VssCredentials(agentCredential, CredentialPromptType.DoNotPrompt));
        }
예제 #4
0
        private async Task <VssCredentials> GetNewOAuthAuthorizationSetting(CancellationToken token)
        {
            Trace.Info("Start checking oauth authorization url update.");
            while (true)
            {
                var backoff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromMinutes(30), TimeSpan.FromMinutes(45));
                await HostContext.Delay(backoff, token);

                try
                {
                    var migratedAuthorizationUrl = await _runnerServer.GetRunnerAuthUrlAsync(_settings.PoolId, _settings.AgentId);

                    if (!string.IsNullOrEmpty(migratedAuthorizationUrl))
                    {
                        var credData = _configStore.GetCredentials();
                        var clientId = credData.Data.GetValueOrDefault("clientId", null);
                        var currentAuthorizationUrl = credData.Data.GetValueOrDefault("authorizationUrl", null);
                        Trace.Info($"Current authorization url: {currentAuthorizationUrl}, new authorization url: {migratedAuthorizationUrl}");

                        if (string.Equals(currentAuthorizationUrl, migratedAuthorizationUrl, StringComparison.OrdinalIgnoreCase))
                        {
                            // We don't need to update credentials.
                            Trace.Info("No needs to update authorization url");
                            await Task.Delay(TimeSpan.FromMilliseconds(-1), token);
                        }

                        var keyManager         = HostContext.GetService <IRSAKeyManager>();
                        var signingCredentials = VssSigningCredentials.Create(() => keyManager.GetKey());

                        var migratedClientCredential = new VssOAuthJwtBearerClientCredential(clientId, migratedAuthorizationUrl, signingCredentials);
                        var migratedRunnerCredential = new VssOAuthCredential(new Uri(migratedAuthorizationUrl, UriKind.Absolute), VssOAuthGrant.ClientCredentials, migratedClientCredential);

                        Trace.Info("Try connect service with Token Service OAuth endpoint.");
                        var runnerServer = HostContext.CreateService <IRunnerServer>();
                        await runnerServer.ConnectAsync(new Uri(_settings.ServerUrl), migratedRunnerCredential);

                        await runnerServer.GetAgentPoolsAsync();

                        Trace.Info($"Successfully connected service with new authorization url.");

                        var migratedCredData = new CredentialData
                        {
                            Scheme = Constants.Configuration.OAuth,
                            Data   =
                            {
                                { "clientId",         clientId                 },
                                { "authorizationUrl", migratedAuthorizationUrl },
                                { "oauthEndpointUrl", migratedAuthorizationUrl },
                            },
                        };

                        _configStore.SaveMigratedCredential(migratedCredData);
                        return(migratedRunnerCredential);
                    }
                    else
                    {
                        Trace.Verbose("No authorization url updates");
                    }
                }
                catch (Exception ex)
                {
                    Trace.Error("Fail to get/test new authorization url.");
                    Trace.Error(ex);

                    try
                    {
                        await _runnerServer.ReportRunnerAuthUrlErrorAsync(_settings.PoolId, _settings.AgentId, ex.ToString());
                    }
                    catch (Exception e)
                    {
                        // best effort
                        Trace.Error("Fail to report the migration error");
                        Trace.Error(e);
                    }
                }
            }
        }