Public/ssh-keypair.ps1
|
function Get-CSSSHKeyPair { <# .SYNOPSIS Lists registered SSH key pairs. .DESCRIPTION Wraps listSSHKeyPairs. CloudStack stores only the public key and its fingerprint; the private key is shown once, by New-CSSSHKeyPair. .PARAMETER Name Filter by key pair name .PARAMETER Id Filter by key pair ID .PARAMETER Fingerprint Filter by public key fingerprint .PARAMETER Keyword Filter by keyword .PARAMETER Account Filter by account name. Must be used with -DomainId. .PARAMETER DomainId Filter by domain ID .PARAMETER ProjectId Filter by project ID (-1 for all projects) .PARAMETER IsRecursive With -DomainId, also include key pairs in subdomains .PARAMETER ListAll List every key pair the caller is allowed to see .PARAMETER Page Page number of results to return .PARAMETER PageSize Number of results per page .EXAMPLE Get-CSSSHKeyPair Lists your key pairs. .EXAMPLE Get-CSSSHKeyPair -Name 'ops-laptop' Gets one key pair by name. .EXAMPLE Get-CSSSHKeyPair -ListAll | Group-Object fingerprint | Where-Object Count -gt 1 Finds the same public key registered more than once. #> [CmdletBinding()] param( [Parameter(Position = 0)] [string]$Name, [string]$Id, [string]$Fingerprint, [string]$Keyword, [string]$Account, [string]$DomainId, [string]$ProjectId, [switch]$IsRecursive, [switch]$ListAll, [int]$Page, [int]$PageSize ) if ($PSBoundParameters.ContainsKey('Account') -and -not $PSBoundParameters.ContainsKey('DomainId')) { throw 'DomainId is required when Account is specified.' } $apiParams = @{} Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{ Name = 'name'; Id = 'id'; Fingerprint = 'fingerprint'; Keyword = 'keyword'; Account = 'account' DomainId = 'domainid'; ProjectId = 'projectid'; IsRecursive = 'isrecursive'; ListAll = 'listall' Page = 'page'; PageSize = 'pagesize' }) ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'listSSHKeyPairs' -Parameters $apiParams) -Command 'listSSHKeyPairs' } function New-CSSSHKeyPair { <# .SYNOPSIS Has CloudStack generate a new SSH key pair. .DESCRIPTION Wraps createSSHKeyPair. CloudStack generates the key pair, keeps the public key, and returns the private key in the 'privatekey' property. That is the only time the private key is available, so save it straight away. To use a key you already have, use Register-CSSSHKeyPair instead. .PARAMETER Name The name of the key pair .PARAMETER Account Account that will own the key pair. Must be used with -DomainId. .PARAMETER DomainId Domain of the owning account .PARAMETER ProjectId Project that will own the key pair .EXAMPLE (New-CSSSHKeyPair -Name 'build-agents').privatekey | Set-Content -Path ./build-agents.pem -NoNewline Creates a key pair and saves the private key. On Linux/macOS, run 'chmod 600 ./build-agents.pem' before using it with ssh. .EXAMPLE New-CSSSHKeyPair -Name 'build-agents' -Account 'engineering' -DomainId domain-uuid Creates a key pair owned by another account. #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Low')] param( [Parameter(Mandatory = $true, Position = 0)] [string]$Name, [string]$Account, [string]$DomainId, [string]$ProjectId ) if ($PSBoundParameters.ContainsKey('Account') -and -not $PSBoundParameters.ContainsKey('DomainId')) { throw 'DomainId is required when Account is specified.' } $apiParams = @{ name = $Name } Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{ Account = 'account'; DomainId = 'domainid'; ProjectId = 'projectid' }) if ($PSCmdlet.ShouldProcess("SSH key pair $Name", 'Create')) { ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'createSSHKeyPair' -Parameters $apiParams) -Command 'createSSHKeyPair' } } function Register-CSSSHKeyPair { <# .SYNOPSIS Registers an existing SSH public key with CloudStack. .DESCRIPTION Wraps registerSSHKeyPair. Pass the key text with -PublicKey, or a .pub file with -PublicKeyPath. The key pair can then be used with New-CSVM -KeyPair or Reset-CSVMSSHKey. .PARAMETER Name The name to register the key under .PARAMETER PublicKey The public key text, e.g. 'ssh-ed25519 AAAA... user@host' .PARAMETER PublicKeyPath Path to a public key file, e.g. ~/.ssh/id_ed25519.pub .PARAMETER Account Account that will own the key pair. Must be used with -DomainId. .PARAMETER DomainId Domain of the owning account .PARAMETER ProjectId Project that will own the key pair .EXAMPLE Register-CSSSHKeyPair -Name 'ops-laptop' -PublicKeyPath ~/.ssh/id_ed25519.pub Registers your own public key. .EXAMPLE Register-CSSSHKeyPair -Name 'ci' -PublicKey $env:CI_SSH_PUBLIC_KEY -ProjectId project-uuid Registers a public key held in an environment variable for a project. #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Low', DefaultParameterSetName = 'Text')] param( [Parameter(Mandatory = $true, Position = 0)] [string]$Name, [Parameter(Mandatory = $true, ParameterSetName = 'Text')] [string]$PublicKey, [Parameter(Mandatory = $true, ParameterSetName = 'Path')] [string]$PublicKeyPath, [string]$Account, [string]$DomainId, [string]$ProjectId ) if ($PSBoundParameters.ContainsKey('Account') -and -not $PSBoundParameters.ContainsKey('DomainId')) { throw 'DomainId is required when Account is specified.' } if ($PSCmdlet.ParameterSetName -eq 'Path') { $resolvedPath = (Resolve-Path -Path $PublicKeyPath -ErrorAction Stop).ProviderPath $PublicKey = ([System.IO.File]::ReadAllText($resolvedPath)).Trim() # Guard against the classic mistake of pointing at the private key file. if ($PublicKey -match 'PRIVATE KEY') { throw "'$PublicKeyPath' holds a private key. Pass the matching .pub file instead." } } if ([string]::IsNullOrWhiteSpace($PublicKey)) { throw 'The public key is empty.' } $apiParams = @{ name = $Name; publickey = $PublicKey } Add-CSOptionalParameter -ApiParameters $apiParams -BoundParameters $PSBoundParameters -Map ([ordered]@{ Account = 'account'; DomainId = 'domainid'; ProjectId = 'projectid' }) if ($PSCmdlet.ShouldProcess("SSH key pair $Name", 'Register')) { ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'registerSSHKeyPair' -Parameters $apiParams) -Command 'registerSSHKeyPair' } } function Remove-CSSSHKeyPair { <# .SYNOPSIS Deletes an SSH key pair. .DESCRIPTION Wraps deleteSSHKeyPair. Key pairs are deleted by name, and names are only unique within an account, so a piped key pair also passes its account, domainid and projectid. That way an admin deleting another account's key cannot hit a same-named key of their own. VMs that already use the key keep it in their authorized_keys. .PARAMETER Name The name of the key pair (binds from a piped key pair's name) .PARAMETER Account The account that owns the key pair. Must be used with -DomainId. Binds from a piped key pair. .PARAMETER DomainId The domain of the owning account. Binds from a piped key pair. .PARAMETER ProjectId The project that owns the key pair. Binds from a piped key pair. .EXAMPLE Remove-CSSSHKeyPair -Name 'old-laptop' Deletes one of your key pairs after prompting for confirmation. .EXAMPLE Get-CSSSHKeyPair -ListAll -Keyword 'temp-' | Remove-CSSSHKeyPair -Confirm:$false Deletes every temporary key pair, whichever account owns it. #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] param( [Parameter(Mandatory = $true, Position = 0, ValueFromPipelineByPropertyName = $true)] [string]$Name, [Parameter(ValueFromPipelineByPropertyName = $true)] [string]$Account, [Parameter(ValueFromPipelineByPropertyName = $true)] [string]$DomainId, [Parameter(ValueFromPipelineByPropertyName = $true)] [string]$ProjectId ) process { $apiParams = @{ name = $Name } # A project's key pair is listed with the project's internal account too, # and CloudStack rejects account and projectid together, so the project wins. if (-not [string]::IsNullOrWhiteSpace($ProjectId)) { $apiParams['projectid'] = $ProjectId $owner = "project $ProjectId" } elseif (-not [string]::IsNullOrWhiteSpace($Account)) { if ([string]::IsNullOrWhiteSpace($DomainId)) { throw 'DomainId is required when Account is specified.' } $apiParams['account'] = $Account $apiParams['domainid'] = $DomainId $owner = "account $Account" } else { if (-not [string]::IsNullOrWhiteSpace($DomainId)) { $apiParams['domainid'] = $DomainId } $owner = 'your account' } if ($PSCmdlet.ShouldProcess("SSH key pair $Name ($owner)", 'Delete')) { ConvertFrom-CSResponse -Response (Invoke-CSApiRequest -Command 'deleteSSHKeyPair' -Parameters $apiParams) -Command 'deleteSSHKeyPair' } } } |