Public/System/Set-VergeCertificate.ps1
|
function Set-VergeCertificate { <# .SYNOPSIS Modifies the configuration of a VergeOS SSL/TLS certificate. .DESCRIPTION Set-VergeCertificate modifies certificate settings such as description, domain list (SANs), keys (for manual certificates), and ACME settings (for Let's Encrypt certificates). .PARAMETER Certificate A certificate object from Get-VergeCertificate. Accepts pipeline input. .PARAMETER Key The key (ID) of the certificate to modify. .PARAMETER Description Set the certificate description. .PARAMETER DomainList Set additional domain names (Subject Alternative Names). Can be specified as an array or comma-separated string. .PARAMETER PublicKey Update the public certificate in PEM format (manual certificates only). .PARAMETER PrivateKey Update the private key in PEM format (manual certificates only). .PARAMETER Chain Update the certificate chain in PEM format (manual certificates only). .PARAMETER ACMEServer Update the ACME server URL (Let's Encrypt certificates only). .PARAMETER EABKeyId Update the External Account Binding Key ID. .PARAMETER EABHMACKey Update the External Account Binding HMAC Key. .PARAMETER KeyType Update the key type: ECDSA or RSA. .PARAMETER RSAKeySize Update the RSA key size: 2048, 3072, or 4096. .PARAMETER ContactUserId Update the contact user ID for Let's Encrypt certificates. .PARAMETER AgreeTOS Accept the Terms of Service (for Let's Encrypt certificates). .PARAMETER PassThru Return the modified certificate object. .PARAMETER Server The VergeOS connection to use. Defaults to the current default connection. .EXAMPLE Set-VergeCertificate -Key 1 -Description "Primary API certificate" Updates the description of a certificate. .EXAMPLE Get-VergeCertificate -Key 1 | Set-VergeCertificate -Description "Updated description" -PassThru Updates a certificate using pipeline input and returns the result. .EXAMPLE Set-VergeCertificate -Key 2 -DomainList "www.example.com","api.example.com" Updates the Subject Alternative Names for a certificate. .OUTPUTS None by default. Verge.Certificate when -PassThru is specified. .NOTES Some fields may be read-only depending on the certificate type. Changing keys on a manual certificate will require the new keys to be valid. #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium', DefaultParameterSetName = 'ByKey')] [OutputType([PSCustomObject])] param( [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'ByCertificate')] [PSTypeName('Verge.Certificate')] [PSCustomObject]$Certificate, [Parameter(Mandatory, ParameterSetName = 'ByKey')] [int]$Key, [Parameter()] [string]$Description, [Parameter()] [string[]]$DomainList, [Parameter()] [string]$PublicKey, [Parameter()] [string]$PrivateKey, [Parameter()] [string]$Chain, [Parameter()] [string]$ACMEServer, [Parameter()] [string]$EABKeyId, [Parameter()] [string]$EABHMACKey, [Parameter()] [ValidateSet('ECDSA', 'RSA')] [string]$KeyType, [Parameter()] [ValidateSet('2048', '3072', '4096')] [string]$RSAKeySize, [Parameter()] [int]$ContactUserId, [Parameter()] [switch]$AgreeTOS, [Parameter()] [switch]$PassThru, [Parameter()] [object]$Server ) begin { # Resolve connection if (-not $Server) { $Server = $script:DefaultConnection } if (-not $Server) { throw [System.InvalidOperationException]::new( 'Not connected to VergeOS. Use Connect-VergeOS to establish a connection.' ) } } process { # Resolve certificate based on parameter set $targetCert = switch ($PSCmdlet.ParameterSetName) { 'ByKey' { Get-VergeCertificate -Key $Key -Server $Server } 'ByCertificate' { $Certificate } } if (-not $targetCert) { Write-Error -Message "Certificate not found" -ErrorId 'CertificateNotFound' return } # Build the update body with only specified parameters $body = @{} $changes = [System.Collections.Generic.List[string]]::new() if ($PSBoundParameters.ContainsKey('Description')) { $body['description'] = $Description $changes.Add("Description updated") } if ($PSBoundParameters.ContainsKey('DomainList')) { $body['domainlist'] = $DomainList -join ',' $changes.Add("DomainList: $($DomainList -join ', ')") } if ($PSBoundParameters.ContainsKey('PublicKey')) { $body['public'] = $PublicKey $changes.Add("PublicKey updated") } if ($PSBoundParameters.ContainsKey('PrivateKey')) { $body['private'] = $PrivateKey $changes.Add("PrivateKey updated") } if ($PSBoundParameters.ContainsKey('Chain')) { $body['chain'] = $Chain $changes.Add("Chain updated") } if ($PSBoundParameters.ContainsKey('ACMEServer')) { $body['acme_server'] = $ACMEServer $changes.Add("ACMEServer: $ACMEServer") } if ($PSBoundParameters.ContainsKey('EABKeyId')) { $body['eab_kid'] = $EABKeyId $changes.Add("EABKeyId updated") } if ($PSBoundParameters.ContainsKey('EABHMACKey')) { $body['eab_hmac_key'] = $EABHMACKey $changes.Add("EABHMACKey updated") } if ($PSBoundParameters.ContainsKey('KeyType')) { $body['key_type'] = $KeyType.ToLower() $changes.Add("KeyType: $KeyType") } if ($PSBoundParameters.ContainsKey('RSAKeySize')) { $body['rsa_key_size'] = $RSAKeySize $changes.Add("RSAKeySize: $RSAKeySize") } if ($PSBoundParameters.ContainsKey('ContactUserId')) { $body['contact'] = $ContactUserId $changes.Add("ContactUserId: $ContactUserId") } if ($AgreeTOS) { $body['agree_tos'] = $true $changes.Add("AgreeTOS: True") } # Check if there are any changes to make if ($body.Count -eq 0) { Write-Warning "No changes specified for certificate '$($targetCert.Domain)'" if ($PassThru) { Write-Output $targetCert } return } # Build change summary for confirmation $changeSummary = $changes -join ', ' $certDisplay = "$($targetCert.Domain) (Key: $($targetCert.Key))" if ($PSCmdlet.ShouldProcess($certDisplay, "Modify Certificate ($changeSummary)")) { try { Write-Verbose "Modifying certificate '$($targetCert.Domain)' (Key: $($targetCert.Key))" Write-Verbose "Changes: $changeSummary" $null = Invoke-VergeAPI -Method PUT -Endpoint "certificates/$($targetCert.Key)" -Body $body -Connection $Server Write-Verbose "Certificate '$($targetCert.Domain)' modified successfully" if ($PassThru) { # Return the updated certificate Start-Sleep -Milliseconds 500 Get-VergeCertificate -Key $targetCert.Key -Server $Server } } catch { $errorMessage = $_.Exception.Message Write-Error -Message "Failed to modify certificate '$($targetCert.Domain)': $errorMessage" -ErrorId 'CertificateModifyFailed' } } } } |