private string CreateServiceSlug(string service) { var sb = new StringBuilder(); char sep = Path.DirectorySeparatorChar; if (!string.IsNullOrWhiteSpace(Namespace)) { sb.AppendFormat("{0}{1}", Namespace, sep); } if (Uri.TryCreate(service, UriKind.Absolute, out Uri serviceUri)) { sb.AppendFormat("{0}{1}", serviceUri.Scheme, sep); sb.AppendFormat("{0}", serviceUri.Host); if (!serviceUri.IsDefaultPort) { sb.Append(PlatformUtils.IsWindows() ? '-' : ':'); sb.Append(serviceUri.Port); } sb.Append(serviceUri.AbsolutePath.Replace('/', sep)); } else { sb.Append(service); } return(sb.ToString()); }
private static string GetGitPath(IEnvironment environment, IFileSystem fileSystem, ITrace trace) { const string unixGitName = "git"; const string winGitName = "git.exe"; string gitExecPath; string programName = PlatformUtils.IsWindows() ? winGitName : unixGitName; // Use the GIT_EXEC_PATH environment variable if set if (environment.Variables.TryGetValue(Constants.EnvironmentVariables.GitExecutablePath, out gitExecPath)) { // If we're invoked from WSL we must locate the UNIX Git executable if (PlatformUtils.IsWindows() && WslUtils.IsWslPath(gitExecPath)) { programName = unixGitName; } string candidatePath = Path.Combine(gitExecPath, programName); if (fileSystem.FileExists(candidatePath)) { trace.WriteLine($"Using Git executable from GIT_EXEC_PATH: {candidatePath}"); return(candidatePath); } } // Otherwise try to locate the git(.exe) on the current PATH gitExecPath = environment.LocateExecutable(programName); trace.WriteLine($"Using PATH-located Git executable: {gitExecPath}"); return(gitExecPath); }
public EnvironmentVariables(IDictionary variables) { EnsureArgument.NotNull(variables, nameof(variables)); // On Windows it is technically possible to get env vars which differ only by case // even though the general assumption is that they are case insensitive on Windows. // For example, some of the standard .NET types like System.Diagnostics.Process // will fail to start a process on Windows if given duplicate environment variables. // See this issue for more information: https://github.com/dotnet/corefx/issues/13146 // If we're on the Windows platform we should de-duplicate by setting the string // comparer to OrdinalIgnoreCase. var comparer = PlatformUtils.IsWindows() ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal; var dict = new Dictionary <string, string>(comparer); foreach (var key in variables.Keys) { if (key is string name && variables[key] is string value) { dict[name] = value; } } _envars = dict; }
public CommandContext() { Streams = new StandardStreams(); Trace = new Trace(); FileSystem = new FileSystem(); var git = new LibGit2(); var envars = new EnvironmentVariables(Environment.GetEnvironmentVariables()); Settings = new Settings(envars, git) { RepositoryPath = git.GetRepositoryPath(FileSystem.GetCurrentDirectory()) }; HttpClientFactory = new HttpClientFactory(Trace, Settings, Streams); if (PlatformUtils.IsWindows()) { Terminal = new WindowsTerminal(Trace); CredentialStore = WindowsCredentialManager.Open(); } else if (PlatformUtils.IsPosix()) { Terminal = new PosixTerminal(Trace); if (PlatformUtils.IsMacOS()) { CredentialStore = MacOSKeychain.Open(); } else if (PlatformUtils.IsLinux()) { throw new NotImplementedException(); } } }
public CommandContext() { Streams = new StandardStreams(); Trace = new Trace(); Git = new LibGit2(Trace); if (PlatformUtils.IsWindows()) { FileSystem = new WindowsFileSystem(); Environment = new WindowsEnvironment(FileSystem); Terminal = new WindowsTerminal(Trace); CredentialStore = WindowsCredentialManager.Open(); } else if (PlatformUtils.IsPosix()) { if (PlatformUtils.IsMacOS()) { FileSystem = new MacOSFileSystem(); CredentialStore = MacOSKeychain.Open(); } else if (PlatformUtils.IsLinux()) { throw new NotImplementedException(); } Environment = new PosixEnvironment(FileSystem); Terminal = new PosixTerminal(Trace); } string repoPath = Git.GetRepositoryPath(FileSystem.GetCurrentDirectory()); Settings = new Settings(Environment, Git, repoPath); HttpClientFactory = new HttpClientFactory(Trace, Settings, Streams); }
private static void AppendAvailableStoreList(StringBuilder sb) { if (PlatformUtils.IsWindows()) { sb.AppendFormat(" {1,-13} : Windows Credential Manager (not available over network/SSH sessions){0}", Environment.NewLine, StoreNames.WindowsCredentialManager); sb.AppendFormat(" {1,-13} : DPAPI protected files{0}", Environment.NewLine, StoreNames.Dpapi); } if (PlatformUtils.IsMacOS()) { sb.AppendFormat(" {1,-13} : macOS Keychain{0}", Environment.NewLine, StoreNames.MacOSKeychain); } if (PlatformUtils.IsLinux()) { sb.AppendFormat(" {1,-13} : freedesktop.org Secret Service (requires graphical interface){0}", Environment.NewLine, StoreNames.SecretService); } if (PlatformUtils.IsPosix()) { sb.AppendFormat(" {1,-13} : GNU `pass` compatible credential storage (requires GPG and `pass`){0}", Environment.NewLine, StoreNames.Gpg); } sb.AppendFormat(" {1,-13} : Git's in-memory credential cache{0}", Environment.NewLine, StoreNames.Cache); sb.AppendFormat(" {1,-13} : store credentials in plain-text files (UNSECURE){0}", Environment.NewLine, StoreNames.Plaintext); }
Task IConfigurableComponent.UnconfigureAsync( IEnvironment environment, EnvironmentVariableTarget environmentTarget, IGit git, GitConfigurationLevel configurationLevel) { string helperKey = $"{Constants.GitConfiguration.Credential.SectionName}.{Constants.GitConfiguration.Credential.Helper}"; string gitConfigAppName = GetGitConfigAppName(); IGitConfiguration targetConfig = git.GetConfiguration(configurationLevel); Context.Trace.WriteLine("Removing Git credential helper configuration..."); // Clear any blank 'reset' entries targetConfig.UnsetAll(helperKey, Constants.RegexPatterns.Empty); // Clear GCM executable entries targetConfig.UnsetAll(helperKey, Regex.Escape(gitConfigAppName)); // NOTE: We currently only update the PATH in Windows installations and leave removing the GCM executable // on the PATH on other platform to their installers. // Remove GCM executable from the PATH if (PlatformUtils.IsWindows()) { Context.Trace.WriteLine("Removing application from the PATH..."); string directoryPath = Path.GetDirectoryName(_appPath); environment.RemoveDirectoryFromPath(directoryPath, environmentTarget); } return(Task.CompletedTask); }
Task IConfigurableComponent.ConfigureAsync( IEnvironment environment, EnvironmentVariableTarget environmentTarget, IGit git, GitConfigurationLevel configurationLevel) { // NOTE: We currently only update the PATH in Windows installations and leave putting the GCM executable // on the PATH on other platform to their installers. if (PlatformUtils.IsWindows()) { string directoryPath = Path.GetDirectoryName(_appPath); if (!environment.IsDirectoryOnPath(directoryPath)) { Context.Trace.WriteLine("Adding application to PATH..."); environment.AddDirectoryToPath(directoryPath, environmentTarget); } else { Context.Trace.WriteLine("Application is already on the PATH."); } } string helperKey = $"{Constants.GitConfiguration.Credential.SectionName}.{Constants.GitConfiguration.Credential.Helper}"; string gitConfigAppName = GetGitConfigAppName(); IGitConfiguration targetConfig = git.GetConfiguration(configurationLevel); /* * We are looking for the following to be considered already set: * * [credential] * ... # any number of helper entries * helper = # an empty value to reset/clear any previous entries * helper = {gitConfigAppName} # the expected executable value in the last position & directly following the empty value * */ string[] currentValues = targetConfig.GetRegex(helperKey, Constants.RegexPatterns.Any).ToArray(); if (currentValues.Length < 2 || !string.IsNullOrWhiteSpace(currentValues[currentValues.Length - 2]) || // second to last entry is empty currentValues[currentValues.Length - 1] != gitConfigAppName) // last entry is the expected executable { Context.Trace.WriteLine("Updating Git credential helper configuration..."); // Clear any existing entries in the configuration. targetConfig.UnsetAll(helperKey, Constants.RegexPatterns.Any); // Add an empty value for `credential.helper`, which has the effect of clearing any helper value // from any lower-level Git configuration, then add a second value which is the actual executable path. targetConfig.SetValue(helperKey, string.Empty); targetConfig.ReplaceAll(helperKey, Constants.RegexPatterns.None, gitConfigAppName); } else { Context.Trace.WriteLine("Credential helper configuration is already set correctly."); } return(Task.CompletedTask); }
private static string GetDefaultStore() { if (PlatformUtils.IsWindows()) { return(StoreNames.WindowsCredentialManager); } if (PlatformUtils.IsMacOS()) { return(StoreNames.MacOSKeychain); } // Other platforms have no default store return(null); }
private string GetGitConfigAppPath() { string path = _appPath; // On Windows we must use UNIX style path separators if (PlatformUtils.IsWindows()) { path = path.Replace('\\', '/'); } // We must escape escape characters like ' ', '(', and ')' return(path .Replace(" ", "\\ ") .Replace("(", "\\(") .Replace(")", "\\)"));; }
private static string GetGitPath(IEnvironment environment, IFileSystem fileSystem) { string programName = PlatformUtils.IsWindows() ? "git.exe" : "git"; // Use the GIT_EXEC_PATH environment variable if set if (environment.Variables.TryGetValue(Constants.EnvironmentVariables.GitExecutablePath, out string gitExecPath)) { string candidatePath = Path.Combine(gitExecPath, programName); if (fileSystem.FileExists(candidatePath)) { return(candidatePath); } } // Otherwise try to locate the git(.exe) on the current PATH return(environment.LocateExecutable(programName)); }
private static string GetApplicationPath() { Assembly entryAssembly = Assembly.GetExecutingAssembly(); if (entryAssembly is null) { throw new InvalidOperationException(); } string candidatePath = entryAssembly.Location; // Strip the .dll from assembly name on Mac and Linux if (!PlatformUtils.IsWindows() && Path.HasExtension(candidatePath)) { return(Path.ChangeExtension(candidatePath, null)); } return(candidatePath); }
private void ValidateWindowsCredentialManager() { if (!PlatformUtils.IsWindows()) { throw new Exception( $"Can only use the '{StoreNames.WindowsCredentialManager}' credential store on Windows." + Environment.NewLine + $"See {Constants.HelpUrls.GcmCredentialStores} for more information." ); } if (!WindowsCredentialManager.CanPersist()) { throw new Exception( $"Unable to persist credentials with the '{StoreNames.WindowsCredentialManager}' credential store." + Environment.NewLine + $"See {Constants.HelpUrls.GcmCredentialStores} for more information." ); } }
public override async Task <ICredential> GenerateCredentialAsync(InputArguments input) { ThrowIfDisposed(); Uri uri = GetUriFromInput(input); // Determine the if the host supports Windows Integration Authentication (WIA) if (IsWindowsAuthAllowed) { if (PlatformUtils.IsWindows()) { Context.Trace.WriteLine($"Checking host '{uri.AbsoluteUri}' for Windows Integrated Authentication..."); bool isWiaSupported = await _winAuth.GetIsSupportedAsync(uri); if (!isWiaSupported) { Context.Trace.WriteLine("Host does not support WIA."); } else { Context.Trace.WriteLine("Host supports WIA - generating empty credential..."); // WIA is signaled to Git using an empty username/password return(new GitCredential(string.Empty, string.Empty)); } } else { string osType = PlatformUtils.GetPlatformInformation().OperatingSystemType; Context.Trace.WriteLine($"Skipping check for Windows Integrated Authentication on {osType}."); } } else { Context.Trace.WriteLine("Windows Integrated Authentication detection has been disabled."); } Context.Trace.WriteLine("Prompting for basic credentials..."); return(_basicAuth.GetCredentials(uri.AbsoluteUri, uri.UserInfo)); }
private void ValidateDpapi(out string storeRoot) { if (!PlatformUtils.IsWindows()) { throw new Exception( $"Can only use the '{StoreNames.Dpapi}' credential store on Windows." + Environment.NewLine + $"See {Constants.HelpUrls.GcmCredentialStores} for more information." ); } // Check for a redirected credential store location if (!_context.Settings.TryGetSetting( Constants.EnvironmentVariables.GcmDpapiStorePath, Constants.GitConfiguration.Credential.SectionName, Constants.GitConfiguration.Credential.DpapiStorePath, out storeRoot)) { // Use default store root at ~/.gcm/dpapi_store storeRoot = Path.Combine(_context.FileSystem.UserDataDirectoryPath, "dpapi_store"); } }
public CommandContext() { Streams = new StandardStreams(); Trace = new Trace(); if (PlatformUtils.IsWindows()) { FileSystem = new WindowsFileSystem(); SessionManager = new WindowsSessionManager(); SystemPrompts = new WindowsSystemPrompts(); Environment = new WindowsEnvironment(FileSystem); Terminal = new WindowsTerminal(Trace); string gitPath = GetGitPath(Environment, FileSystem); Git = new GitProcess( Trace, gitPath, FileSystem.GetCurrentDirectory() ); Settings = new Settings(Environment, Git); CredentialStore = new WindowsCredentialManager(Settings.CredentialNamespace); } else if (PlatformUtils.IsMacOS()) { FileSystem = new MacOSFileSystem(); SessionManager = new MacOSSessionManager(); SystemPrompts = new MacOSSystemPrompts(); Environment = new PosixEnvironment(FileSystem); Terminal = new PosixTerminal(Trace); string gitPath = GetGitPath(Environment, FileSystem); Git = new GitProcess( Trace, gitPath, FileSystem.GetCurrentDirectory() ); Settings = new Settings(Environment, Git); CredentialStore = new MacOSKeychain(Settings.CredentialNamespace); } else if (PlatformUtils.IsLinux()) { FileSystem = new LinuxFileSystem(); // TODO: support more than just 'Posix' or X11 SessionManager = new PosixSessionManager(); SystemPrompts = new LinuxSystemPrompts(); Environment = new PosixEnvironment(FileSystem); Terminal = new PosixTerminal(Trace); string gitPath = GetGitPath(Environment, FileSystem); Git = new GitProcess( Trace, gitPath, FileSystem.GetCurrentDirectory() ); Settings = new Settings(Environment, Git); IGpg gpg = new Gpg( Environment.LocateExecutable("gpg"), SessionManager ); CredentialStore = new LinuxCredentialStore(FileSystem, Settings, SessionManager, gpg, Environment); } else { throw new PlatformNotSupportedException(); } HttpClientFactory = new HttpClientFactory(Trace, Settings, Streams); // Set the parent window handle/ID SystemPrompts.ParentWindowId = Settings.ParentWindowId; }
public CommandContext(string appPath) { EnsureArgument.NotNullOrWhiteSpace(appPath, nameof(appPath)); ApplicationPath = appPath; Streams = new StandardStreams(); Trace = new Trace(); if (PlatformUtils.IsWindows()) { FileSystem = new WindowsFileSystem(); SessionManager = new WindowsSessionManager(); SystemPrompts = new WindowsSystemPrompts(); Environment = new WindowsEnvironment(FileSystem); Terminal = new WindowsTerminal(Trace); string gitPath = GetGitPath(Environment, FileSystem, Trace); Git = new GitProcess( Trace, Environment, gitPath, FileSystem.GetCurrentDirectory() ); Settings = new WindowsSettings(Environment, Git, Trace); } else if (PlatformUtils.IsMacOS()) { FileSystem = new MacOSFileSystem(); SessionManager = new MacOSSessionManager(); SystemPrompts = new MacOSSystemPrompts(); Environment = new PosixEnvironment(FileSystem); Terminal = new MacOSTerminal(Trace); string gitPath = GetGitPath(Environment, FileSystem, Trace); Git = new GitProcess( Trace, Environment, gitPath, FileSystem.GetCurrentDirectory() ); Settings = new Settings(Environment, Git); } else if (PlatformUtils.IsLinux()) { FileSystem = new LinuxFileSystem(); // TODO: support more than just 'Posix' or X11 SessionManager = new PosixSessionManager(); SystemPrompts = new LinuxSystemPrompts(); Environment = new PosixEnvironment(FileSystem); Terminal = new LinuxTerminal(Trace); string gitPath = GetGitPath(Environment, FileSystem, Trace); Git = new GitProcess( Trace, Environment, gitPath, FileSystem.GetCurrentDirectory() ); Settings = new Settings(Environment, Git); } else { throw new PlatformNotSupportedException(); } HttpClientFactory = new HttpClientFactory(FileSystem, Trace, Settings, Streams); CredentialStore = new CredentialStore(this); // Set the parent window handle/ID SystemPrompts.ParentWindowId = Settings.ParentWindowId; }