SetCredentials() public method

public SetCredentials ( Credential credentials ) : void
credentials Microsoft.Alm.Authentication.Credential
return void
Ejemplo n.º 1
0
        public static Credential QueryCredentials(Program program, OperationArguments operationArguments)
        {
            if (program is null)
            {
                throw new ArgumentNullException(nameof(program));
            }
            if (operationArguments is null)
            {
                throw new ArgumentNullException(nameof(operationArguments));
            }
            if (operationArguments.TargetUri is null)
            {
                var innerException = new NullReferenceException($"{operationArguments.TargetUri} cannot be null.");
                throw new ArgumentException(innerException.Message, nameof(operationArguments), innerException);
            }

            var task = Task.Run(async() => { return(await program.CreateAuthentication(operationArguments)); });
            BaseAuthentication authentication = task.Result;
            Credential         credentials    = null;

            switch (operationArguments.Authority)
            {
            default:
            case AuthorityType.Basic:
            {
                var basicAuth = authentication as BasicAuthentication;

                Task.Run(async() =>
                    {
                        // Attempt to get cached credentials or acquire credentials if interactivity is allowed.
                        if ((operationArguments.Interactivity != Interactivity.Always &&
                             (credentials = authentication.GetCredentials(operationArguments.TargetUri)) != null) ||
                            (operationArguments.Interactivity != Interactivity.Never &&
                             (credentials = await basicAuth.AcquireCredentials(operationArguments.TargetUri)) != null))
                        {
                            Git.Trace.WriteLine("credentials found.");
                            // No need to save the credentials explicitly, as Git will call back
                            // with a store command if the credentials are valid.
                        }
                        else
                        {
                            Git.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' not found.");
                            program.LogEvent($"Failed to retrieve credentials for '{operationArguments.TargetUri}'.", EventLogEntryType.FailureAudit);
                        }
                    }).Wait();
            }
            break;

            case AuthorityType.AzureDirectory:
            {
                var aadAuth    = authentication as VstsAadAuthentication;
                var patOptions = new PersonalAccessTokenOptions()
                {
                    RequireCompactToken = true,
                    TokenDuration       = operationArguments.TokenDuration,
                    TokenScope          = null,
                };

                Task.Run(async() =>
                    {
                        // Attempt to get cached credentials -> non-interactive logon -> interactive
                        // logon note that AAD "credentials" are always scoped access tokens.
                        if (((operationArguments.Interactivity != Interactivity.Always &&
                              ((credentials = aadAuth.GetCredentials(operationArguments.TargetUri)) != null) &&
                              (!operationArguments.ValidateCredentials ||
                               await aadAuth.ValidateCredentials(operationArguments.TargetUri, credentials)))) ||
                            (operationArguments.Interactivity != Interactivity.Always &&
                             ((credentials = await aadAuth.NoninteractiveLogon(operationArguments.TargetUri, patOptions)) != null) &&
                             (!operationArguments.ValidateCredentials ||
                              await aadAuth.ValidateCredentials(operationArguments.TargetUri, credentials))) ||
                            (operationArguments.Interactivity != Interactivity.Never &&
                             ((credentials = await aadAuth.InteractiveLogon(operationArguments.TargetUri, patOptions)) != null) &&
                             (!operationArguments.ValidateCredentials ||
                              await aadAuth.ValidateCredentials(operationArguments.TargetUri, credentials))))
                        {
                            Git.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' found.");
                            program.LogEvent($"Azure Directory credentials  for '{operationArguments.TargetUri}' successfully retrieved.", EventLogEntryType.SuccessAudit);
                        }
                        else
                        {
                            Git.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' not found.");
                            program.LogEvent($"Failed to retrieve Azure Directory credentials for '{operationArguments.TargetUri}'.", EventLogEntryType.FailureAudit);
                        }
                    }).Wait();
            }
            break;

            case AuthorityType.MicrosoftAccount:
            {
                var msaAuth    = authentication as VstsMsaAuthentication;
                var patOptions = new PersonalAccessTokenOptions()
                {
                    RequireCompactToken = true,
                    TokenDuration       = operationArguments.TokenDuration,
                    TokenScope          = null,
                };

                Task.Run(async() =>
                    {
                        // Attempt to get cached credentials -> interactive logon note that MSA
                        // "credentials" are always scoped access tokens.
                        if (((operationArguments.Interactivity != Interactivity.Always &&
                              ((credentials = msaAuth.GetCredentials(operationArguments.TargetUri)) != null) &&
                              (!operationArguments.ValidateCredentials ||
                               await msaAuth.ValidateCredentials(operationArguments.TargetUri, credentials)))) ||
                            (operationArguments.Interactivity != Interactivity.Never &&
                             ((credentials = await msaAuth.InteractiveLogon(operationArguments.TargetUri, patOptions)) != null) &&
                             (!operationArguments.ValidateCredentials ||
                              await msaAuth.ValidateCredentials(operationArguments.TargetUri, credentials))))
                        {
                            Git.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' found.");
                            program.LogEvent($"Microsoft Live credentials for '{operationArguments.TargetUri}' successfully retrieved.", EventLogEntryType.SuccessAudit);
                        }
                        else
                        {
                            Git.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' not found.");
                            program.LogEvent($"Failed to retrieve Microsoft Live credentials for '{operationArguments.TargetUri}'.", EventLogEntryType.FailureAudit);
                        }
                    }).Wait();
            }
            break;

            case AuthorityType.GitHub:
            {
                var ghAuth = authentication as Github.Authentication;

                Task.Run(async() =>
                    {
                        if ((operationArguments.Interactivity != Interactivity.Always &&
                             ((credentials = ghAuth.GetCredentials(operationArguments.TargetUri)) != null) &&
                             (!operationArguments.ValidateCredentials ||
                              await ghAuth.ValidateCredentials(operationArguments.TargetUri, credentials))) ||
                            (operationArguments.Interactivity != Interactivity.Never &&
                             ((credentials = await ghAuth.InteractiveLogon(operationArguments.TargetUri)) != null) &&
                             (!operationArguments.ValidateCredentials ||
                              await ghAuth.ValidateCredentials(operationArguments.TargetUri, credentials))))
                        {
                            Git.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' found.");
                            program.LogEvent($"GitHub credentials for '{operationArguments.TargetUri}' successfully retrieved.", EventLogEntryType.SuccessAudit);
                        }
                        else
                        {
                            Git.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' not found.");
                            program.LogEvent($"Failed to retrieve GitHub credentials for '{operationArguments.TargetUri}'.", EventLogEntryType.FailureAudit);
                        }
                    }).Wait();
            }
            break;

            case AuthorityType.Bitbucket:
            {
                var bbcAuth = authentication as Bitbucket.Authentication;

                Task.Run(async() =>
                    {
                        if (((operationArguments.Interactivity != Interactivity.Always) &&
                             ((credentials = bbcAuth.GetCredentials(operationArguments.TargetUri, operationArguments.CredUsername)) != null) &&
                             (!operationArguments.ValidateCredentials ||
                              ((credentials = await bbcAuth.ValidateCredentials(operationArguments.TargetUri, operationArguments.CredUsername, credentials)) != null))) ||
                            ((operationArguments.Interactivity != Interactivity.Never) &&
                             ((credentials = await bbcAuth.InteractiveLogon(operationArguments.TargetUri, operationArguments.CredUsername)) != null) &&
                             (!operationArguments.ValidateCredentials ||
                              ((credentials = await bbcAuth.ValidateCredentials(operationArguments.TargetUri, operationArguments.CredUsername, credentials)) != null))))
                        {
                            Git.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' found.");
                            // Bitbucket relies on a username + secret, so make sure there is a
                            // username to return.
                            if (operationArguments.CredUsername != null)
                            {
                                credentials = new Credential(operationArguments.CredUsername, credentials.Password);
                            }
                            program.LogEvent($"Bitbucket credentials for '{operationArguments.TargetUri}' successfully retrieved.", EventLogEntryType.SuccessAudit);
                        }
                        else
                        {
                            program.LogEvent($"Failed to retrieve Bitbucket credentials for '{operationArguments.TargetUri}'.", EventLogEntryType.FailureAudit);
                        }
                    }).Wait();
            }
            break;

            case AuthorityType.Ntlm:
            {
                Git.Trace.WriteLine($"'{operationArguments.TargetUri}' is NTLM.");
                credentials = BasicAuthentication.NtlmCredentials;
            }
            break;
            }

            if (credentials != null)
            {
                operationArguments.SetCredentials(credentials);
            }

            return(credentials);
        }
        internal void Askpass(string[] args)
        {
            if (args == null || args.Length == 0)
            {
                throw new ArgumentException("Arguments cannot be empty.");
            }

            Gui.UserPromptKind promptKind = Gui.UserPromptKind.SshPassphrase;

            Match match;

            if ((match = AskPasswordRegex.Match(args[0])).Success)
            {
                promptKind = Gui.UserPromptKind.CredentialsPassword;
            }
            else if ((match = AskPassphraseRegex.Match(args[0])).Success)
            {
                promptKind = Gui.UserPromptKind.SshPassphrase;
            }

            if (match.Success)
            {
                _context.Trace.WriteLine("querying for passphrase key.");

                if (match.Groups.Count < 2)
                {
                    throw new ArgumentException("Unable to understand command.");
                }

                // string request = match.Groups[0].Value;
                string resource = match.Groups[1].Value;

                _context.Trace.WriteLine($"open dialog for '{resource}'.");

                System.Windows.Application application = new System.Windows.Application();
                Gui.UserPromptDialog       prompt      = new Gui.UserPromptDialog(promptKind, resource);
                application.Run(prompt);

                if (!prompt.Failed && !string.IsNullOrEmpty(prompt.Response))
                {
                    string passphase = prompt.Response;

                    _context.Trace.WriteLine("passphase acquired.");

                    Out.Write(passphase + "\n");
                    return;
                }

                Die("failed to interactively acquire credentials.");
            }

            if ((match = AskCredentialRegex.Match(args[0])).Success)
            {
                _context.Trace.WriteLine("querying for basic credentials.");

                if (match.Groups.Count < 3)
                {
                    throw new ArgumentException("Unable to understand command.");
                }

                string seeking   = match.Groups[1].Value;
                string targetUrl = match.Groups[2].Value;

                string username  = string.Empty;
                string password  = string.Empty;
                Uri    targetUri = null;

                // Since we're looking for HTTP(s) credentials, we can use NetFx `Uri` class.
                if (Uri.TryCreate(targetUrl, UriKind.Absolute, out targetUri))
                {
                    _context.Trace.WriteLine($"success parsing URL, targetUri = '{targetUri}'.");

                    if (TryParseUrlCredentials(targetUrl, out username, out password))
                    {
                        if (password != null &&
                            seeking.Equals("Password", StringComparison.OrdinalIgnoreCase))
                        {
                            Out.Write(password + '\n');
                            return;
                        }

                        // print the username if it sought
                        if (seeking.Equals("Username", StringComparison.OrdinalIgnoreCase))
                        {
                            Out.Write(username + '\n');
                            return;
                        }
                    }

                    // create a target Url with the credential portion stripped, because Git doesn't
                    // report hosts with credentials
                    targetUrl = targetUri.Scheme + "://";

                    // Add the username@ portion of the url if it exists
                    if (username != null)
                    {
                        targetUrl += Uri.EscapeDataString(username);

                        targetUrl += '@';
                    }

                    targetUrl += targetUri.Host;

                    // retain the port if specified
                    if (!targetUri.IsDefaultPort)
                    {
                        targetUrl += $":{targetUri.Port}";
                    }

                    // retain the path if specified
                    if (!string.IsNullOrWhiteSpace(targetUri.LocalPath))
                    {
                        targetUrl += targetUri.LocalPath;
                    }

                    if (Uri.TryCreate(targetUrl, UriKind.Absolute, out targetUri))
                    {
                        _context.Trace.WriteLine($"success parsing URL, targetUri = '{targetUri}'.");

                        OperationArguments operationArguments = new OperationArguments(_context, targetUri);
                        operationArguments.SetCredentials(username ?? string.Empty, password ?? string.Empty);

                        // Load up the operation arguments, enable tracing, and query for credentials.
                        Task.Run(async() =>
                        {
                            await LoadOperationArguments(operationArguments);
                            EnableTraceLogging(operationArguments);

                            Credential credentials;
                            if ((credentials = await QueryCredentials(operationArguments)) != null)
                            {
                                if (seeking.Equals("Username", StringComparison.OrdinalIgnoreCase))
                                {
                                    _context.Trace.WriteLine($"username for '{targetUrl}' asked for and found.");

                                    Out.Write(credentials.Username + '\n');
                                    return;
                                }

                                if (seeking.Equals("Password", StringComparison.OrdinalIgnoreCase))
                                {
                                    _context.Trace.WriteLine($"password for '{targetUrl}' asked for and found.");

                                    Out.Write(credentials.Password + '\n');
                                    return;
                                }
                            }
                            else
                            {
                                _context.Trace.WriteLine($"user cancelled credential dialog.");
                                return;
                            }
                        }).Wait();
                    }
                    else
                    {
                        _context.Trace.WriteLine("error: unable to parse target URL.");
                    }
                }
                else
                {
                    _context.Trace.WriteLine("error: unable to parse supplied URL.");
                }

                Die($"failed to detect {seeking} in target URL.");
            }

            if ((match = AskAuthenticityRegex.Match(args[0])).Success)
            {
                string host        = match.Groups[1].Value;
                string fingerprint = match.Groups[2].Value;

                _context.Trace.WriteLine($"requesting authorization to add {host} ({fingerprint}) to known hosts.");

                System.Windows.Application application = new System.Windows.Application();
                Gui.UserPromptDialog       prompt      = new Gui.UserPromptDialog(host, fingerprint);
                application.Run(prompt);

                if (prompt.Failed)
                {
                    _context.Trace.WriteLine("denied authorization of host.");
                    Out.Write("no\n");
                }
                else
                {
                    _context.Trace.WriteLine("approved authorization of host.");
                    Out.Write("yes\n");
                }

                return;
            }

            Die("failed to acquire credentials.");
        }
        private static bool QueryCredentials(OperationArguments operationArguments)
        {
            const string AadMsaAuthFailureMessage = "Logon failed, use ctrl+c to cancel basic credential prompt.";
            const string BasicAuthFaulureMessage = "Logon failed, use ctrl+c to cancel basic credential prompt.";
            const string GitHubAuthFailureMessage = "Logon failed, use ctrl+c to cancel basic credential prompt.";

            if (ReferenceEquals(operationArguments, null))
                throw new ArgumentNullException("operationArguments");
            if (ReferenceEquals(operationArguments.TargetUri, null))
                throw new ArgumentNullException("operationArguments.TargetUri");

            bool credentialsFound = false;
            BaseAuthentication authentication = CreateAuthentication(operationArguments);
            Credential credentials = null;

            switch (operationArguments.Authority)
            {
                default:
                case AuthorityType.Basic:
                    {
                        BasicAuthentication basicAuth = authentication as BasicAuthentication;

                        Task.Run(async () =>
                        {
                            // attempt to get cached creds or acquire creds if interactivity is allowed
                            if ((operationArguments.Interactivity != Interactivity.Always
                                    && (credentials = authentication.GetCredentials(operationArguments.TargetUri)) != null)
                                || (operationArguments.Interactivity != Interactivity.Never
                                    && (credentials = await basicAuth.AcquireCredentials(operationArguments.TargetUri)) != null))
                            {
                                Git.Trace.WriteLine("credentials found.");
                                // set the credentials object
                                // no need to save the credentials explicitly, as Git will call back
                                // with a store command if the credentials are valid.
                                operationArguments.SetCredentials(credentials);
                                credentialsFound = true;
                            }
                            else
                            {
                                Git.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' not found.");
                                Program.WriteLine(BasicAuthFaulureMessage);
                                LogEvent($"Failed to retrieve credentials for '{operationArguments.TargetUri}'.", EventLogEntryType.FailureAudit);
                            }
                        }).Wait();
                    }
                    break;

                case AuthorityType.AzureDirectory:
                    {
                        VstsAadAuthentication aadAuth = authentication as VstsAadAuthentication;

                        Task.Run(async () =>
                        {
                            // attempt to get cached creds -> non-interactive logon -> interactive logon
                            // note that AAD "credentials" are always scoped access tokens
                            if (((operationArguments.Interactivity != Interactivity.Always
                                    && ((credentials = aadAuth.GetCredentials(operationArguments.TargetUri)) != null)
                                    && (!operationArguments.ValidateCredentials
                                        || await aadAuth.ValidateCredentials(operationArguments.TargetUri, credentials))))
                                || (operationArguments.Interactivity != Interactivity.Always
                                        && ((credentials = await aadAuth.NoninteractiveLogon(operationArguments.TargetUri, true)) != null)
                                    && (!operationArguments.ValidateCredentials
                                        || await aadAuth.ValidateCredentials(operationArguments.TargetUri, credentials)))
                                || (operationArguments.Interactivity != Interactivity.Never
                                    && ((credentials = await aadAuth.InteractiveLogon(operationArguments.TargetUri, true)) != null)
                                    && (!operationArguments.ValidateCredentials
                                        || await aadAuth.ValidateCredentials(operationArguments.TargetUri, credentials))))
                            {
                                Git.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' found.");
                                operationArguments.SetCredentials(credentials);
                                credentialsFound = true;
                                LogEvent($"Azure Directory credentials  for '{operationArguments.TargetUri}' successfully retrieved.", EventLogEntryType.SuccessAudit);
                            }
                            else
                            {
                                Git.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' not found.");
                                Program.WriteLine(AadMsaAuthFailureMessage);
                                LogEvent($"Failed to retrieve Azure Directory credentials for '{operationArguments.TargetUri}'.", EventLogEntryType.FailureAudit);
                            }
                        }).Wait();
                    }
                    break;

                case AuthorityType.MicrosoftAccount:
                    {
                        VstsMsaAuthentication msaAuth = authentication as VstsMsaAuthentication;

                        Task.Run(async () =>
                        {
                            // attempt to get cached creds -> interactive logon
                            // note that MSA "credentials" are always scoped access tokens
                            if (((operationArguments.Interactivity != Interactivity.Always
                                    && ((credentials = msaAuth.GetCredentials(operationArguments.TargetUri)) != null)
                                    && (!operationArguments.ValidateCredentials
                                        || await msaAuth.ValidateCredentials(operationArguments.TargetUri, credentials))))
                                || (operationArguments.Interactivity != Interactivity.Never
                                    && ((credentials = await msaAuth.InteractiveLogon(operationArguments.TargetUri, true)) != null)
                                    && (!operationArguments.ValidateCredentials
                                        || await msaAuth.ValidateCredentials(operationArguments.TargetUri, credentials))))
                            {
                                Git.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' found.");
                                operationArguments.SetCredentials(credentials);
                                credentialsFound = true;
                                LogEvent($"Microsoft Live credentials for '{operationArguments.TargetUri}' successfully retrieved.", EventLogEntryType.SuccessAudit);
                            }
                            else
                            {
                                Git.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' not found.");
                                Program.WriteLine(AadMsaAuthFailureMessage);
                                LogEvent($"Failed to retrieve Microsoft Live credentials for '{operationArguments.TargetUri}'.", EventLogEntryType.FailureAudit);
                            }
                        }).Wait();
                    }
                    break;

                case AuthorityType.GitHub:
                    {
                        GitHubAuthentication ghAuth = authentication as GitHubAuthentication;

                        Task.Run(async () =>
                        {
                            if ((operationArguments.Interactivity != Interactivity.Always
                                    && ((credentials = ghAuth.GetCredentials(operationArguments.TargetUri)) != null)
                                    && (!operationArguments.ValidateCredentials
                                        || await ghAuth.ValidateCredentials(operationArguments.TargetUri, credentials)))
                                || (operationArguments.Interactivity != Interactivity.Never
                                    && ((credentials = await ghAuth.InteractiveLogon(operationArguments.TargetUri)) != null)
                                    && (!operationArguments.ValidateCredentials
                                        || await ghAuth.ValidateCredentials(operationArguments.TargetUri, credentials))))
                            {
                                Git.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' found.");
                                operationArguments.SetCredentials(credentials);
                                credentialsFound = true;
                                LogEvent($"GitHub credentials for '{operationArguments.TargetUri}' successfully retrieved.", EventLogEntryType.SuccessAudit);
                            }
                            else
                            {
                                Git.Trace.WriteLine($"credentials for '{operationArguments.TargetUri}' not found.");
                                Program.WriteLine(GitHubAuthFailureMessage);
                                LogEvent($"Failed to retrieve GitHub credentials for '{operationArguments.TargetUri}'.", EventLogEntryType.FailureAudit);
                            }
                        }).Wait();
                    }
                    break;

                case AuthorityType.Ntlm:
                    {
                        Git.Trace.WriteLine($"'{operationArguments.TargetUri}' is NTLM.");
                        operationArguments.SetCredentials(BasicAuthentication.NtlmCredentials);
                        credentialsFound = true;
                    }
                    break;
            }

            return credentialsFound;
        }