public/Get-PulpCertificate.ps1
# .ExternalHelp powershell-pulp-help.xml Function Get-PulpCertificate{ [Cmdletbinding()] Param( [Parameter(Mandatory=$false)] [string]$Server = (Get-PulpLocalConfig -Server).Server, [Parameter(Mandatory=$false)] [int]$Port = (Get-PulpLocalConfig -Port).Port, [Parameter(Mandatory=$false)] [string]$Protocol = (Get-PulpLocalConfig -Protocol).Protocol, [Parameter(Mandatory=$false)] [string]$Username = (Get-PulpLocalConfig -Username).Username, [Parameter(Mandatory=$false)] [switch]$Force ) $acctErr = "Error logging into ${Protocol}://${Server}:${Port}. "+ "Please check your username and password." $sslErr = "If your client computer does not trust the SSL certificate " + "presented by server ${server}, please trust this certificate or " + "try running: Set-PulpLocalConfig -SkipCertificateCheck" $uri = "${Protocol}://${Server}:${Port}/pulp/api/v2/actions/login/" $certFriendlyName = "Pulp on $server" if ($Env:OS -eq "Windows_NT") { $certStorePath = "Cert:\CurrentUser\My" } else { $certStorePath = "~\.pulp\certs" } # Windows: get relevant certs from the cert store if ($Env:OS -eq "Windows_NT") { $storedCertificates = (Get-ChildItem $certStorePath | Where-Object {$_.FriendlyName -eq $certFriendlyName} | Where-Object {$_.NotAfter -gt (Get-Date)} | Sort-Object NotAfter -Descending) } # Linux: Get cert from standard file else { $storedCertificates = @() If ((Test-Path "${certStorePath}\user-cert.pem")) { $pemArray = Get-Content "${certStorePath}\user-cert.pem" $certString = '' $keyString = '' $certStart = $false $keyStart = $false $certEnd = $false $keyEnd = $false foreach ($line in $pemArray) { if ($line -match '-----BEGIN RSA PRIVATE KEY-----') { $keyStart = $true } if ($line -match '-----BEGIN CERTIFICATE-----') { $certStart = $true } if ($keyStart -and !$keyEnd) { $keyString += "${line}`n" } if ($certStart -and !$certEnd) { $certString += "${line}`n" } if ($line -match '-----END RSA PRIVATE KEY-----') { $keyEnd = $true } if ($line -match '-----END CERTIFICATE-----') { $certEnd = $true } } $certBytes = [System.Convert]::FromBase64String( $certString.Substring( 28, $certString.Length - 55)) $keyBytes = [System.Convert]::FromBase64String( $keyString.Substring(32, $keyString.Length-63)) if (-not ([System.Management.Automation.PSTypeName]'PowershellPulp.Crypto2').Type) { Add-Type -TypeDefinition (Get-Content -Raw $PSScriptRoot\..\lib\powershell-pulp-main.cs) } $decodedKey = [PowershellPulp.Crypto2]::DecodeRSAPrivateKey($keyBytes) $certWithoutKey = New-Object ` System.Security.Cryptography.X509Certificates.X509Certificate2( $certBytes,'') $certificate = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::CopyWithPrivateKey($certWithoutKey, $decodedKey) if ($certificate.NotAfter -gt (Get-Date)) { $storedCertificates += $certificate } } } if (($storedCertificates.Count -gt 0) -and (!$Force)) { return $storedCertificates[0] } else { $config = Get-PulpLocalConfig $attempt = 0 while ((!$authResponse) -and ($attempt -lt 3)) { if (!$Password){ $credential = Get-Credential -user $Username -Message ` "Enter Pulp username and password to obtain certificate" If ($credential) { $Password = $credential.GetNetworkCredential().password $Username = $credential.UserName } } $base64Cred = [System.Convert]::ToBase64String( [Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $Username,$Password))) try { # PowerShell 5 if ($PSVersionTable.PSVersion.Major -lt 6) { if ((Get-PulpLocalConfig -SkipCertificateCheck).SkipCertificateCheck) { if (-not ([System.Management.Automation.PSTypeName]'PowershellPulp.SkipCertificateCheck').Type) { Add-Type -Path $PSScriptRoot\..\lib\powershell-pulp-skip.cs [System.Net.ServicePointManager]::CertificatePolicy = New-Object PowershellPulp.SkipCertificateCheck } } $authResponse = Invoke-RestMethod -Uri $uri -Method Post ` -Headers @{Authorization=("Basic {0}" -f $base64Cred)} ` -ErrorAction Stop } # PowerShell 6 else { if ((Get-PulpLocalConfig -SkipCertificateCheck).SkipCertificateCheck) { $authResponse = Invoke-RestMethod -Uri $uri -Method Post ` -Headers @{Authorization=("Basic {0}" -f $base64Cred)} ` -SkipCertificateCheck -ErrorAction Continue } else { $authResponse = Invoke-RestMethod -Uri $uri -Method Post ` -Headers @{Authorization=("Basic {0}" -f $base64Cred)} ` -ErrorAction Continue } } } catch { $attempt++ $Password = $null } } if (!$authResponse) { if ($Protocol -eq 'https') { Write-Error ($acctErr + " " + $sslErr) } else { Write-Error $acctErr } throw } # Windows: Convert and store returned cert and key in cert store if ($Env:OS -eq "Windows_NT") { $certBytes = [System.Convert]::FromBase64String( $authResponse.certificate.Substring( 28, $authResponse.certificate.Length - 55)) $keyBytes = [System.Convert]::FromBase64String( $authResponse.key.Substring(32, $authResponse.key.Length-63)) # PowerShell 5 if ($PSVersionTable.PSVersion.Major -lt 6) { if (-not ([System.Management.Automation.PSTypeName]'PowershellPulp.Crypto').Type) { Add-Type -Path $PSScriptRoot\..\lib\powershell-pulp-main.cs } $decodedKey = [PowershellPulp.Crypto]::DecodeRsaPrivateKey($keyBytes) $certificate = New-Object ` System.Security.Cryptography.X509Certificates.X509Certificate2( $certBytes,'') $certificate.FriendlyName = $certFriendlyName $certificate.PrivateKey = $decodedKey } # PowerShell 6 else { if (-not ([System.Management.Automation.PSTypeName]'PowershellPulp.Crypto2').Type) { Add-Type -TypeDefinition (Get-Content -Raw $PSScriptRoot\..\lib\powershell-pulp-main.cs) } $decodedKey = [PowershellPulp.Crypto2]::DecodeRSAPrivateKey($keyBytes) $certWithoutKey = New-Object ` System.Security.Cryptography.X509Certificates.X509Certificate2( $certBytes,'') $certWithoutKey.FriendlyName = $certFriendlyName $certificate = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::CopyWithPrivateKey($certWithoutKey, $decodedKey) } $certStore = Get-Item $certStorePath $certStore.Open('ReadWrite') $certStore.Add($certificate) } # Linux: Write returned cert and key directly to file else { if (!(Test-Path $certStorePath)) { $null = New-Item -Type Directory -Path $certStorePath -Force } $authResponse.key + $authResponse.certificate | Out-File -Encoding ASCII -NoNewLine "${certStorePath}\user-cert.pem" # Recursion! } return (Get-PulpCertificate -Server $Server -Port $Port ` -Protocol $Protocol -Username $Username) } } |