Public/Configure-GitCmdLine.ps1
<#
.SYNOPSIS Configures Git Command Line for the current PowerShell Session in the current local Git Repo directory. .DESCRIPTION See Synopsis. .PARAMETER GitHubUserName TODO .PARAMETER GitHubEmail TODO .PARAMETER AuthMethod TODO .PARAMETER ExistingSSHPrivateKeyPath TODO .PARAMETER NewSSHKeyName TODO .PARAMETER NewSSHKeyPwd TODO .PARAMETER PersonalAccessToken TODO .EXAMPLE # Launch PowerShell and... $GitAuthParams = @{ GitHubUserName = "pldmgg" GitHubEmail = "pldmgg@mykolab.com" AuthMethod = "https" PersonalAccessToken = "2345678dsfghjk4567890" } Configure-GitCmdLine @GitAuthParams .EXAMPLE # Launch PowerShell and... $GitAuthParams = @{ GitHubUserName = "pldmgg" GitHubEmail = "pldmgg@mykolab.com" AuthMethod = "ssh" NewSSHKeyName "gitauth_rsa" } Configure-GitCmdLine @GitAuthParams .EXAMPLE # Launch PowerShell and... $GitAuthParams = @{ GitHubUserName = "pldmgg" GitHubEmail = "pldmgg@mykolab.com" AuthMethod = "ssh" ExistingSSHPrivateKeyPath = "$HOME\.ssh\github_rsa" } Configure-GitCmdLine @GitAuthParams #> function Configure-GitCmdLine { [CmdletBinding(DefaultParameterSetname='AuthSetup')] Param( [Parameter(Mandatory=$False)] [string]$GitHubUserName = $(Read-Host -Prompt "Please enter your GitHub Username"), [Parameter(Mandatory=$False)] [string]$GitHubEmail = $(Read-Host -Prompt "Please the primary GitHub email address associated with $GitHubUserName"), [Parameter(Mandatory=$False)] [ValidateSet("https","ssh")] [string]$AuthMethod = $(Read-Host -Prompt "Please select the Authentication Method you would like to use. [https/ssh]"), [Parameter( Mandatory=$False, ParameterSetName='SSH Auth' )] [string]$ExistingSSHPrivateKeyPath, [Parameter( Mandatory=$False, ParameterSetName='SSH Auth' )] [string]$NewSSHKeyName, [Parameter( Mandatory=$False, ParameterSetName='SSH Auth' )] $NewSSHKeyPwd, [Parameter( Mandatory=$False, ParameterSetName='HTTPS Auth' )] [securestring]$PersonalAccessToken ) ##### BEGIN Variable/Parameter Transforms and PreRun Prep ###### $CurrentUser = $($([System.Security.Principal.WindowsIdentity]::GetCurrent()).Name -split "\\")[-1] # Make sure git cmdline is installed if (![bool]$(Get-Command git -ErrorAction SilentlyContinue)) { $ExpectedGitPath = "C:\Program Files\Git\cmd" if ($($env:Path -split ";") -notcontains [regex]::Escape($ExpectedGitPath)) { if (Test-Path $ExpectedGitPath) { $env:Path = $ExpectedGitPath + ";" + $env:Path } } } if (![bool]$(Get-Command git -ErrorAction SilentlyContinue)) { Write-Error "Unable to find git.exe! Try installing with the 'Install-GitCmdLine' function. Halting!" $global:FunctionResult = "1" return } # Make sure global config for UserName and Email Address is configured git config --global user.name "$GitHubUserName" git config --global user.email "$GitHubEmail" if ($ExistingSSHPrivateKeyPath -or $NewSSHKeyName -or $NewSSHKeyPwd) { $AuthMethod = "ssh" } if ($PersonalAccessToken) { $AuthMethod = "https" } if (!$AuthMethod) { $AuthMethod = "ssh" } if ($AuthMethod -eq "https" -and $($ExistingSSHPrivateKeyPath -or $NewSSHKeyName -or $NewSSHKeyPwd)) { $ErrMsg = "The parameters -ExistingSSHPrivateKeyPath, -NewSSHKeyName, " + "and/or -NewSSHKeyPwd should only be used when -AuthMethod is `"ssh`"! Halting!" Write-Error $ErrMsg $global:FunctionResult = "1" return } # NOTE: We do NOT need to force use of -ExistingSSHPrivateKeyPath or -NewSSHKeyName when -AuthMethod is "ssh" # because Setup-GitCmdLine function can handle things if neither are provided if ($AuthMethod -eq "https") { if (!$PersonalAccessToken) { $PersonalAccessToken = Read-Host -Prompt "Please enter the GitHub Personal Access Token you would like to use for https authentication." -AsSecureString } # Convert SecureString to PlainText $PersonalAccessTokenPT = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($PersonalAccessToken)) git config --global credential.helper wincred # Alternate Stored Credentials Format <# $ManageStoredCredsParams = @{ Target = "git:https://$PersonalAccessToken@github.com" User = $PersonalAccessToken Pass = 'x-oauth-basic' Comment = "Saved By Manage-StoredCredentials" } #> $ManageStoredCredsParams = @{ Target = "git:https://$GitHubUserName@github.com" User = $GitHubUserName Pass = $PersonalAccessTokenPT Comment = "Saved By Manage-StoredCredentials" } $null = Manage-StoredCredentials -AddCred @ManageStoredCredsParams # Test https OAuth2 authentication # More info here: https://channel9.msdn.com/Blogs/trevor-powershell/Automating-the-GitHub-REST-API-Using-PowerShell $GitHubAuthSuccess = Test-GitAuthentication -GitHubUserName $GitHubUserName -AuthMethod $AuthMethod -PersonalAccessToken $PersonalAccessToken if ($GitHubAuthSuccess) { $env:GitCmdLineConfigured = "True" } } if ($AuthMethod -eq "ssh") { if ($ExistingSSHPrivateKeyPath) { try { $ExistingSSHPrivateKeyPath = $(Resolve-Path $ExistingSSHPrivateKeyPath -ErrorAction Stop).Path } catch { Write-Error $_ $global:FunctionResult = "1" return } } else { if (Test-Path "$HOME\.ssh\github_rsa") { $ExistingSSHPrivateKeyPath = "$HOME\.ssh\github_rsa" } else { if ($NewSSHKeyPwd) { if ($NewSSHKeyPwd.GetType().FullName -eq "System.Security.SecureString") { # Convert SecureString to PlainText $NewSSHKeyPwd = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($NewSSHKeyPwd)) } } if (!$NewSSHKeyName) { $NewSSHKeyName = "github_rsa" } $SSHKeyGenPath = $(Get-ChildItem "C:\Program Files\Git" -Recurse -Filter "*ssh-keygen.exe").FullName $SSHKeyGenArgumentsString = "-t rsa -b 2048 -f `"$HOME\.ssh\$NewSSHKeyName`" -q -N `"$NewSSHKeyPwd`" -C `"GitAuthFor$CurrentUser`"" $SSHKeyGenArgumentsNoPwdString = "-t rsa -b 2048 -f `"$HOME\.ssh\$NewSSHKeyName`" -q -C `"GitAuthFor$CurrentUser`"" if (!$(Test-Path "$HOME\.ssh")) { New-Item -Type Directory -Path "$HOME\.ssh" } # Create new public/private keypair if ($NewSSHKeyPwd) { $ProcessInfo = New-Object System.Diagnostics.ProcessStartInfo $ProcessInfo.WorkingDirectory = $($SSHKeyGenPath | Split-Path -Parent) $ProcessInfo.FileName = $SSHKeyGenPath $ProcessInfo.RedirectStandardError = $true $ProcessInfo.RedirectStandardOutput = $true $ProcessInfo.UseShellExecute = $false $ProcessInfo.Arguments = $SSHKeyGenArgumentsString $Process = New-Object System.Diagnostics.Process $Process.StartInfo = $ProcessInfo $Process.Start() | Out-Null $stdout = $Process.StandardOutput.ReadToEnd() $stderr = $Process.StandardError.ReadToEnd() $AllOutput = $stdout + $stderr if ($AllOutput -match "fail|error") { Write-Error $AllOutput Write-Error "The 'ssh-keygen command failed! Halting!" $global:FunctionResult = "1" return } } else { try { if ($(Get-Module -ListAvailable).Name -notcontains 'WinSSH') {$null = Install-Module WinSSH -ErrorAction Stop} if ($(Get-Module).Name -notcontains 'WinSSH') {$null = Import-Module WinSSH -ErrorAction Stop} Import-Module "$($(Get-Module WinSSH).ModuleBase)\Await\Await.psd1" -ErrorAction Stop } catch { Write-Error $_ $global:FunctionResult = "1" return } # Make sure we don't have any other Await sessions running... try { $null = Stop-AwaitSession } catch { Write-Verbose $_.Exception.Message } Start-AwaitSession Start-Sleep -Seconds 1 Send-AwaitCommand '$host.ui.RawUI.WindowTitle = "PSAwaitSession"' $PSAwaitProcess = $($(Get-Process | ? {$_.Name -eq "powershell"}) | Sort-Object -Property StartTime -Descending)[0] Start-Sleep -Seconds 1 Send-AwaitCommand "`$env:Path = '$env:Path'; Push-Location '$($SSHKeyGenPath | Split-Path -Parent)'" Start-Sleep -Seconds 1 #Send-AwaitCommand "Invoke-Expression `"& '$SSHKeyGenPath' $SSHKeyGenArgumentsNoPwdString`"" Send-AwaitCommand ".\ssh-keygen.exe $SSHKeyGenArgumentsNoPwdString" Start-Sleep -Seconds 2 # The below is the equivalent of pressing [ENTER] to proceed with the ssh-keygen.exe interactive prompt Send-AwaitCommand "" Start-Sleep -Seconds 2 # The below is the equivalent of pressing [ENTER] to proceed with the ssh-keygen.exe interactive prompt Send-AwaitCommand "" Start-Sleep -Seconds 1 $SSHKeyGenConsoleOutput = Receive-AwaitResponse # If Stop-AwaitSession errors for any reason, it doesn't return control, so we need to handle in try/catch block if ($PSAwaitProcess.Id) { try { $null = Stop-AwaitSession } catch { if ($PSAwaitProcess.Id -eq $PID) { Write-Error "The PSAwaitSession never spawned! Halting!" $global:FunctionResult = "1" return } else { if ([bool]$(Get-Process -Id $PSAwaitProcess.Id -ErrorAction SilentlyContinue)) { Stop-Process -Id $PSAwaitProcess.Id -ErrorAction SilentlyContinue } $Counter = 0 while ([bool]$(Get-Process -Id $PSAwaitProcess.Id -ErrorAction SilentlyContinue) -and $Counter -le 15) { Write-Verbose "Waiting for Await Module Process Id $($PSAwaitProcess.Id) to end..." Start-Sleep -Seconds 1 $Counter++ } } } } } if (!$(Test-Path "$HOME\.ssh\$NewSSHKeyName")) { Write-Error "ssh-keygen did not successfully create the public/private keypair! Halting!" $global:FunctionResult = "1" return } else { $ExistingSSHPrivateKeyPath = "$HOME\.ssh\$NewSSHKeyName" } } } $null = git config core.sshCommand "ssh -i $([regex]::Escape($ExistingSSHPrivateKeyPath)) -F /dev/null" 2>&1 $env:GIT_SSH_COMMAND = "ssh -i $([regex]::Escape($ExistingSSHPrivateKeyPath))" # Check To Make Sure Online GitHub Account is aware of Existing Public Key $GitHubAuthSuccess = Test-GitAuthentication -GitHubUserName $GitHubUserName -AuthMethod $AuthMethod -ExistingSSHPrivateKeyPath $ExistingSSHPrivateKeyPath if (!$GitHubAuthSuccess) { Write-Host "" Write-Host "GitHub Authentication was successfully configured on the client machine, however, we were not able to successfully authenticate to GitHub using '$ExistingSSHPrivateKeyPath'" Write-Host "Please add '$HOME\.ssh\$ExistingSSHPrivateKeyPath.pub' to your GitHub Account via Web Browser by:" Write-Host " 1) Navigating to Settings" Write-Host " 2) In the user settings sidebar, click SSH and GPG keys." Write-Host " 3) Add SSH Key" Write-Host " 4) Enter a descriptive Title like: SSH Key for Paul-MacBookPro auth" Write-Host " 5) Paste your key into the Key field." Write-Host " 6) Click Add SSH key." } else { $env:GitCmdLineConfigured = "True" } } ##### END Main Body ##### } |