Skip to content

Commit 0581591

Browse files
Copy-DbaCredential: Add ExcludePassword (#10115)
1 parent 6260f82 commit 0581591

2 files changed

Lines changed: 38 additions & 31 deletions

File tree

public/Copy-DbaCredential.ps1

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ function Copy-DbaCredential {
5656
Specifies credential identities (user accounts) to exclude from the copy operation. Does not support wildcards for pattern matching.
5757
Use this when you want to copy most credentials but skip those associated with specific service accounts or domain users.
5858
59+
.PARAMETER ExcludePassword
60+
Copies credential definitions without the actual password values.
61+
Use this in security-conscious environments where password decryption is restricted or when passwords should be manually reset after migration.
62+
5963
.PARAMETER Force
6064
Overwrites existing credentials on the destination server by dropping and recreating them with the source values.
6165
Use this when you need to update credential passwords or identities that have changed on the source server since the last migration.
@@ -131,6 +135,7 @@ function Copy-DbaCredential {
131135
[string[]]$Identity,
132136
[Alias('ExcludeCredentialIdentity')]
133137
[string[]]$ExcludeIdentity,
138+
[switch]$ExcludePassword,
134139
[switch]$Force,
135140
[switch]$EnableException
136141
)
@@ -140,33 +145,30 @@ function Copy-DbaCredential {
140145
Stop-Function -Message "Copy-DbaCredential is only supported on Windows"
141146
return
142147
}
143-
$results = Test-ElevationRequirement -ComputerName $Source.ComputerName
144-
145-
if (-not $results) {
146-
return
147-
}
148148

149149
if ($Force) { $ConfirmPreference = 'none' }
150150

151151
try {
152-
Write-Message -Level Verbose -Message "We will try to open a dedicated admin connection."
153-
$sourceServer = Connect-DbaInstance -SqlInstance $Source -SqlCredential $SourceSqlCredential -MinimumVersion 9 -DedicatedAdminConnection -WarningAction SilentlyContinue
152+
if ($ExcludePassword) {
153+
Write-Message -Level Verbose -Message "Opening normal connection because we don't need the passwords."
154+
$sourceServer = Connect-DbaInstance -SqlInstance $Source -SqlCredential $SourceSqlCredential -MinimumVersion 9
155+
} else {
156+
Write-Message -Level Verbose -Message "Opening dedicated admin connection for password retrieval."
157+
$sourceServer = Connect-DbaInstance -SqlInstance $Source -SqlCredential $SourceSqlCredential -MinimumVersion 9 -DedicatedAdminConnection -WarningAction SilentlyContinue
158+
}
154159
} catch {
155160
Stop-Function -Message "Failure" -Category ConnectionError -ErrorRecord $_ -Target $Source
156161
return
157162
}
158-
Invoke-SmoCheck -SqlInstance $sourceServer
159163

160-
if ($null -ne $SourceSqlCredential.Username) {
161-
Write-Message -Level Verbose -Message "You are using SQL credentials and this script requires Windows admin access to the $Source server. Trying anyway."
162-
}
163-
164-
Write-Message -Level Verbose -Message "Decrypting all Credential logins and passwords on $($sourceServer.Name)"
165-
try {
166-
$decryptedCredentials = Get-DecryptedObject -SqlInstance $sourceServer -Type Credential -EnableException
167-
} catch {
168-
Stop-Function -Message "Failed to decrypt credentials on $($sourceServer.Name)" -ErrorRecord $_
169-
return
164+
if (-not $ExcludePassword) {
165+
Write-Message -Level Verbose -Message "Decrypting all Credential logins and passwords on $($sourceServer.Name)"
166+
try {
167+
$decryptedCredentials = Get-DecryptedObject -SqlInstance $sourceServer -Type Credential -EnableException
168+
} catch {
169+
Stop-Function -Message "Failed to decrypt credentials on $($sourceServer.Name)" -ErrorRecord $_
170+
return
171+
}
170172
}
171173

172174
Write-Message -Level Verbose -Message "Getting all Credentials that should be processed on $($sourceServer.Name)"
@@ -181,7 +183,6 @@ function Copy-DbaCredential {
181183
} catch {
182184
Stop-Function -Message "Failure" -Category ConnectionError -ErrorRecord $_ -Target $destinstance -Continue
183185
}
184-
Invoke-SmoCheck -SqlInstance $destServer
185186

186187
Write-Message -Level Verbose -Message "Starting migration"
187188
$destServer.Credentials.Refresh()
@@ -222,24 +223,27 @@ function Copy-DbaCredential {
222223

223224
Write-Message -Level Verbose -Message "Attempting to migrate $credentialName"
224225
try {
225-
$decryptedCred = $decryptedCredentials | Where-Object { $_.Name -eq $credentialName }
226-
$sqlcredentialName = $decryptedCred.Quotename
227-
$identity = $decryptedCred.Identity.Replace("'", "''")
228-
$password = $decryptedCred.Password.Replace("'", "''")
229-
230-
if ($cred.MappedClassType -eq "CryptographicProvider") {
226+
$splatNewCredential = @{
227+
SqlInstance = $destServer
228+
Name = $cred.Name
229+
Identity = $cred.Identity
230+
MappedClassType = $cred.MappedClassType
231+
EnableException = $true
232+
}
233+
if ($cred.mappedClassType -eq "CryptographicProvider") {
231234
$cryptoConfiguredOnDestination = $destServer.Query("SELECT is_enabled FROM sys.cryptographic_providers WHERE name = '$($cred.ProviderName)'")
232-
233235
if (-not $cryptoConfiguredOnDestination.is_enabled) {
234236
throw "The cryptographic provider $($cred.ProviderName) needs to be configured and enabled on $destServer"
235-
} else {
236-
$cryptoSQL = " FOR CRYPTOGRAPHIC PROVIDER $($cred.ProviderName) "
237237
}
238+
$splatNewCredential.ProviderName = $cred.ProviderName
239+
}
240+
if (-not $ExcludePassword) {
241+
$decryptedCred = $decryptedCredentials | Where-Object { $_.Name -eq $credentialName }
242+
$splatNewCredential.SecurePassword = ConvertTo-SecureString -String $decryptedCred.Password -AsPlainText -Force
238243
}
239244

240245
if ($Pscmdlet.ShouldProcess($destinstance, "Copying $identity ($credentialName)")) {
241-
$destServer.Query("CREATE CREDENTIAL $sqlcredentialName WITH IDENTITY = N'$identity', SECRET = N'$password' $cryptoSQL")
242-
$destServer.Credentials.Refresh()
246+
$null = New-DbaCredential @splatNewCredential
243247
Write-Message -Level Verbose -Message "$credentialName successfully copied"
244248
$copyCredentialStatus.Status = "Successful"
245249
$copyCredentialStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject
@@ -257,6 +261,8 @@ function Copy-DbaCredential {
257261
end {
258262
# Disconnect is important because it is a DAC
259263
# Disconnect in case of WhatIf, as we opened the connection
260-
$null = $sourceServer | Disconnect-DbaInstance -WhatIf:$false
264+
if (-not $ExcludePassword) {
265+
$null = $sourceServer | Disconnect-DbaInstance -WhatIf:$false
266+
}
261267
}
262268
}

tests/Copy-DbaCredential.Tests.ps1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Describe $CommandName -Tag UnitTests {
2020
"ExcludeName",
2121
"Identity",
2222
"ExcludeIdentity",
23+
"ExcludePassword",
2324
"Force",
2425
"EnableException"
2526
)

0 commit comments

Comments
 (0)