[SQL Migration] Properly respect user's encryptConnection and trustServerCertificate settings (#21824)

* WIP

* Always get latest current connection

* Update more references

* Clean up

* Clean up

* vbump

* Update comments

* Address PR feedback

* Separate into helper methods
This commit is contained in:
Raymond Truong
2023-02-08 10:12:11 -08:00
committed by GitHub
parent 99a924dbcd
commit 480d8e2cd0
25 changed files with 206 additions and 154 deletions

View File

@@ -628,6 +628,7 @@ export async function getLocationDisplayName(location: string): Promise<string>
export async function validateIrSqlDatabaseMigrationSettings(
migration: MigrationStateModel,
sourceServerName: string,
encryptConnection: boolean,
trustServerCertificate: boolean,
sourceDatabaseName: string,
targetDatabaseName: string,
@@ -654,17 +655,18 @@ export async function validateIrSqlDatabaseMigrationSettings(
userName: migration._sqlServerUsername,
password: migration._sqlServerPassword,
authentication: migration._authenticationType,
encryptConnection: encryptConnection,
trustServerCertificate: trustServerCertificate,
// encryptConnection: true,
},
targetSqlConnection: {
testConnectivity: testTargetConnectivity,
dataSource: targetDatabaseServer.properties.fullyQualifiedDomainName,
userName: migration._targetUserName,
password: migration._targetPassword,
authentication: MigrationSourceAuthenticationType.Sql,
// when connecting to a target Azure SQL DB, use true/false
encryptConnection: true,
trustServerCertificate: false,
authentication: MigrationSourceAuthenticationType.Sql,
}
};
@@ -686,6 +688,7 @@ export async function validateIrSqlDatabaseMigrationSettings(
export async function validateIrDatabaseMigrationSettings(
migration: MigrationStateModel,
sourceServerName: string,
encryptConnection: boolean,
trustServerCertificate: boolean,
sourceDatabaseName: string,
networkShare: NetworkShare,
@@ -728,7 +731,7 @@ export async function validateIrDatabaseMigrationSettings(
dataSource: sourceServerName,
userName: migration._sqlServerUsername,
password: migration._sqlServerPassword,
// to-do: use correct value of encryptConnection and trustServerCertificate
encryptConnection: encryptConnection,
trustServerCertificate: trustServerCertificate,
authentication: migration._authenticationType,
}
@@ -954,8 +957,8 @@ export interface ValdiateIrDatabaseMigrationResponse {
sourceDatabaseName: string,
sourceSqlConnection: {
testConnectivity: boolean,
encryptConnection: true,
trustServerCertificate: false,
encryptConnection: boolean,
trustServerCertificate: boolean,
dataSource: string,
},
backupConfiguration: {
@@ -1042,15 +1045,6 @@ export interface CopyProgressDetail {
errors: string[];
}
export interface SqlConnectionInfo {
dataSource: string;
authentication: string;
username: string;
password: string;
encryptConnection: string;
trustServerCertificate: string;
}
export interface BackupConfiguration {
sourceLocation?: SourceLocation;
targetLocation?: TargetLocation;

View File

@@ -130,6 +130,40 @@ export interface LoginTableInfo {
status: string;
}
export async function getSourceConnectionProfile(): Promise<azdata.connection.ConnectionProfile> {
return await azdata.connection.getCurrentConnection();
}
export async function getSourceConnectionId(): Promise<string> {
return (await getSourceConnectionProfile()).connectionId;
}
export async function getSourceConnectionServerInfo(): Promise<azdata.ServerInfo> {
return await azdata.connection.getServerInfo(await getSourceConnectionId());
}
export async function getSourceConnectionUri(): Promise<string> {
return await azdata.connection.getUriForConnection(await getSourceConnectionId());
}
export async function getSourceConnectionCredentials(): Promise<{ [name: string]: string }> {
return await azdata.connection.getCredentials(await getSourceConnectionId());
}
export async function getSourceConnectionQueryProvider(): Promise<azdata.QueryProvider> {
return azdata.dataprotocol.getProvider<azdata.QueryProvider>(
(await getSourceConnectionProfile()).providerId,
azdata.DataProviderType.QueryProvider);
}
export function getEncryptConnectionValue(connection: azdata.connection.ConnectionProfile): boolean {
return connection?.options?.encrypt === true || connection?.options?.encrypt === 'true';
}
export function getTrustServerCertificateValue(connection: azdata.connection.ConnectionProfile): boolean {
return connection?.options?.trustServerCertificate === true || connection?.options?.trustServerCertificate === 'true';
}
function getSqlDbConnectionProfile(
serverName: string,
tenantId: string,
@@ -156,6 +190,7 @@ function getSqlDbConnectionProfile(
password: password,
connectionTimeout: 60,
columnEncryptionSetting: 'Enabled',
// when connecting to a target Azure SQL DB, use true/false
encrypt: true,
trustServerCertificate: false,
connectRetryCount: '1',
@@ -168,12 +203,13 @@ function getSqlDbConnectionProfile(
};
}
export function getConnectionProfile(
export function getTargetConnectionProfile(
serverName: string,
azureResourceId: string,
userName: string,
password: string,
trustServerCert: boolean = false): azdata.IConnectionProfile {
encryptConnection: boolean,
trustServerCert: boolean): azdata.IConnectionProfile {
const connectId = generateGuid();
return {
@@ -197,7 +233,7 @@ export function getConnectionProfile(
password: password,
connectionTimeout: 60,
columnEncryptionSetting: 'Enabled',
encrypt: true,
encrypt: encryptConnection,
trustServerCertificate: trustServerCert,
connectRetryCount: '1',
connectRetryInterval: '10',
@@ -206,8 +242,36 @@ export function getConnectionProfile(
};
}
export async function collectSourceDatabaseTableInfo(sourceConnectionId: string, sourceDatabase: string): Promise<TableInfo[]> {
const ownerUri = await azdata.connection.getUriForConnection(sourceConnectionId);
export async function getSourceConnectionString(): Promise<string> {
return await azdata.connection.getConnectionString((await getSourceConnectionProfile()).connectionId, true);
}
export async function getTargetConnectionString(
serverName: string,
azureResourceId: string,
username: string,
password: string,
encryptConnection: boolean,
trustServerCertificate: boolean): Promise<string> {
const connectionProfile = getTargetConnectionProfile(
serverName,
azureResourceId,
username,
password,
encryptConnection,
trustServerCertificate);
const result = await azdata.connection.connect(connectionProfile, false, false);
if (result.connected && result.connectionId) {
return azdata.connection.getConnectionString(result.connectionId, true);
}
return '';
}
export async function collectSourceDatabaseTableInfo(sourceDatabase: string): Promise<TableInfo[]> {
const ownerUri = await azdata.connection.getUriForConnection((await getSourceConnectionProfile()).connectionId);
const connectionProvider = azdata.dataprotocol.getProvider<azdata.ConnectionProvider>(
'MSSQL',
azdata.DataProviderType.ConnectionProvider);
@@ -272,11 +336,14 @@ export async function collectTargetDatabaseInfo(
userName: string,
password: string): Promise<TargetDatabaseInfo[]> {
const connectionProfile = getConnectionProfile(
const connectionProfile = getTargetConnectionProfile(
targetServer.properties.fullyQualifiedDomainName,
targetServer.id,
userName,
password);
password,
// when connecting to a target Azure SQL DB, use true/false
true /* encryptConnection */,
false /* trustServerCertificate */);
const result = await azdata.connection.connect(connectionProfile, false, false);
if (result.connected && result.connectionId) {
@@ -397,11 +464,14 @@ export async function collectTargetLogins(
password: string,
includeWindowsAuth: boolean = true): Promise<string[]> {
const connectionProfile = getConnectionProfile(
const connectionProfile = getTargetConnectionProfile(
serverName,
azureResourceId,
userName,
password,
// for login migration, connect to target Azure SQL with true/true
// to-do: take as input from the user, should be true/false for DB/MI but true/true for VM
true /* encryptConnection */,
true /* trustServerCertificate */);
const result = await azdata.connection.connect(connectionProfile, false, false);
@@ -422,7 +492,8 @@ export async function collectTargetLogins(
throw new Error(result.errorMessage);
}
export async function isSysAdmin(sourceConnectionId: string): Promise<boolean> {
export async function isSourceConnectionSysAdmin(): Promise<boolean> {
const sourceConnectionId = await getSourceConnectionId();
const ownerUri = await azdata.connection.getUriForConnection(sourceConnectionId);
const queryProvider = azdata.dataprotocol.getProvider<azdata.QueryProvider>(
'MSSQL',