예제 #1
0
        private async ValueTask <AccessToken> GetTokenImplAsync(TokenRequestContext requestContext, bool async, CancellationToken cancellationToken)
        {
            using CredentialDiagnosticScope scope = _pipeline.StartGetTokenScope("VisualStudioCredential.GetToken", requestContext);

            try
            {
                var tokenProviderPath = GetTokenProviderPath();
                var tokenProviders    = GetTokenProviders(tokenProviderPath);

                var resource          = ScopeUtilities.ScopesToResource(requestContext.Scopes);
                var processStartInfos = GetProcessStartInfos(tokenProviders, resource, cancellationToken);

                if (processStartInfos.Count == 0)
                {
                    throw new CredentialUnavailableException("No installed instance of Visual Studio was found");
                }

                return(await RunProcessesAsync(processStartInfos, async, cancellationToken).ConfigureAwait(false));
            }
            catch (OperationCanceledException e)
            {
                scope.Failed(e);
                throw;
            }
            catch (Exception e)
            {
                throw scope.FailAndWrap(e);
            }
        }
        protected override Request CreateRequest(string[] scopes)
        {
            // covert the scopes to a resource string
            string resource = ScopeUtilities.ScopesToResource(scopes);

            Request request = Pipeline.HttpPipeline.CreateRequest();

            request.Method = RequestMethod.Get;
            request.Headers.Add("Metadata", "true");
            request.Uri.Reset(_imdsEndpoint);
            request.Uri.AppendQuery("api-version", ImdsApiVersion);

            request.Uri.AppendQuery("resource", resource);

            if (!string.IsNullOrEmpty(_clientId))
            {
                request.Uri.AppendQuery(Constants.ManagedIdentityClientId, _clientId);
            }
            if (!string.IsNullOrEmpty(_resourceId))
            {
                request.Uri.AppendQuery(Constants.ManagedIdentityResourceId, _resourceId);
            }

            return(request);
        }
예제 #3
0
        protected virtual async ValueTask <AccessToken> RequestCliAccessTokenAsync(bool async, string[] scopes, CancellationToken cancellationToken)
        {
            string resource = ScopeUtilities.ScopesToResource(scopes);

            ScopeUtilities.ValidateScope(resource);

            (string output, int exitCode) = await GetAzureCliAccesToken(async, resource, cancellationToken).ConfigureAwait(false);

            if (exitCode != 0)
            {
                bool isLoginError = output.IndexOf("az login", StringComparison.OrdinalIgnoreCase) != -1 || output.IndexOf("az account set", StringComparison.OrdinalIgnoreCase) != -1;

                bool isWinError = output.StartsWith(WinAzureCLIError, StringComparison.CurrentCultureIgnoreCase);

                bool isOtherOsError = AzNotFoundPattern.IsMatch(output);

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

                throw new AuthenticationFailedException($"{AzureCliFailedError} {output}");
            }

            return(DeserializeOutput(output));
        }
예제 #4
0
        private Request CreateManagedIdentityAuthRequest(string[] scopes, string clientId = null)
        {
            // covert the scopes to a resource string
            string resource = ScopeUtilities.ScopesToResource(scopes);

            Request request = _pipeline.CreateRequest();

            request.Method = HttpPipelineMethod.Get;

            request.Headers.Add("Metadata", "true");

            // TODO: support MSI for hosted services
            request.UriBuilder.Uri = ImdsEndptoint;

            request.UriBuilder.AppendQuery("api-version", MsiApiVersion);

            request.UriBuilder.AppendQuery("resource", Uri.EscapeDataString(resource));

            if (!string.IsNullOrEmpty(clientId))
            {
                request.UriBuilder.AppendQuery("client_id", Uri.EscapeDataString(clientId));
            }

            return(request);
        }
예제 #5
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));
        }
예제 #6
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));
        }
        protected override Request CreateRequest(string[] scopes)
        {
            // covert the scopes to a resource string
            string resource = ScopeUtilities.ScopesToResource(scopes);
            Request request = Pipeline.HttpPipeline.CreateRequest();
            request.Method = RequestMethod.Post;
            request.Headers.Add(HttpHeader.Common.FormUrlEncodedContentType);
            request.Uri.Reset(_endpoint);
            request.Headers.Add("Metadata", "true");

            var bodyStr = $"resource={Uri.EscapeDataString(resource)}";
            ReadOnlyMemory<byte> content = Encoding.UTF8.GetBytes(bodyStr).AsMemory();

            request.Content = RequestContent.Create(content);
            return request;
        }
예제 #8
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));
        }