Skip to content

Commit 60adce3

Browse files
authored
Add New-AzDataMigrationTdeCertificateMigration Cmdlet (Azure#21346)
* Added New-AzDataMigrationTdeCertificateMigration * Export New-AzDataMigrationTdeCertificateMigration * Add generated files * Added unit test * Removed SupportsShouldProcess * Support multiple database names * Updated documentation * Added example * Added support for TDE Console App NuGet * Extract latest NuGet * Download latest version of NuGet from NuGet.org * Added error handling logic * Changed parameter type * Updated example and documentation * Handle case of unsuccessful NuGet upgrades * Added support for ShouldProcess * Use SecureString
1 parent 79bbf7c commit 60adce3

File tree

6 files changed

+537
-1
lines changed

6 files changed

+537
-1
lines changed

src/DataMigration/DataMigration.Autorest/Az.DataMigration.psd1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
DotNetFrameworkVersion = '4.7.2'
1212
RequiredAssemblies = './bin/Az.DataMigration.private.dll'
1313
FormatsToProcess = './Az.DataMigration.format.ps1xml'
14-
FunctionsToExport = 'Get-AzDataMigrationAssessment', 'Get-AzDataMigrationPerformanceDataCollection', 'Get-AzDataMigrationSkuRecommendation', 'Get-AzDataMigrationSqlService', 'Get-AzDataMigrationSqlServiceAuthKey', 'Get-AzDataMigrationSqlServiceIntegrationRuntimeMetric', 'Get-AzDataMigrationSqlServiceMigration', 'Get-AzDataMigrationToSqlDb', 'Get-AzDataMigrationToSqlManagedInstance', 'Get-AzDataMigrationToSqlVM', 'Invoke-AzDataMigrationCutoverToSqlManagedInstance', 'Invoke-AzDataMigrationCutoverToSqlVM', 'New-AzDataMigrationLoginsMigration', 'New-AzDataMigrationSqlService', 'New-AzDataMigrationSqlServiceAuthKey', 'New-AzDataMigrationToSqlDb', 'New-AzDataMigrationToSqlManagedInstance', 'New-AzDataMigrationToSqlVM', 'Register-AzDataMigrationIntegrationRuntime', 'Remove-AzDataMigrationSqlService', 'Remove-AzDataMigrationSqlServiceNode', 'Remove-AzDataMigrationToSqlDb', 'Stop-AzDataMigrationToSqlDb', 'Stop-AzDataMigrationToSqlManagedInstance', 'Stop-AzDataMigrationToSqlVM', 'Update-AzDataMigrationSqlService', '*'
14+
FunctionsToExport = 'Get-AzDataMigrationAssessment', 'Get-AzDataMigrationPerformanceDataCollection', 'Get-AzDataMigrationSkuRecommendation', 'Get-AzDataMigrationSqlService', 'Get-AzDataMigrationSqlServiceAuthKey', 'Get-AzDataMigrationSqlServiceIntegrationRuntimeMetric', 'Get-AzDataMigrationSqlServiceMigration', 'Get-AzDataMigrationToSqlDb', 'Get-AzDataMigrationToSqlManagedInstance', 'Get-AzDataMigrationToSqlVM', 'Invoke-AzDataMigrationCutoverToSqlManagedInstance', 'Invoke-AzDataMigrationCutoverToSqlVM', 'New-AzDataMigrationLoginsMigration', 'New-AzDataMigrationTdeCertificateMigration','New-AzDataMigrationSqlService', 'New-AzDataMigrationSqlServiceAuthKey', 'New-AzDataMigrationToSqlDb', 'New-AzDataMigrationToSqlManagedInstance', 'New-AzDataMigrationToSqlVM', 'Register-AzDataMigrationIntegrationRuntime', 'Remove-AzDataMigrationSqlService', 'Remove-AzDataMigrationSqlServiceNode', 'Remove-AzDataMigrationToSqlDb', 'Stop-AzDataMigrationToSqlDb', 'Stop-AzDataMigrationToSqlManagedInstance', 'Stop-AzDataMigrationToSqlVM', 'Update-AzDataMigrationSqlService', '*'
1515
AliasesToExport = '*'
1616
PrivateData = @{
1717
PSData = @{
Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
2+
# ----------------------------------------------------------------------------------
3+
#
4+
# Copyright Microsoft Corporation
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
# ----------------------------------------------------------------------------------
15+
<#
16+
.Synopsis
17+
Migrate TDE certificate(s) from source SQL Server to the target Azure SQL Server.
18+
.Description
19+
Migrate TDE certificate(s) from source SQL Server to the target Azure SQL Server.
20+
#>
21+
22+
23+
function New-AzDataMigrationTdeCertificateMigration
24+
{
25+
[OutputType([System.Boolean])]
26+
[CmdletBinding(PositionalBinding=$false, SupportsShouldProcess, ConfirmImpact='Medium')]
27+
[Microsoft.Azure.PowerShell.Cmdlets.DataMigration.Description('Migrate TDE certificate(s) from source SQL Server to the target Azure SQL Server.')]
28+
29+
param(
30+
[Parameter(ParameterSetName='CommandLine', Mandatory, HelpMessage='Required. Connection string for the source SQL instance, using the formal connection string format.')]
31+
[SecureString]
32+
${SourceSqlConnectionString},
33+
34+
[Parameter(ParameterSetName='CommandLine', Mandatory, HelpMessage='Subscription Id of the target Azure SQL server.')]
35+
[System.String]
36+
${TargetSubscriptionId},
37+
38+
[Parameter(ParameterSetName='CommandLine', Mandatory, HelpMessage='Resource group name of the target Azure SQL server.')]
39+
[System.String]
40+
${TargetResourceGroupName},
41+
42+
[Parameter(ParameterSetName='CommandLine', Mandatory, HelpMessage='Name of the Azure SQL Server.')]
43+
[System.String]
44+
${TargetManagedInstanceName},
45+
46+
[Parameter(ParameterSetName='CommandLine', Mandatory, HelpMessage='Network share path.')]
47+
[System.String]
48+
${NetworkSharePath},
49+
50+
[Parameter(ParameterSetName='CommandLine', Mandatory, HelpMessage='Network share domain.')]
51+
[System.String]
52+
${NetworkShareDomain},
53+
54+
[Parameter(ParameterSetName='CommandLine', HelpMessage='Network share user name.')]
55+
[System.String]
56+
${NetworkShareUserName},
57+
58+
[Parameter(ParameterSetName='CommandLine', HelpMessage='Network share password.')]
59+
[SecureString]
60+
${NetworkSharePassword},
61+
62+
[Parameter(ParameterSetName='CommandLine', Mandatory, HelpMessage='Source database name.')]
63+
[System.String[]]
64+
${DatabaseName},
65+
66+
[Parameter()]
67+
[Microsoft.Azure.PowerShell.Cmdlets.DataMigration.Category('Runtime')]
68+
[System.Management.Automation.SwitchParameter]
69+
# Returns true when the command succeeds
70+
${PassThru}
71+
)
72+
73+
process
74+
{
75+
try {
76+
if($PSCmdlet.ShouldProcess("Migrate TDE certificate(s) from source SQL Server.") -eq $false)
77+
{
78+
return;
79+
}
80+
81+
$OSPlatform = Get-OSName
82+
83+
if(-Not $OSPlatform.Contains("Windows"))
84+
{
85+
throw "This command cannot be run in non-windows environment"
86+
Break;
87+
}
88+
89+
#Defining Default Output Path
90+
$DefaultOutputFolder = Get-DefaultTdeMigrationsOutputFolder
91+
92+
#Determine latest version of TDE console app
93+
$PackageId = "Microsoft.SqlServer.Migration.TdeConsoleApp"
94+
95+
$AvailablePackagesOnNugetOrg = ""
96+
97+
try {
98+
$AvailablePackagesOnNugetOrg = Find-Package -Source "https://api.nuget.org/v3/index.json" -Name $PackageId -AllowPrereleaseVersions -AllVersions
99+
$AvailablePackagesOnNugetOrg = $AvailablePackagesOnNugetOrg | Sort-Object -Property Version -Descending
100+
} catch {
101+
Write-Host "Unable to connect to NuGet.org to check for updates."
102+
}
103+
104+
$LatestNugetOrgName = $AvailablePackagesOnNugetOrg[0].Name
105+
$LatestNugetOrgVersion = $AvailablePackagesOnNugetOrg[0].Version
106+
$LatestNugetOrgNameAndVersion = "$LatestNugetOrgName.$LatestNugetOrgVersion";
107+
108+
$DownloadsFolder = Join-Path -Path $DefaultOutputFolder -ChildPath "Downloads"
109+
if(-Not (Test-Path $DownloadsFolder))
110+
{
111+
$null = New-Item -Path $DownloadsFolder -ItemType "directory";
112+
}
113+
114+
$ConsoleAppFolders = Get-ChildItem -Path $DownloadsFolder -Filter "$PackageId.*"
115+
$LatestLocalNameAndVersion = ""
116+
if ($ConsoleAppFolders.Length -gt 0)
117+
{
118+
$ConsoleAppFolders = $ConsoleAppFolders | Sort-Object -Property Name -Descending
119+
$LatestLocalNameAndVersion = $ConsoleAppFolders[0].Name
120+
121+
if ($AvailablePackagesOnNugetOrg -eq "")
122+
{
123+
$LatestNugetOrgNameAndVersion = $LatestLocalNameAndVersion
124+
}
125+
}
126+
else
127+
{
128+
#No local console app
129+
if ($AvailablePackagesOnNugetOrg -eq "")
130+
{
131+
#No version available to download
132+
Write-Host "Connection to NuGet.org required. Please check connection and try again."
133+
return;
134+
}
135+
}
136+
137+
$LatestNugetFolder = Join-Path -Path $DownloadsFolder -ChildPath $LatestNugetOrgNameAndVersion;
138+
$ExePath = "tools\Microsoft.SqlServer.Migration.Tde.ConsoleApp.exe";
139+
140+
if ($LatestNugetOrgNameAndVersion -gt $LatestLocalNameAndVersion)
141+
{
142+
#Update is available
143+
$DownloadUrl = "https://www.nuget.org/api/v2/package/$PackageId/$LatestNugetOrgVersion"
144+
145+
#Checking if LatestNugetFolder Path is valid or not
146+
if(-Not (Test-Path $LatestNugetFolder))
147+
{
148+
$null = New-Item -Path $LatestNugetFolder -ItemType "directory";
149+
}
150+
151+
Invoke-WebRequest $DownloadUrl -OutFile "$LatestNugetFolder\\$LatestNugetOrgName.$LatestNugetOrgVersion.nupkg"
152+
153+
$ToolsPathExists = Test-Path -Path (Join-Path -Path $LatestNugetFolder -ChildPath "tools");
154+
155+
if ($ToolsPathExists -eq $False)
156+
{
157+
$Nugets = Get-ChildItem -Path $LatestNugetFolder -Filter "$PackageId.*.nupkg";
158+
159+
if ($Nugets.Length -gt 0)
160+
{
161+
$Nugets = $Nugets | Sort-Object -Property Name -Descending;
162+
$LatestNugetPath = $Nugets[0].FullName;
163+
Expand-Archive -Path $LatestNugetPath -DestinationPath $LatestNugetFolder;
164+
}
165+
}
166+
167+
#Check if update was successful
168+
$TestPathResult = Test-Path -Path "$LatestNugetFolder\$ExePath"
169+
170+
$NugetVersions = Get-ChildItem -Path $DownloadsFolder -Filter "$PackageId.*";
171+
$NugetVersions = $NugetVersions | Sort-Object -Property Name -Descending
172+
173+
if($TestPathResult)
174+
{
175+
#Remove all other NuGet versions except for the version just downloaded
176+
for ($NugetIndex = 0; $NugetIndex -lt $NugetVersions.Length; $NugetIndex = $NugetIndex + 1)
177+
{
178+
if($NugetVersions[$NugetIndex].Name -ne $LatestNugetOrgNameAndVersion)
179+
{
180+
Remove-Item -Path $NugetVersions[$NugetIndex].FullName -Recurse -Force
181+
}
182+
}
183+
}
184+
else
185+
{
186+
if($NugetVersions.Length -gt 0)
187+
{
188+
$LatestNugetFolder = $NugetVersions[0].Name;
189+
}
190+
}
191+
}
192+
193+
if(-Not (Test-Path -Path "$LatestNugetFolder\$ExePath"))
194+
{
195+
Write-Host "Failed to locate executable."
196+
return
197+
}
198+
199+
$SourceSqlConnectionStringParam = . "$PSScriptRoot/../../utils/Unprotect-SecureString.ps1" $SourceSqlConnectionString
200+
$NetworkSharePasswordParam = . "$PSScriptRoot/../../utils/Unprotect-SecureString.ps1" $NetworkSharePassword
201+
202+
[System.Collections.ArrayList] $parameterArray = @(
203+
"--sourceSqlConnectionString", $SourceSqlConnectionStringParam,
204+
"--targetSubscriptionId", $TargetSubscriptionId,
205+
"--targetResourceGroupName", $TargetResourceGroupName,
206+
"--targetManagedInstanceName", $TargetManagedInstanceName
207+
"--networkSharePath", $NetworkSharePath
208+
"--networkShareDomain", $NetworkShareDomain
209+
"--networkShareUserName", $NetworkShareUserName
210+
"--networkSharePassword", $NetworkSharePasswordParam
211+
"--databaseName"
212+
)
213+
214+
$ExePath = Join-Path -Path $LatestNugetFolder -ChildPath $ExePath;
215+
foreach($Name in $DatabaseName) {
216+
$parameterArray.Add($Name) | Out-Null;
217+
}
218+
219+
& $ExePath $parameterArray
220+
221+
if($PSBoundParameters.ContainsKey("PassThru"))
222+
{
223+
return $true;
224+
}
225+
}
226+
catch
227+
{
228+
throw $_
229+
}
230+
}
231+
}
232+
233+
function Get-DefaultTdeMigrationsOutputFolder {
234+
[Microsoft.Azure.PowerShell.Cmdlets.DataMigration.DoNotExportAttribute()]
235+
param(
236+
)
237+
238+
process {
239+
$OSPlatform = Get-OSName
240+
241+
if($OSPlatform.Contains("Linux"))
242+
{
243+
$DefualtPath = Join-Path -Path $env:USERPROFILE -ChildPath ".config\Microsoft\SqlTdeMigrations";
244+
245+
}
246+
elseif ($OSPlatform.Contains("Darwin"))
247+
{
248+
$DefualtPath = Join-Path -Path $env:USERPROFILE -ChildPath "Library\Application Support\Microsoft\SqlTdeMigrations";
249+
}
250+
else
251+
{
252+
$DefualtPath = Join-Path -Path $env:LOCALAPPDATA -ChildPath "Microsoft\SqlTdeMigrations";
253+
}
254+
255+
return $DefualtPath
256+
}
257+
}

src/DataMigration/DataMigration.Autorest/docs/Az.DataMigration.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ Create or Update Database Migration Service.
5656
### [New-AzDataMigrationSqlServiceAuthKey](New-AzDataMigrationSqlServiceAuthKey.md)
5757
Regenerate a new set of Authentication Keys for Self Hosted Integration Runtime.
5858

59+
### [New-AzDataMigrationTdeCertificateMigration](New-AzDataMigrationTdeCertificateMigration.md)
60+
Migrate TDE certificate from source SQL Server to the target Azure SQL Server.
61+
5962
### [New-AzDataMigrationToSqlDb](New-AzDataMigrationToSqlDb.md)
6063
Create a new database migration to a given SQL Db.
6164

0 commit comments

Comments
 (0)