Esempio n. 1
0
        private async ValueTask <AccessToken> RequestCliAccessTokenAsync(bool async, TokenRequestContext context, CancellationToken cancellationToken)
        {
            string resource = ScopeUtilities.ScopesToResource(context.Scopes);
            string tenantId = TenantIdResolver.Resolve(_tenantId, context, _allowMultiTenantAuthentication);

            ScopeUtilities.ValidateScope(resource);

            GetFileNameAndArguments(resource, tenantId, out string fileName, out string argument);
            ProcessStartInfo processStartInfo = GetAzureCliProcessStartInfo(fileName, argument);

            using var processRunner = new ProcessRunner(_processService.Create(processStartInfo), TimeSpan.FromMilliseconds(CliProcessTimeoutMs), cancellationToken);

            string output;

            try
            {
                output = async ? await processRunner.RunAsync().ConfigureAwait(false) : processRunner.Run();
            }
            catch (OperationCanceledException) when(!cancellationToken.IsCancellationRequested)
            {
                throw new AuthenticationFailedException(AzureCliTimeoutError);
            }
            catch (InvalidOperationException exception)
            {
                bool isWinError = exception.Message.StartsWith(WinAzureCLIError, StringComparison.CurrentCultureIgnoreCase);

                bool isOtherOsError = AzNotFoundPattern.IsMatch(exception.Message);

                if (isWinError || isOtherOsError)
                {
                    throw new CredentialUnavailableException(AzureCLINotInstalled);
                }

                bool isLoginError = exception.Message.IndexOf("az login", StringComparison.OrdinalIgnoreCase) != -1 ||
                                    exception.Message.IndexOf("az account set", StringComparison.OrdinalIgnoreCase) != -1;

                if (isLoginError)
                {
                    throw new CredentialUnavailableException(AzNotLogIn);
                }

                bool isRefreshTokenFailedError = exception.Message.IndexOf(AzureCliFailedError, StringComparison.OrdinalIgnoreCase) != -1 &&
                                                 exception.Message.IndexOf(RefreshTokeExpired, StringComparison.OrdinalIgnoreCase) != -1 ||
                                                 exception.Message.IndexOf("CLIInternalError", StringComparison.OrdinalIgnoreCase) != -1;

                if (isRefreshTokenFailedError)
                {
                    throw new CredentialUnavailableException(InteractiveLoginRequired);
                }

                throw new AuthenticationFailedException($"{AzureCliFailedError} {exception.Message}");
            }

            return(DeserializeOutput(output));
        }
Esempio n. 2
0
        private async ValueTask <AccessToken> RequestAzurePowerShellAccessTokenAsync(bool async, TokenRequestContext context, CancellationToken cancellationToken)
        {
            string resource = ScopeUtilities.ScopesToResource(context.Scopes);

            ScopeUtilities.ValidateScope(resource);
            var tenantId = TenantIdResolver.Resolve(_tenantId, context, _allowMultiTenantAuthentication);

            GetFileNameAndArguments(resource, tenantId, out string fileName, out string argument);
            ProcessStartInfo processStartInfo = GetAzurePowerShellProcessStartInfo(fileName, argument);

            using var processRunner = new ProcessRunner(
                      _processService.Create(processStartInfo),
                      TimeSpan.FromMilliseconds(PowerShellProcessTimeoutMs),
                      _logPII,
                      cancellationToken);

            string output;

            try
            {
                output = async ? await processRunner.RunAsync().ConfigureAwait(false) : processRunner.Run();

                CheckForErrors(output);
            }
            catch (OperationCanceledException) when(!cancellationToken.IsCancellationRequested)
            {
                throw new AuthenticationFailedException(AzurePowerShellTimeoutError);
            }
            catch (InvalidOperationException exception)
            {
                bool noPowerShell = exception.Message.IndexOf("not found", StringComparison.OrdinalIgnoreCase) != -1 ||
                                    exception.Message.IndexOf("is not recognized", StringComparison.OrdinalIgnoreCase) != -1;

                if (noPowerShell)
                {
                    throw new CredentialUnavailableException(PowerShellNotInstalledError);
                }

                bool noLogin = exception.Message.IndexOf("Run Connect-AzAccount to login", StringComparison.OrdinalIgnoreCase) != -1;

                if (noLogin)
                {
                    throw new CredentialUnavailableException(AzurePowerShellNotLogInError);
                }

                throw new AuthenticationFailedException($"{AzurePowerShellFailedError} {exception.Message}");
            }
            return(DeserializeOutput(output));
        }
        private async Task <AccessToken> RunProcessesAsync(List <ProcessStartInfo> processStartInfos, bool async, CancellationToken cancellationToken)
        {
            var exceptions = new List <Exception>();

            foreach (ProcessStartInfo processStartInfo in processStartInfos)
            {
                string output = string.Empty;
                try
                {
                    var processRunner = new ProcessRunner(_processService.Create(processStartInfo), TimeSpan.FromSeconds(30), cancellationToken);
                    output = async
                        ? await processRunner.RunAsync().ConfigureAwait(false)
                        : processRunner.Run();

                    JsonElement    root        = JsonDocument.Parse(output).RootElement;
                    string         accessToken = root.GetProperty("access_token").GetString();
                    DateTimeOffset expiresOn   = root.GetProperty("expires_on").GetDateTimeOffset();
                    return(new AccessToken(accessToken, expiresOn));
                }
                catch (OperationCanceledException) when(!cancellationToken.IsCancellationRequested)
                {
                    exceptions.Add(new CredentialUnavailableException($"Process \"{processStartInfo.FileName}\" has failed to get access token in 30 seconds."));
                }
                catch (JsonException exception)
                {
                    exceptions.Add(new CredentialUnavailableException($"Process \"{processStartInfo.FileName}\" has non-json output: {output}.", exception));
                }
                catch (Exception exception)
                {
                    exceptions.Add(exception);
                }
            }

            switch (exceptions.Count)
            {
            case 0:
                throw new CredentialUnavailableException("No installed instance of Visual Studio was able to get credentials.");

            case 1:
                ExceptionDispatchInfo.Capture(exceptions[0]).Throw();
                return(default);

            default:
                throw new AggregateException(exceptions);
            }
        }
Esempio n. 4
0
        private async ValueTask <AccessToken> RequestAzurePowerShellAccessTokenAsync(bool async, TokenRequestContext context, CancellationToken cancellationToken)
        {
            string resource = ScopeUtilities.ScopesToResource(context.Scopes);

            ScopeUtilities.ValidateScope(resource);
            var tenantId = TenantIdResolver.Resolve(_tenantId, context);

            GetFileNameAndArguments(resource, tenantId, out string fileName, out string argument);
            ProcessStartInfo processStartInfo = GetAzurePowerShellProcessStartInfo(fileName, argument);

            using var processRunner = new ProcessRunner(
                      _processService.Create(processStartInfo),
                      TimeSpan.FromMilliseconds(PowerShellProcessTimeoutMs),
                      _logPII,
                      cancellationToken);

            string output;

            try
            {
                output = async ? await processRunner.RunAsync().ConfigureAwait(false) : processRunner.Run();

                CheckForErrors(output);
                ValidateResult(output);
            }
            catch (OperationCanceledException) when(!cancellationToken.IsCancellationRequested)
            {
                throw new AuthenticationFailedException(AzurePowerShellTimeoutError);
            }
            catch (InvalidOperationException exception)
            {
                CheckForErrors(exception.Message);
                throw new AuthenticationFailedException($"{AzurePowerShellFailedError} {exception.Message}");
            }
            return(DeserializeOutput(output));
        }