Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backup-DbaDbMasterKey, add FileBaseName #9599

Merged
merged 1 commit into from
Feb 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 24 additions & 15 deletions public/Backup-DbaDbMasterKey.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,24 @@ function Backup-DbaDbMasterKey {

For MFA support, please use Connect-DbaInstance.

.PARAMETER Credential
Pass a credential object for the password

.PARAMETER Database
Backup master key from specific database(s).

.PARAMETER ExcludeDatabase
The database(s) to exclude - this list is auto-populated from the server.

.PARAMETER SecurePassword
The password to encrypt the exported key. This must be a SecureString.

.PARAMETER Path
The directory to export the key. If no path is specified, the default backup directory for the instance will be used.

.PARAMETER Credential
Pass a credential object for the password

.PARAMETER SecurePassword
The password to encrypt the exported key. This must be a SecureString.
.PARAMETER FileBaseName
Override the default naming convention with a fixed name for the database master key, useful when exporting a single one.
".key" will be appended to the filename.

.PARAMETER InputObject
Database object piped in from Get-DbaDatabase
Expand Down Expand Up @@ -82,6 +86,7 @@ function Backup-DbaDbMasterKey {
[Alias("Password")]
[Security.SecureString]$SecurePassword,
[string]$Path,
[string]$FileBaseName,
[parameter(ValueFromPipeline)]
[Microsoft.SqlServer.Management.Smo.Database[]]$InputObject,
[switch]$EnableException
Expand All @@ -90,7 +95,6 @@ function Backup-DbaDbMasterKey {
if ($Credential) {
$SecurePassword = $Credential.Password
}
$time = Get-Date -Format yyyMMddHHmmss
}
process {
foreach ($instance in $SqlInstance) {
Expand Down Expand Up @@ -144,31 +148,36 @@ function Backup-DbaDbMasterKey {
}

$fileinstance = $instance.ToString().Replace('\', '$')
$filename = Join-DbaPath -SqlInstance $server -Path $actualPath -ChildPath "$fileinstance-$dbname-masterkey.key"
$targetBaseName = "$fileinstance-$dbname-masterkey"
if ($FileBaseName) {
$targetBaseName = $FileBaseName
}

$exportFileName = Join-DbaPath -SqlInstance $server -Path $actualPath -ChildPath "$targetBaseName.key"

# if the base file name exists, then default to old style of appending a timestamp
if (Test-DbaPath -SqlInstance $server -Path $filename) {
$filename = Join-DbaPath -SqlInstance $server -Path $actualPath -ChildPath "$fileinstance-$dbname-masterkey-$time.key"
if (Test-DbaPath -SqlInstance $server -Path $exportFileName) {
$time = Get-Date -Format yyyMMddHHmmss
$exportFileName = Join-DbaPath -SqlInstance $server -Path $actualPath -ChildPath "$targetBaseName-$time.key"
# Sleep for a second to avoid another export in the same second
Start-Sleep -Seconds 1
}

if ($Pscmdlet.ShouldProcess($instance, "Backing up master key to $filename")) {
if ($Pscmdlet.ShouldProcess($instance, "Backing up master key to $exportFileName")) {
try {
$masterkey.Export($filename, ($SecurePassword | ConvertFrom-SecurePass))
$masterkey.Export($exportFileName, ($SecurePassword | ConvertFrom-SecurePass))
$status = "Success"
} catch {
$status = "Failure"
Write-Message -Level Warning -Message "Backup failure: $($_.Exception.InnerException)"
}

# Sleep for a second to avoid another export in the same second
Start-Sleep -Seconds 1

Add-Member -Force -InputObject $masterkey -MemberType NoteProperty -Name ComputerName -value $server.ComputerName
Add-Member -Force -InputObject $masterkey -MemberType NoteProperty -Name InstanceName -value $server.ServiceName
Add-Member -Force -InputObject $masterkey -MemberType NoteProperty -Name SqlInstance -value $server.DomainInstanceName
Add-Member -Force -InputObject $masterkey -MemberType NoteProperty -Name Database -value $dbName
Add-Member -Force -InputObject $masterkey -MemberType NoteProperty -Name DatabaseID -value $db.ID
Add-Member -Force -InputObject $masterkey -MemberType NoteProperty -Name Filename -value $filename
Add-Member -Force -InputObject $masterkey -MemberType NoteProperty -Name Filename -value $exportFileName
Add-Member -Force -InputObject $masterkey -MemberType NoteProperty -Name Status -value $status

Select-DefaultView -InputObject $masterkey -Property ComputerName, InstanceName, SqlInstance, Database, 'Filename as Path', Status
Expand Down
29 changes: 24 additions & 5 deletions tests/Backup-DbaDbMasterKey.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Describe "Backup-DbaDbMasterKey" -Tag "UnitTests" {
"ExcludeDatabase",
"SecurePassword",
"Path",
"FileBaseName",
"InputObject",
"EnableException",
"WhatIf",
Expand Down Expand Up @@ -45,27 +46,45 @@ Describe "Backup-DbaDbMasterKey" -Tag "IntegrationTests" {
if (-not (Get-DbaDbMasterKey -SqlInstance $instance -Database $database)) {
$null = New-DbaDbMasterKey -SqlInstance $instance -Database $database -Password $password -Confirm:$false
}
}

AfterAll {
Get-DbaDbMasterKey -SqlInstance $instance -Database $database | Remove-DbaDbMasterKey -Confirm:$false
}

It "Backs up the database master key" {
$splatBackup = @{
SqlInstance = $instance
Database = $database
SecurePassword = $password
Confirm = $false
}
}
$results = Backup-DbaDbMasterKey @splatBackup
$results | Should -Not -BeNullOrEmpty
$results.Database | Should -Be $database
$results.Status | Should -Be "Success"
$results.DatabaseID | Should -Be (Get-DbaDatabase -SqlInstance $instance -Database $database).ID

AfterAll {
Get-DbaDbMasterKey -SqlInstance $instance -Database $database | Remove-DbaDbMasterKey -Confirm:$false
$null = Remove-Item -Path $results.Path -ErrorAction SilentlyContinue -Confirm:$false
}

It "Backs up the database master key" {
It "Backs up the database master key with a specific filename (see #9484)" {
$random = Get-Random
$splatBackup = @{
SqlInstance = $instance
Database = $database
SecurePassword = $password
FileBaseName = "dbatoolscli_dbmasterkey_$random"
Confirm = $false
}
$results = Backup-DbaDbMasterKey @splatBackup
$results | Should -Not -BeNullOrEmpty
$results.Database | Should -Be $database
$results.Status | Should -Be "Success"
$results.DatabaseID | Should -Be (Get-DbaDatabase -SqlInstance $instance -Database $database).ID

[IO.Path]::GetFileNameWithoutExtension($results.Path) | Should -Be "dbatoolscli_dbmasterkey_$random"
$null = Remove-Item -Path $results.Path -ErrorAction SilentlyContinue -Confirm:$false
}

}
}