src/public/Security/Get-AitherSSHKey.ps1
|
#Requires -Version 7.0 <# .SYNOPSIS List and retrieve SSH key information .DESCRIPTION Lists SSH keys in the .ssh directory and retrieves information about them including fingerprints, key types, and public key content. Useful for managing multiple SSH keys and verifying which keys are available. .PARAMETER Name Optional name filter to find specific keys. Matches keys with this name in their filename. If not specified, returns all keys found in the .ssh directory. .PARAMETER KeyPath Directory to search for SSH keys. Default is ~/.ssh (or $env:USERPROFILE\.ssh on Windows). .PARAMETER PublicKeyOnly Return only public keys (skip private keys). Useful for listing keys you can share. .PARAMETER IncludeContent Include the full public key content in the output. Useful for copying keys to remote servers. .INPUTS System.String You can pipe key names to Get-AitherSSHKey. .OUTPUTS PSCustomObject Returns SSH key objects with properties: - Name: Key name identifier - PrivateKeyPath: Path to private key file - PublicKeyPath: Path to public key file - KeyType: Type of key (RSA, ED25519, etc.) - Fingerprint: SSH key fingerprint - Comment: Comment embedded in key - PublicKeyContent: Public key content (if -IncludeContent specified) - Created: File creation timestamp - Modified: File modification timestamp .EXAMPLE Get-AitherSSHKey Lists all SSH keys in the default .ssh directory. .EXAMPLE Get-AitherSSHKey -Name "production" Finds SSH keys with "production" in their name. .EXAMPLE Get-AitherSSHKey -IncludeContent Lists all keys and includes their public key content for easy copying. .EXAMPLE Get-AitherSSHKey -PublicKeyOnly Lists only public keys (skips private keys). .EXAMPLE "production", "github" | Get-AitherSSHKey Gets information for multiple keys by piping key names. .NOTES This cmdlet searches for SSH key files in the .ssh directory. It recognizes common SSH key naming patterns and extracts information from the key files themselves. .LINK New-AitherSSHKey Add-AitherSSHKey Remove-AitherSSHKey #> function Get-AitherSSHKey { [OutputType([PSCustomObject])] [CmdletBinding()] param( [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)] [AllowEmptyString()] [string]$Name, [string]$KeyPath, [switch]$PublicKeyOnly, [switch]$IncludeContent ) begin { # Determine default key path if (-not $KeyPath) { if ($IsWindows) { $KeyPath = Join-Path $env:USERPROFILE '.ssh' } else { $KeyPath = Join-Path $env:HOME '.ssh' } } } process { try { if (-not (Test-Path $KeyPath)) { Write-AitherLog -Level Warning -Message "SSH key directory not found: $KeyPath" -Source $PSCmdlet.MyInvocation.MyCommand.Name return @() } # Find SSH key files $keyFiles = Get-ChildItem -Path $KeyPath -File -ErrorAction SilentlyContinue | Where-Object { $_.Name -match '^(id_rsa|id_ed25519|id_ecdsa|id_dsa).*\.pub?$' -and (-not $PublicKeyOnly -or $_.Extension -eq '.pub') } $keys = @() $processedKeys = @{} foreach ($file in $keyFiles) { # Determine if this is a public or private key $isPublic = $file.Extension -eq '.pub' $baseName = if ($isPublic) { $file.BaseName } else { $file.Name } # Extract key name (everything after the key type prefix) $keyName = $null $keyType = $null if ($baseName -match '^(id_rsa|id_ed25519|id_ecdsa|id_dsa)(?:_(.+))?$') { $keyType = $matches[1] -replace '^id_', '' $keyName = if ($matches[2]) { $matches[2] } else { 'default' } } else { continue } # Filter by name if specified if ($Name -and $keyName -notlike "*$Name*") { continue } # Skip if we've already processed this key pair $keyId = "${keyType}_${keyName}" if ($processedKeys.ContainsKey($keyId)) { continue } $privateKeyPath = if ($isPublic) { $privatePath = Join-Path $KeyPath ($baseName -replace '\.pub$', '') if (Test-Path $privatePath) { $privatePath } else { $null } } else { $file.FullName } $publicKeyPath = if ($isPublic) { $file.FullName } else { $publicPath = "${file.FullName}.pub" if (Test-Path $publicPath) { $publicPath } else { $null } } # Get fingerprint and comment from public key $fingerprint = "Unknown" $comment = "" $publicKeyContent = "" if ($publicKeyPath -and (Test-Path $publicKeyPath)) { $publicKeyContent = Get-Content -Path $publicKeyPath -Raw -ErrorAction SilentlyContinue if ($publicKeyContent) { # Extract comment (everything after the second space) if ($publicKeyContent -match '^\S+\s+\S+\s+(.+)$') { $comment = $matches[1].Trim() } # Get fingerprint if (Get-Command ssh-keygen -ErrorAction SilentlyContinue) { $fingerprintOutput = & ssh-keygen -lf $publicKeyPath 2>&1 if ($fingerprintOutput -match '^\d+\s+([a-f0-9:]+)') { $fingerprint = $matches[1] } } } } $keyInfo = [PSCustomObject]@{ PSTypeName = 'AitherZero.SSHKey' Name = $keyName PrivateKeyPath = $privateKeyPath PublicKeyPath = $publicKeyPath KeyType = $keyType.ToUpper() Fingerprint = $fingerprint Comment = $comment Created = $file.CreationTime Modified = $file.LastWriteTime } if ($IncludeContent -and $publicKeyContent) { $keyInfo | Add-Member -NotePropertyName 'PublicKeyContent' -NotePropertyValue $publicKeyContent.Trim() } $keys += $keyInfo $processedKeys[$keyId] = $true } return $keys } catch { Invoke-AitherErrorHandler -ErrorRecord $_ -CmdletName $PSCmdlet.MyInvocation.MyCommand.Name -Operation "Getting SSH keys" -Parameters $PSBoundParameters -ThrowOnError } } } |