From dcf00d77865e232be1c468e3f2e05168b868f41a Mon Sep 17 00:00:00 2001 From: Simone Bizzotto Date: Mon, 24 Feb 2025 14:26:26 +0100 Subject: [PATCH] Backup-DbaDbCertificate, new FileBaseName parameter (#9597) --- public/Backup-DbaDbCertificate.ps1 | 19 +++++++++++++------ tests/Backup-DbaDbCertificate.Tests.ps1 | 11 +++++++++++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/public/Backup-DbaDbCertificate.ps1 b/public/Backup-DbaDbCertificate.ps1 index a70bf88272..3ac036143b 100644 --- a/public/Backup-DbaDbCertificate.ps1 +++ b/public/Backup-DbaDbCertificate.ps1 @@ -37,6 +37,10 @@ function Backup-DbaDbCertificate { .PARAMETER Suffix The suffix of the filename of the exported certificate. + .PARAMETER FileBaseName + Override the default naming convention with a fixed name for the certificate and private key file name, useful when exporting a single certificate. + ".cer" will be appended to the certificate file name and ".pvk" will be appended to the private key file name. + .PARAMETER InputObject Enables piping from Get-DbaDbCertificate @@ -131,6 +135,7 @@ function Backup-DbaDbCertificate { [Security.SecureString]$DecryptionPassword, [System.IO.FileInfo]$Path, [string]$Suffix, + [string]$FileBaseName, [parameter(ValueFromPipeline, ParameterSetName = "collection")] [Microsoft.SqlServer.Management.Smo.Certificate[]]$InputObject, [switch]$EnableException @@ -140,7 +145,6 @@ function Backup-DbaDbCertificate { if (-not $EncryptionPassword -and $DecryptionPassword) { Stop-Function -Message "If you specify a decryption password, you must also specify an encryption password" -Target $DecryptionPassword } - $time = Get-Date -Format yyyMMddHHmmss function export-cert ($cert) { $certName = $cert.Name @@ -164,14 +168,21 @@ function Backup-DbaDbCertificate { } $fileinstance = $instance.ToString().Replace('\', '$') - $fullCertName = Join-DbaPath -SqlInstance $server -Path $actualPath -ChildPath "$fileinstance-$dbname-$certName$Suffix" + $targetBaseName = "$fileinstance-$dbname-$certName$Suffix" + if ($FileBaseName) { + $targetBaseName = $FileBaseName + } + $fullCertName = Join-DbaPath -SqlInstance $server -Path $actualPath -ChildPath $targetBaseName # if the base file name exists, then default to old style of appending a timestamp if (Test-DbaPath -SqlInstance $server -Path "$fullCertName.cer") { if ($Suffix) { Stop-Function -Message "$fullCertName.cer already exists on $($server.Name)" -Target $actualPath -Continue } else { + $time = Get-Date -Format yyyyMMddHHmmss $fullCertName = "$fullCertName-$time" + # Sleep for a second to avoid another export in the same second + Start-Sleep -Seconds 1 } } @@ -180,7 +191,6 @@ function Backup-DbaDbCertificate { if ($Pscmdlet.ShouldProcess($instance, "Exporting certificate $certName from $db on $instance to $actualPath")) { Write-Message -Level Verbose -Message "Exporting Certificate: $certName to $fullCertName" try { - $exportPathCert = "$fullCertName.cer" # because the password shouldn't go to memory... @@ -208,9 +218,6 @@ function Backup-DbaDbCertificate { $cert.export($exportPathCert) } - # Sleep for a second to avoid another export in the same second - Start-Sleep -Seconds 1 - [PSCustomObject]@{ ComputerName = $server.ComputerName InstanceName = $server.ServiceName diff --git a/tests/Backup-DbaDbCertificate.Tests.ps1 b/tests/Backup-DbaDbCertificate.Tests.ps1 index 3957909fdd..f54bd26da0 100644 --- a/tests/Backup-DbaDbCertificate.Tests.ps1 +++ b/tests/Backup-DbaDbCertificate.Tests.ps1 @@ -19,6 +19,7 @@ Describe "Backup-DbaDbCertificate" -Tag "UnitTests" { "DecryptionPassword", "Path", "Suffix", + "FileBaseName", "InputObject", "EnableException", "Confirm", @@ -63,6 +64,15 @@ Describe "Backup-DbaDbCertificate" -Tag "IntegrationTests" { $results.DatabaseID | Should -Be (Get-DbaDatabase -SqlInstance $TestConfig.instance1 -Database $db1Name).ID } + It "backs up the db cert with a filename (see #9485)" { + $results = Backup-DbaDbCertificate -SqlInstance $TestConfig.instance1 -Certificate $cert.Name -Database $db1Name -EncryptionPassword $pw -DecryptionPassword $pw -FileBaseName "dbatoolscli_cert1_$random" + $results.Certificate | Should -Be $cert.Name + $results.Status | Should -Match "Success" + $results.DatabaseID | Should -Be (Get-DbaDatabase -SqlInstance $TestConfig.instance1 -Database $db1Name).ID + [IO.Path]::GetFileNameWithoutExtension($results.Path) | Should -Be "dbatoolscli_cert1_$random" + $null = Get-ChildItem -Path $results.Path -ErrorAction Ignore | Remove-Item -Confirm:$false -ErrorAction Ignore + } + It "warns the caller if the cert cannot be found" { $invalidDBCertName = "dbatoolscli_invalidCertName" $invalidDBCertName2 = "dbatoolscli_invalidCertName2" @@ -82,5 +92,6 @@ Describe "Backup-DbaDbCertificate" -Tag "IntegrationTests" { $results = Backup-DbaDbCertificate -SqlInstance $TestConfig.instance1 -EncryptionPassword $pw $null = Get-ChildItem -Path $results.Path -ErrorAction Ignore | Remove-Item -Confirm:$false -ErrorAction Ignore } + } }