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-DbaServiceMasterKey, add FileBaseName parameter #9598

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
30 changes: 21 additions & 9 deletions public/Backup-DbaServiceMasterKey.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@ function Backup-DbaServiceMasterKey {

For MFA support, please use Connect-DbaInstance.

.PARAMETER KeyCredential
Pass a credential object for the password

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

.PARAMETER KeyCredential
Pass a credential object for the password
.PARAMETER FileBaseName
Override the default naming convention with a fixed name for the service master key, useful when exporting a single one.
".key" will be appended to the filename.

.PARAMETER SecurePassword
The password to encrypt the exported key. This must be a SecureString.
Expand Down Expand Up @@ -72,13 +76,13 @@ function Backup-DbaServiceMasterKey {
[Alias("Password")]
[Security.SecureString]$SecurePassword,
[string]$Path,
[string]$FileBaseName,
[switch]$EnableException
)
begin {
if ($KeyCredential) {
$SecurePassword = $KeyCredential.Password
}
$time = Get-Date -Format yyyMMddHHmmss
}
process {
foreach ($instance in $SqlInstance) {
Expand Down Expand Up @@ -116,16 +120,24 @@ function Backup-DbaServiceMasterKey {
$Path = $Path.TrimEnd("\")
$Path = $Path.TrimEnd("/")
$fileinstance = $instance.ToString().Replace('\', '$')
$filename = Join-DbaPath -SqlInstance $server -Path $Path -ChildPath "$fileinstance-servicemasterkey.key"
$targetBaseName = "$fileinstance-servicemasterkey"
if ($FileBaseName) {
$targetBaseName = $FileBaseName
}

$exportFileName = Join-DbaPath -SqlInstance $server -Path $Path -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 $Path -ChildPath "$fileinstance-servicemasterkey-$time.key"
if (Test-DbaPath -SqlInstance $server -Path $exportFileName) {
$time = Get-Date -Format yyyyMMddHHmmss
$exportFileName = Join-DbaPath -SqlInstance $server -Path $Path -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 service master key to $filename")) {
if ($Pscmdlet.ShouldProcess($instance, "Backing up service master key to $exportFileName")) {
try {
$masterkey.Export($filename, ($SecurePassword | ConvertFrom-SecurePass))
$masterkey.Export($exportFileName, ($SecurePassword | ConvertFrom-SecurePass))
$status = "Success"
} catch {
$status = "Failure"
Expand All @@ -135,7 +147,7 @@ function Backup-DbaServiceMasterKey {
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 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, 'Filename as Path', Status
Expand Down
10 changes: 9 additions & 1 deletion tests/Backup-DbaServiceMasterKey.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Describe "Backup-DbaServiceMasterKey" -Tag "UnitTests" {
"KeyCredential",
"SecurePassword",
"Path",
"FileBaseName",
"EnableException",
"Confirm",
"WhatIf"
Expand All @@ -36,14 +37,21 @@ Describe "Backup-DbaServiceMasterKey" -Tag "IntegrationTests" {
Context "Can backup a service master key" {
BeforeAll {
$securePassword = ConvertTo-SecureString -String "GoodPass1234!" -AsPlainText -Force
$results = Backup-DbaServiceMasterKey -SqlInstance $TestConfig.instance1 -SecurePassword $securePassword -Confirm:$false
}

AfterAll {
$null = Remove-Item -Path $results.Path -ErrorAction SilentlyContinue -Confirm:$false
}

It "backs up the SMK" {
$results = Backup-DbaServiceMasterKey -SqlInstance $TestConfig.instance1 -SecurePassword $securePassword -Confirm:$false
$results.Status | Should -Be "Success"
}

It "backs up the SMK with a specific filename (see #9483)" {
$random = Get-Random
$results = Backup-DbaServiceMasterKey -SqlInstance $TestConfig.instance1 -SecurePassword $securePassword -FileBaseName "smk($random)" -Confirm:$false
[IO.Path]::GetFileNameWithoutExtension($results.Path) | Should -Be "smk($random)"
$results.Status | Should -Be "Success"
}
}
Expand Down