Update Microsoft.Data.SqlClient to v5.0.1 (#1708)

This commit is contained in:
Cheena Malhotra
2022-10-24 20:10:04 -07:00
committed by GitHub
parent 3be806ddce
commit c0f8482e26
30 changed files with 416 additions and 313 deletions

View File

@@ -6,8 +6,8 @@
<PackageReference Update="System.IO.Packaging" Version="4.7.0" /> <PackageReference Update="System.IO.Packaging" Version="4.7.0" />
<PackageReference Update="System.Runtime.Loader" Version="4.3.0" /> <PackageReference Update="System.Runtime.Loader" Version="4.3.0" />
<PackageReference Update="System.Composition" Version="1.4.1" /> <PackageReference Update="System.Composition" Version="1.4.1" />
<PackageReference Update="System.Security.Permissions" Version="4.7.0" /> <PackageReference Update="System.Security.Permissions" Version="5.0.0" />
<PackageReference Update="System.Text.Encoding.CodePages" Version="4.7.1" /> <PackageReference Update="System.Text.Encoding.CodePages" Version="5.0.0" />
<PackageReference Update="System.Text.Encodings.Web" Version="4.7.2" /> <PackageReference Update="System.Text.Encodings.Web" Version="4.7.2" />
<PackageReference Update="System.Reactive.Core" Version="5.0.0" /> <PackageReference Update="System.Reactive.Core" Version="5.0.0" />
@@ -19,14 +19,14 @@
<PackageReference Update="Microsoft.Azure.Management.Sql" Version="1.41.0-preview" /> <PackageReference Update="Microsoft.Azure.Management.Sql" Version="1.41.0-preview" />
<PackageReference Update="Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider" Version="1.1.1" /> <PackageReference Update="Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider" Version="1.1.1" />
<PackageReference Update="Microsoft.Data.SqlClient" Version="3.1.1" /> <PackageReference Update="Microsoft.Data.SqlClient" Version="5.0.1" />
<PackageReference Update="Microsoft.SqlServer.SqlManagementObjects" Version="161.47021.0" /> <PackageReference Update="Microsoft.SqlServer.SqlManagementObjects" Version="170.8.0" />
<PackageReference Update="Microsoft.SqlServer.Management.SmoMetadataProvider" Version="161.47008.0" /> <PackageReference Update="Microsoft.SqlServer.Management.SmoMetadataProvider" Version="170.8.0" />
<PackageReference Update="Microsoft.SqlServer.DACFx" Version="160.6295.0-preview" /> <PackageReference Update="Microsoft.SqlServer.DacFx" Version="161.6337.0-preview" />
<PackageReference Update="Microsoft.Azure.Kusto.Data" Version="9.0.4" /> <PackageReference Update="Microsoft.Azure.Kusto.Data" Version="9.0.4" />
<PackageReference Update="Microsoft.Azure.Kusto.Language" Version="9.0.4" /> <PackageReference Update="Microsoft.Azure.Kusto.Language" Version="9.0.4" />
<PackageReference Update="Microsoft.SqlServer.Assessment" Version="[1.1.9]" /> <PackageReference Update="Microsoft.SqlServer.Assessment" Version="[1.1.9]" />
<PackageReference Update="Microsoft.SqlServer.Migration.Assessment" Version="1.0.20220816.40" /> <PackageReference Update="Microsoft.SqlServer.Migration.Assessment" Version="1.0.20221014.16" />
<PackageReference Update="Microsoft.SqlServer.Management.SqlParser" Version="160.22519.0" /> <PackageReference Update="Microsoft.SqlServer.Management.SqlParser" Version="160.22519.0" />
<PackageReference Update="Microsoft.Azure.OperationalInsights" Version="1.0.0" /> <PackageReference Update="Microsoft.Azure.OperationalInsights" Version="1.0.0" />
<PackageReference Update="Microsoft.CodeAnalysis.CSharp" Version="3.10.0" /> <PackageReference Update="Microsoft.CodeAnalysis.CSharp" Version="3.10.0" />
@@ -45,4 +45,4 @@
<PackageReference Update="coverlet.collector" Version="3.1.2" /> <PackageReference Update="coverlet.collector" Version="3.1.2" />
<PackageReference Update="coverlet.msbuild" Version="3.1.2" /> <PackageReference Update="coverlet.msbuild" Version="3.1.2" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -91,14 +91,6 @@ namespace Microsoft.Kusto.ServiceLayer.Connection
GroupName = "Initialization" GroupName = "Initialization"
}, },
new ConnectionOption new ConnectionOption
{
Name = "asynchronousProcessing",
DisplayName = "Asynchronous processing enabled",
Description = "When true, enables usage of the Asynchronous functionality in the .Net Framework Data Provider",
ValueType = ConnectionOption.ValueTypeBoolean,
GroupName = "Initialization"
},
new ConnectionOption
{ {
Name = "connectTimeout", Name = "connectTimeout",
DisplayName = "Connect timeout", DisplayName = "Connect timeout",

View File

@@ -31,8 +31,9 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Azure.OperationalInsights" /> <PackageReference Include="Microsoft.Azure.OperationalInsights" />
<PackageReference Include="Microsoft.SqlServer.DACFx" /> <PackageReference Include="Microsoft.SqlServer.DacFx" />
<PackageReference Include="Microsoft.SqlServer.Management.SmoMetadataProvider" /> <PackageReference Include="Microsoft.SqlServer.Management.SmoMetadataProvider" />
<PackageReference Include="Microsoft.SqlServer.SqlManagementObjects" />
<PackageReference Include="System.Text.Encoding.CodePages" /> <PackageReference Include="System.Text.Encoding.CodePages" />
<PackageReference Include="Microsoft.Azure.Kusto.Data" /> <PackageReference Include="Microsoft.Azure.Kusto.Data" />
<PackageReference Include="System.Net.Http" /> <PackageReference Include="System.Net.Http" />

View File

@@ -86,7 +86,7 @@ namespace Microsoft.SqlTools.Utility
enumValue = Enum.Parse(t, value); enumValue = Enum.Parse(t, value);
return true; return true;
} }
catch(Exception) catch (Exception)
{ {
enumValue = default(T); enumValue = default(T);
return false; return false;

View File

@@ -155,12 +155,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode
} }
} }
if (fullFileName == null) return fullFileName ?? Path.GetFullPath(fileName);
{
fullFileName = Path.GetFullPath(fileName);
}
return fullFileName;
} }
catch (ArgumentException) catch (ArgumentException)
{ {

View File

@@ -128,15 +128,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser.ExecutionEngineCode
internal Dictionary<string, string> Variables internal Dictionary<string, string> Variables
{ {
get get => cmdVariables ??= new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
{
if (cmdVariables == null)
{
cmdVariables = new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
}
return cmdVariables;
}
} }
#endregion #endregion
} }

View File

@@ -608,18 +608,10 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser
} }
internal void RaiseError(ErrorCode errorCode, string message = null) internal void RaiseError(ErrorCode errorCode, string message = null)
{ => RaiseError(errorCode, LookaheadToken, message);
RaiseError(errorCode, LookaheadToken, message);
}
internal static void RaiseError(ErrorCode errorCode, Token token, string message = null) internal static void RaiseError(ErrorCode errorCode, Token token, string message = null)
{ => throw new BatchParserException(errorCode, token, message ?? string.Format(CultureInfo.CurrentCulture, SR.BatchParser_IncorrectSyntax, token.Text));
if (message == null)
{
message = string.Format(CultureInfo.CurrentCulture, SR.BatchParser_IncorrectSyntax, token.Text);
}
throw new BatchParserException(errorCode, token, message);
}
internal string ResolveVariables(Token inputToken, int offset, List<VariableReference> variableRefs) internal string ResolveVariables(Token inputToken, int offset, List<VariableReference> variableRefs)
{ {

View File

@@ -1,7 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<!-- Targeting netstandard2.0 so that other things such as PS cmdlets can use this which need to support a wider range of machines --> <!-- Targeting both net6.0 and net472 so that other things such as PS cmdlets can use this which need to support a wider range of machines -->
<TargetFramework>netstandard2.0</TargetFramework> <TargetFrameworks>net6.0;net472</TargetFrameworks>
<LangVersion>9.0</LangVersion>
<Nullable>disable</Nullable> <Nullable>disable</Nullable>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<EnableDefaultEmbeddedResourceItems>false</EnableDefaultEmbeddedResourceItems> <EnableDefaultEmbeddedResourceItems>false</EnableDefaultEmbeddedResourceItems>

View File

@@ -276,10 +276,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection
Debug.Assert(conn.State == ConnectionState.Open, "connection passed to ExecuteNonQuery should be open."); Debug.Assert(conn.State == ConnectionState.Open, "connection passed to ExecuteNonQuery should be open.");
cmd = conn.CreateCommand(); cmd = conn.CreateCommand();
if (initializeCommand == null)
{ initializeCommand ??= SetCommandTimeout;
initializeCommand = SetCommandTimeout;
}
initializeCommand(cmd); initializeCommand(cmd);
cmd.CommandText = commandText; cmd.CommandText = commandText;
@@ -331,10 +329,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection
Debug.Assert(conn.State == ConnectionState.Open, "connection passed to ExecuteScalar should be open."); Debug.Assert(conn.State == ConnectionState.Open, "connection passed to ExecuteScalar should be open.");
cmd = conn.CreateCommand(); cmd = conn.CreateCommand();
if (initializeCommand == null)
{ initializeCommand ??= SetCommandTimeout;
initializeCommand = SetCommandTimeout;
}
initializeCommand(cmd); initializeCommand(cmd);
cmd.CommandText = commandText; cmd.CommandText = commandText;
@@ -384,11 +380,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection
{ {
cmd = conn.CreateCommand(); cmd = conn.CreateCommand();
if (initializeCommand == null) initializeCommand ??= SetCommandTimeout;
{
initializeCommand = SetCommandTimeout;
}
initializeCommand(cmd); initializeCommand(cmd);
cmd.CommandText = commandText; cmd.CommandText = commandText;

View File

@@ -478,10 +478,7 @@ SET NUMERIC_ROUNDABORT OFF;";
{ {
// Verify whether or not the connection is valid and is open. This code may be retried therefore // Verify whether or not the connection is valid and is open. This code may be retried therefore
// it is important to ensure that a connection is re-established should it have previously failed. // it is important to ensure that a connection is re-established should it have previously failed.
if (command.Connection == null) command.Connection ??= this;
{
command.Connection = this;
}
if (command.Connection.State != ConnectionState.Open) if (command.Connection.State != ConnectionState.Open)
{ {

View File

@@ -91,14 +91,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
GroupName = "Initialization" GroupName = "Initialization"
}, },
new ConnectionOption new ConnectionOption
{
Name = "asynchronousProcessing",
DisplayName = "Asynchronous processing enabled",
Description = "When true, enables usage of the Asynchronous functionality in the .Net Framework Data Provider",
ValueType = ConnectionOption.ValueTypeBoolean,
GroupName = "Initialization"
},
new ConnectionOption
{ {
Name = "connectTimeout", Name = "connectTimeout",
DisplayName = "Connect timeout", DisplayName = "Connect timeout",
@@ -152,10 +144,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
{ {
Name = "encrypt", Name = "encrypt",
DisplayName = "Encrypt", DisplayName = "Encrypt",
Description = Description = "When set, SQL Server uses provided setting for SSL encryption for all data sent between the client and server.",
"When true, SQL Server uses SSL encryption for all data sent between the client and server if the servers has a certificate installed", ValueType = ConnectionOption.ValueTypeCategory,
GroupName = "Security", GroupName = "Security",
ValueType = ConnectionOption.ValueTypeBoolean CategoryValues = new CategoryValue[] {
new CategoryValue { DisplayName = "Optional", Name = "Optional" },
new CategoryValue { DisplayName = "Mandatory", Name = "Mandatory" },
new CategoryValue { DisplayName = "Strict", Name = "Strict" }
}
}, },
new ConnectionOption new ConnectionOption
{ {
@@ -174,6 +170,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
ValueType = ConnectionOption.ValueTypeBoolean ValueType = ConnectionOption.ValueTypeBoolean
}, },
new ConnectionOption new ConnectionOption
{
Name = "hostNameInCertificate",
DisplayName = "HostNameInCertificate",
Description = "Specifies host name in certificate to be used for certificate validation, when encryption is enabled.",
GroupName = "Security",
ValueType = ConnectionOption.ValueTypeString,
},
new ConnectionOption
{ {
Name = "attachedDBFileName", Name = "attachedDBFileName",
DisplayName = "Attached DB file name", DisplayName = "Attached DB file name",

View File

@@ -410,7 +410,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
if (response?.ErrorNumber == 40613) if (response?.ErrorNumber == 40613)
{ {
counter++; counter++;
if(counter != MaxServerlessReconnectTries) { if (counter != MaxServerlessReconnectTries)
{
Logger.Information($"Database for connection {connectionInfo.OwnerUri} is paused, retrying connection. Attempt #{counter}"); Logger.Information($"Database for connection {connectionInfo.OwnerUri} is paused, retrying connection. Attempt #{counter}");
} }
} }
@@ -1299,14 +1300,26 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
connectionBuilder.EnclaveAttestationUrl = connectionDetails.EnclaveAttestationUrl; connectionBuilder.EnclaveAttestationUrl = connectionDetails.EnclaveAttestationUrl;
} }
if (connectionDetails.Encrypt.HasValue)
if (!string.IsNullOrEmpty(connectionDetails.Encrypt))
{ {
connectionBuilder.Encrypt = connectionDetails.Encrypt.Value; connectionBuilder.Encrypt = connectionDetails.Encrypt.ToLowerInvariant() switch
{
"optional" or "false" or "no" => SqlConnectionEncryptOption.Optional,
"mandatory" or "true" or "yes" => SqlConnectionEncryptOption.Mandatory,
"strict" => SqlConnectionEncryptOption.Strict,
_ => throw new ArgumentException(SR.ConnectionServiceConnStringInvalidEncryptOption(connectionDetails.Encrypt))
};
} }
if (connectionDetails.TrustServerCertificate.HasValue) if (connectionDetails.TrustServerCertificate.HasValue)
{ {
connectionBuilder.TrustServerCertificate = connectionDetails.TrustServerCertificate.Value; connectionBuilder.TrustServerCertificate = connectionDetails.TrustServerCertificate.Value;
} }
if (!string.IsNullOrEmpty(connectionDetails.HostNameInCertificate))
{
connectionBuilder.HostNameInCertificate = connectionDetails.HostNameInCertificate;
}
if (connectionDetails.PersistSecurityInfo.HasValue) if (connectionDetails.PersistSecurityInfo.HasValue)
{ {
connectionBuilder.PersistSecurityInfo = connectionDetails.PersistSecurityInfo.Value; connectionBuilder.PersistSecurityInfo = connectionDetails.PersistSecurityInfo.Value;
@@ -1471,8 +1484,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
ColumnEncryptionSetting = builder.ColumnEncryptionSetting.ToString(), ColumnEncryptionSetting = builder.ColumnEncryptionSetting.ToString(),
EnclaveAttestationProtocol = builder.AttestationProtocol == SqlConnectionAttestationProtocol.NotSpecified ? null : builder.AttestationProtocol.ToString(), EnclaveAttestationProtocol = builder.AttestationProtocol == SqlConnectionAttestationProtocol.NotSpecified ? null : builder.AttestationProtocol.ToString(),
EnclaveAttestationUrl = builder.EnclaveAttestationUrl, EnclaveAttestationUrl = builder.EnclaveAttestationUrl,
Encrypt = builder.Encrypt, Encrypt = builder.Encrypt.ToString(),
FailoverPartner = builder.FailoverPartner, FailoverPartner = builder.FailoverPartner,
HostNameInCertificate = builder.HostNameInCertificate,
LoadBalanceTimeout = builder.LoadBalanceTimeout, LoadBalanceTimeout = builder.LoadBalanceTimeout,
MaxPoolSize = builder.MaxPoolSize, MaxPoolSize = builder.MaxPoolSize,
MinPoolSize = builder.MinPoolSize, MinPoolSize = builder.MinPoolSize,

View File

@@ -147,13 +147,13 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts
} }
/// <summary> /// <summary>
/// Gets or sets a Boolean value that indicates whether SQL Server uses SSL encryption for all data sent between the client and server if the server has a certificate installed. /// Gets or sets a <see cref="string"/> value that indicates encryption mode that SQL Server should use to perform SSL encryption for all the data sent between the client and server. Supported values are: Optional, Mandatory, Strict.
/// </summary> /// </summary>
public bool? Encrypt public string Encrypt
{ {
get get
{ {
return GetOptionValue<bool?>("encrypt"); return GetOptionValue<string>("encrypt");
} }
set set
@@ -178,6 +178,22 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts
} }
} }
/// <summary>
/// Gets or sets a value that indicates the host name in the certificate to be used for certificate validation when encryption is enabled.
/// </summary>
public string HostNameInCertificate
{
get
{
return GetOptionValue<string>("hostNameInCertificate");
}
set
{
SetOptionValue("hostNameInCertificate", value);
}
}
/// <summary> /// <summary>
/// Gets or sets a Boolean value that indicates if security-sensitive information, such as the password, is not returned as part of the connection if the connection is open or has ever been in an open state. /// Gets or sets a Boolean value that indicates if security-sensitive information, such as the password, is not returned as part of the connection if the connection is open or has ever been in an open state.
/// </summary> /// </summary>

View File

@@ -27,6 +27,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts
EnclaveAttestationUrl = details.EnclaveAttestationUrl, EnclaveAttestationUrl = details.EnclaveAttestationUrl,
Encrypt = details.Encrypt, Encrypt = details.Encrypt,
TrustServerCertificate = details.TrustServerCertificate, TrustServerCertificate = details.TrustServerCertificate,
HostNameInCertificate = details.HostNameInCertificate,
PersistSecurityInfo = details.PersistSecurityInfo, PersistSecurityInfo = details.PersistSecurityInfo,
ConnectTimeout = details.ConnectTimeout, ConnectTimeout = details.ConnectTimeout,
ConnectRetryCount = details.ConnectRetryCount, ConnectRetryCount = details.ConnectRetryCount,

View File

@@ -9641,6 +9641,11 @@ namespace Microsoft.SqlTools.ServiceLayer
return Keys.GetString(Keys.ConnectionServiceConnStringInvalidColumnEncryptionSetting, columnEncryptionSetting); return Keys.GetString(Keys.ConnectionServiceConnStringInvalidColumnEncryptionSetting, columnEncryptionSetting);
} }
public static string ConnectionServiceConnStringInvalidEncryptOption(string encrypt)
{
return Keys.GetString(Keys.ConnectionServiceConnStringInvalidEncryptOption, encrypt);
}
public static string ConnectionServiceConnStringInvalidEnclaveAttestationProtocol(string enclaveAttestationProtocol) public static string ConnectionServiceConnStringInvalidEnclaveAttestationProtocol(string enclaveAttestationProtocol)
{ {
return Keys.GetString(Keys.ConnectionServiceConnStringInvalidEnclaveAttestationProtocol, enclaveAttestationProtocol); return Keys.GetString(Keys.ConnectionServiceConnStringInvalidEnclaveAttestationProtocol, enclaveAttestationProtocol);
@@ -10062,6 +10067,9 @@ namespace Microsoft.SqlTools.ServiceLayer
public const string ConnectionServiceConnStringInvalidColumnEncryptionSetting = "ConnectionServiceConnStringInvalidColumnEncryptionSetting"; public const string ConnectionServiceConnStringInvalidColumnEncryptionSetting = "ConnectionServiceConnStringInvalidColumnEncryptionSetting";
public const string ConnectionServiceConnStringInvalidEncryptOption = "ConnectionServiceConnStringInvalidEncryptOption";
public const string ConnectionServiceConnStringInvalidEnclaveAttestationProtocol = "ConnectionServiceConnStringInvalidEnclaveAttestationProtocol"; public const string ConnectionServiceConnStringInvalidEnclaveAttestationProtocol = "ConnectionServiceConnStringInvalidEnclaveAttestationProtocol";

View File

@@ -144,6 +144,11 @@
<value>Invalid value &apos;{0}&apos; for ComlumEncryption. Valid values are &apos;Enabled&apos; and &apos;Disabled&apos;.</value> <value>Invalid value &apos;{0}&apos; for ComlumEncryption. Valid values are &apos;Enabled&apos; and &apos;Disabled&apos;.</value>
<comment>. <comment>.
Parameters: 0 - columnEncryptionSetting (string) </comment> Parameters: 0 - columnEncryptionSetting (string) </comment>
</data>
<data name="ConnectionServiceConnStringInvalidEncryptOption" xml:space="preserve">
<value>Invalid value &apos;{0}&apos; for Encrypt. Valid values are &apos;Optional&apos;, &apos;Mandatory&apos;, &apos;Strict&apos;, &apos;True&apos;, &apos;False&apos;, &apos;Yes&apos; and &apos;No&apos;.</value>
<comment>.
Parameters: 0 - encrypt (string) </comment>
</data> </data>
<data name="ConnectionServiceConnStringInvalidEnclaveAttestationProtocol" xml:space="preserve"> <data name="ConnectionServiceConnStringInvalidEnclaveAttestationProtocol" xml:space="preserve">
<value>Invalid value &apos;{0}&apos; for EnclaveAttestationProtocol. Valid values are &apos;AAS&apos; and &apos;HGS&apos;.</value> <value>Invalid value &apos;{0}&apos; for EnclaveAttestationProtocol. Valid values are &apos;AAS&apos; and &apos;HGS&apos;.</value>

View File

@@ -35,6 +35,8 @@ ConnectionServiceConnStringInvalidAuthType(string authType) = Invalid value '{0}
ConnectionServiceConnStringInvalidColumnEncryptionSetting(string columnEncryptionSetting) = Invalid value '{0}' for ComlumEncryption. Valid values are 'Enabled' and 'Disabled'. ConnectionServiceConnStringInvalidColumnEncryptionSetting(string columnEncryptionSetting) = Invalid value '{0}' for ComlumEncryption. Valid values are 'Enabled' and 'Disabled'.
ConnectionServiceConnStringInvalidEncryptOption(string encrypt) = Invalid value '{0}' for Encrypt. Valid values are 'Optional', 'Mandatory', 'Strict', 'True', 'False', 'Yes' and 'No'.
ConnectionServiceConnStringInvalidEnclaveAttestationProtocol(string enclaveAttestationProtocol) = Invalid value '{0}' for EnclaveAttestationProtocol. Valid values are 'AAS' and 'HGS'. ConnectionServiceConnStringInvalidEnclaveAttestationProtocol(string enclaveAttestationProtocol) = Invalid value '{0}' for EnclaveAttestationProtocol. Valid values are 'AAS' and 'HGS'.
ConnectionServiceConnStringInvalidAlwaysEncryptedOptionCombination = The Attestation Protocol and Enclave Attestation URL requires Always Encrypted to be set to Enabled. ConnectionServiceConnStringInvalidAlwaysEncryptedOptionCombination = The Attestation Protocol and Enclave Attestation URL requires Always Encrypted to be set to Enabled.

View File

@@ -2034,6 +2034,12 @@
<target state="new">Invalid value '{0}' for ComlumEncryption. Valid values are 'Enabled' and 'Disabled'.</target> <target state="new">Invalid value '{0}' for ComlumEncryption. Valid values are 'Enabled' and 'Disabled'.</target>
<note>. <note>.
Parameters: 0 - columnEncryptionSetting (string) </note> Parameters: 0 - columnEncryptionSetting (string) </note>
</trans-unit>
<trans-unit id="ConnectionServiceConnStringInvalidEncryptOption">
<source>Invalid value '{0}' for Encrypt. Valid values are 'Optional', 'Mandatory', 'Strict', 'True', 'False', 'Yes' and 'No'.</source>
<target state="new">Invalid value '{0}' for Encrypt. Valid values are 'Optional', 'Mandatory', 'Strict', 'True', 'False', 'Yes' and 'No'.</target>
<note>.
Parameters: 0 - encrypt (string) </note>
</trans-unit> </trans-unit>
<trans-unit id="ConnectionServiceConnStringInvalidEnclaveAttestationProtocol"> <trans-unit id="ConnectionServiceConnStringInvalidEnclaveAttestationProtocol">
<source>Invalid value '{0}' for EnclaveAttestationProtocol. Valid values are 'AAS' and 'HGS'.</source> <source>Invalid value '{0}' for EnclaveAttestationProtocol. Valid values are 'AAS' and 'HGS'.</source>

View File

@@ -49,11 +49,12 @@
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" /> <PackageReference Include="Microsoft.CodeAnalysis.CSharp" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" /> <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" /> <PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" />
<PackageReference Include="Microsoft.SqlServer.DACFx" /> <PackageReference Include="Microsoft.SqlServer.DacFx" />
<PackageReference Include="Microsoft.Data.SqlClient" />
<PackageReference Include="Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider" /> <PackageReference Include="Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider" />
<PackageReference Include="System.Text.Encoding.CodePages" />
<PackageReference Include="Microsoft.SqlServer.Assessment" /> <PackageReference Include="Microsoft.SqlServer.Assessment" />
<PackageReference Include="Microsoft.SqlServer.Management.SmoMetadataProvider" /> <PackageReference Include="Microsoft.SqlServer.Management.SmoMetadataProvider" />
<PackageReference Include="Microsoft.SqlServer.SqlManagementObjects" />
<PackageReference Include="Microsoft.SqlServer.Management.SqlParser" /> <PackageReference Include="Microsoft.SqlServer.Management.SqlParser" />
<PackageReference Include="System.Text.Encoding.CodePages" /> <PackageReference Include="System.Text.Encoding.CodePages" />
<PackageReference Include="Microsoft.SqlServer.TransactSql.ScriptDom.NRT"> <PackageReference Include="Microsoft.SqlServer.TransactSql.ScriptDom.NRT">

View File

@@ -11,10 +11,10 @@ namespace Microsoft.Kusto.ServiceLayer.UnitTests.Connection
public class ConnectionProviderOptionsHelperTests public class ConnectionProviderOptionsHelperTests
{ {
[Test] [Test]
public void BuildConnectionProviderOptions_Returns_31_Options() public void BuildConnectionProviderOptions_Returns_30_Options()
{ {
var providerOptions = ConnectionProviderOptionsHelper.BuildConnectionProviderOptions(); var providerOptions = ConnectionProviderOptionsHelper.BuildConnectionProviderOptions();
Assert.AreEqual(31, providerOptions.Options.Length); Assert.AreEqual(30, providerOptions.Options.Length);
} }
} }
} }

View File

@@ -242,8 +242,19 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Connection
csb.Password = connectParams.Connection.Password; csb.Password = connectParams.Connection.Password;
} }
csb.ConnectTimeout = connectParams.Connection.ConnectTimeout.HasValue ? connectParams.Connection.ConnectTimeout.Value: 30; csb.ConnectTimeout = connectParams.Connection.ConnectTimeout.HasValue ? connectParams.Connection.ConnectTimeout.Value: 30;
csb.Encrypt = connectParams.Connection.Encrypt.HasValue ? connectParams.Connection.Encrypt.Value : false;
csb.Encrypt = connectParams.Connection.Encrypt?.ToLowerInvariant() switch {
"optional" or "false" or "no" => SqlConnectionEncryptOption.Optional,
"mandatory" or "true" or "yes" => SqlConnectionEncryptOption.Mandatory,
"strict" => SqlConnectionEncryptOption.Strict,
_ => default
};
csb.TrustServerCertificate = connectParams.Connection.TrustServerCertificate.HasValue ? connectParams.Connection.TrustServerCertificate.Value : false; csb.TrustServerCertificate = connectParams.Connection.TrustServerCertificate.HasValue ? connectParams.Connection.TrustServerCertificate.Value : false;
if (!string.IsNullOrEmpty(connectParams.Connection.HostNameInCertificate))
{
csb.HostNameInCertificate = connectParams.Connection.HostNameInCertificate;
}
return csb; return csb;
} }

View File

@@ -852,7 +852,7 @@ Streaming query statement contains a reference to missing output stream 'Missing
Assert.That(options.ObjectTypesDictionary, Is.Not.Null, "Object types dictionary is empty"); Assert.That(options.ObjectTypesDictionary, Is.Not.Null, "Object types dictionary is empty");
// Verify that the objects dictionary has all the item from Enum // Verify that the objects dictionary has all the item from Enum
Assert.That(options.ObjectTypesDictionary.Count, Is.EqualTo(Enum.GetNames(typeof(ObjectType)).Length), @"ObjectTypesDictionary is missing these objectTypes: {0}", Assert.That(options.ObjectTypesDictionary.Count, Is.EqualTo(Enum.GetNames(typeof(ObjectType)).Length), @"ObjectTypesDictionary is missing these objectTypes: {0}",
string.Join(", ", Enum.GetNames(typeof(ObjectType)).Except(options.ObjectTypesDictionary.Keys))); string.Join(", ", Enum.GetNames(typeof(ObjectType)).Except(options.ObjectTypesDictionary.Keys)));
// Verify the options in the objects dictionary exists in the ObjectType Enum // Verify the options in the objects dictionary exists in the ObjectType Enum
@@ -956,158 +956,158 @@ Streaming query statement contains a reference to missing output stream 'Missing
} }
} }
} }
}
[TestFixture] [TestFixture]
public class TSqlModelRequestTests public class TSqlModelRequestTests
{
private string TSqlModelTestFolder = string.Empty;
private DacFxService service = new DacFxService();
[SetUp]
public void Create()
{ {
TSqlModelTestFolder = Path.Combine("..", "..", "..", "DacFx", "TSqlModels", Guid.NewGuid().ToString()); private string TSqlModelTestFolder = string.Empty;
Directory.CreateDirectory(TSqlModelTestFolder);
}
[TearDown] private DacFxService service = new DacFxService();
public void CleanUp()
{
Directory.Delete(TSqlModelTestFolder, true);
}
/// <summary> [SetUp]
/// Verify the generate Tsql model operation public void Create()
/// </summary> {
[Test] TSqlModelTestFolder = Path.Combine("..", "..", "..", "DacFx", "TSqlModels", Guid.NewGuid().ToString());
public void GenerateTSqlModelFromSqlFiles() Directory.CreateDirectory(TSqlModelTestFolder);
{ }
string sqlTable1DefinitionPath = Path.Join(TSqlModelTestFolder, "table1.sql");
string sqlTable2DefinitionPath = Path.Join(TSqlModelTestFolder, "table2.sql"); [TearDown]
const string table1 = @"CREATE TABLE [dbo].[table1] public void CleanUp()
{
Directory.Delete(TSqlModelTestFolder, true);
}
/// <summary>
/// Verify the generate Tsql model operation
/// </summary>
[Test]
public void GenerateTSqlModelFromSqlFiles()
{
string sqlTable1DefinitionPath = Path.Join(TSqlModelTestFolder, "table1.sql");
string sqlTable2DefinitionPath = Path.Join(TSqlModelTestFolder, "table2.sql");
const string table1 = @"CREATE TABLE [dbo].[table1]
( (
[ID] INT NOT NULL PRIMARY KEY, [ID] INT NOT NULL PRIMARY KEY,
)"; )";
const string table2 = @"CREATE TABLE [dbo].[table2] const string table2 = @"CREATE TABLE [dbo].[table2]
( (
[ID] INT NOT NULL PRIMARY KEY, [ID] INT NOT NULL PRIMARY KEY,
)"; )";
// create sql file // create sql file
File.WriteAllText(sqlTable1DefinitionPath, table1); File.WriteAllText(sqlTable1DefinitionPath, table1);
File.WriteAllText(sqlTable2DefinitionPath, table2); File.WriteAllText(sqlTable2DefinitionPath, table2);
var generateTSqlScriptParams = new GenerateTSqlModelParams var generateTSqlScriptParams = new GenerateTSqlModelParams
{
ProjectUri = Path.Join(TSqlModelTestFolder, "test.sqlproj"),
ModelTargetVersion = "Sql160",
FilePaths = new[] { sqlTable1DefinitionPath, sqlTable2DefinitionPath }
};
GenerateTSqlModelOperation op = new GenerateTSqlModelOperation(generateTSqlScriptParams);
var model = op.GenerateTSqlModel();
var objects = model.GetObjects(DacQueryScopes.UserDefined, ModelSchema.Table).ToList();
Assert.That(model.Version.ToString(), Is.EqualTo(generateTSqlScriptParams.ModelTargetVersion), $"Model version is not equal to {generateTSqlScriptParams.ModelTargetVersion}");
Assert.That(objects, Is.Not.Empty, "Model is empty");
var tableNames = objects.Select(o => o.Name.ToString()).ToList();
Assert.That(tableNames.Count, Is.EqualTo(2), "Model was not populated correctly");
CollectionAssert.AreEquivalent(tableNames, new[] { "[dbo].[table1]", "[dbo].[table2]" }, "Table names do not match");
}
/// <summary>
/// Verify the generate Tsql model operation, creates an empty model when files are empty
/// </summary>
[Test]
public void GenerateEmptyTSqlModel()
{ {
ProjectUri = Path.Join(TSqlModelTestFolder, "test.sqlproj"), var generateTSqlScriptParams = new GenerateTSqlModelParams
ModelTargetVersion = "Sql160", {
FilePaths = new[] { sqlTable1DefinitionPath, sqlTable2DefinitionPath } ProjectUri = Path.Join(TSqlModelTestFolder, "test.sqlproj"),
}; ModelTargetVersion = "Sql160",
FilePaths = new string[] { }
};
GenerateTSqlModelOperation op = new GenerateTSqlModelOperation(generateTSqlScriptParams); GenerateTSqlModelOperation op = new GenerateTSqlModelOperation(generateTSqlScriptParams);
var model = op.GenerateTSqlModel(); var model = op.GenerateTSqlModel();
var objects = model.GetObjects(DacQueryScopes.UserDefined, ModelSchema.Table).ToList();
Assert.That(model.Version.ToString(), Is.EqualTo(generateTSqlScriptParams.ModelTargetVersion), $"Model version is not equal to {generateTSqlScriptParams.ModelTargetVersion}"); Assert.That(model.GetObjects(DacQueryScopes.UserDefined, ModelSchema.Table).ToList().Count, Is.EqualTo(0), "Model is not empty");
Assert.That(objects, Is.Not.Empty, "Model is empty"); Assert.That(model.Version.ToString(), Is.EqualTo(generateTSqlScriptParams.ModelTargetVersion), $"Model version is not equal to {generateTSqlScriptParams.ModelTargetVersion}");
}
var tableNames = objects.Select(o => o.Name.ToString()).ToList(); /// <summary>
/// Verify the generate TSql Model handle
Assert.That(tableNames.Count, Is.EqualTo(2), "Model was not populated correctly"); /// </summary>
CollectionAssert.AreEquivalent(tableNames, new[] { "[dbo].[table1]", "[dbo].[table2]" }, "Table names do not match"); [Test]
} public async Task VerifyGenerateTSqlModelHandle()
/// <summary>
/// Verify the generate Tsql model operation, creates an empty model when files are empty
/// </summary>
[Test]
public void GenerateEmptyTSqlModel()
{
var generateTSqlScriptParams = new GenerateTSqlModelParams
{ {
ProjectUri = Path.Join(TSqlModelTestFolder, "test.sqlproj"), var generateTSqlScriptParams = new GenerateTSqlModelParams
ModelTargetVersion = "Sql160", {
FilePaths = new string[] { } ProjectUri = Path.Join(TSqlModelTestFolder, "test.sqlproj"),
}; ModelTargetVersion = "Sql160",
FilePaths = new string[] { }
};
GenerateTSqlModelOperation op = new GenerateTSqlModelOperation(generateTSqlScriptParams); var requestContext = new Mock<RequestContext<bool>>();
var model = op.GenerateTSqlModel(); requestContext.Setup((RequestContext<bool> x) => x.SendResult(It.Is<bool>((result) => result == true))).Returns(Task.FromResult(new object()));
Assert.That(model.GetObjects(DacQueryScopes.UserDefined, ModelSchema.Table).ToList().Count, Is.EqualTo(0), "Model is not empty"); await service.HandleGenerateTSqlModelRequest(generateTSqlScriptParams, requestContext.Object);
Assert.That(model.Version.ToString(), Is.EqualTo(generateTSqlScriptParams.ModelTargetVersion), $"Model version is not equal to {generateTSqlScriptParams.ModelTargetVersion}"); Assert.That(service.projectModels.Value, Contains.Key(generateTSqlScriptParams.ProjectUri), "Model was not stored under project uri");
} }
/// <summary> /// <summary>
/// Verify the generate TSql Model handle /// Verify the get objects TSql Model handle
/// </summary> /// </summary>
[Test] [Test]
public async Task VerifyGenerateTSqlModelHandle() public async Task VerifyGetObjectsFromTSqlModelHandle()
{
var generateTSqlScriptParams = new GenerateTSqlModelParams
{ {
ProjectUri = Path.Join(TSqlModelTestFolder, "test.sqlproj"), string sqlTable1DefinitionPath = Path.Join(TSqlModelTestFolder, "table1.sql");
ModelTargetVersion = "Sql160", string sqlTable2DefinitionPath = Path.Join(TSqlModelTestFolder, "table2.sql");
FilePaths = new string[] { } string view1DefinitionPath = Path.Join(TSqlModelTestFolder, "view1.sql");
}; const string table1 = @"CREATE TABLE [dbo].[table1]
var requestContext = new Mock<RequestContext<bool>>();
requestContext.Setup((RequestContext<bool> x) => x.SendResult(It.Is<bool>((result) => result == true))).Returns(Task.FromResult(new object()));
await service.HandleGenerateTSqlModelRequest(generateTSqlScriptParams, requestContext.Object);
Assert.That(service.projectModels.Value, Contains.Key(generateTSqlScriptParams.ProjectUri), "Model was not stored under project uri");
}
/// <summary>
/// Verify the get objects TSql Model handle
/// </summary>
[Test]
public async Task VerifyGetObjectsFromTSqlModelHandle()
{
string sqlTable1DefinitionPath = Path.Join(TSqlModelTestFolder, "table1.sql");
string sqlTable2DefinitionPath = Path.Join(TSqlModelTestFolder, "table2.sql");
string view1DefinitionPath = Path.Join(TSqlModelTestFolder, "view1.sql");
const string table1 = @"CREATE TABLE [dbo].[table1]
( (
[ID] INT NOT NULL PRIMARY KEY, [ID] INT NOT NULL PRIMARY KEY,
)"; )";
const string table2 = @"CREATE TABLE [dbo].[table2] const string table2 = @"CREATE TABLE [dbo].[table2]
( (
[ID] INT NOT NULL PRIMARY KEY, [ID] INT NOT NULL PRIMARY KEY,
)"; )";
const string view1 = "CREATE VIEW [dbo].[view1] AS SELECT dbo.table1.* FROM dbo.table1"; const string view1 = "CREATE VIEW [dbo].[view1] AS SELECT dbo.table1.* FROM dbo.table1";
// create sql file // create sql file
File.WriteAllText(sqlTable1DefinitionPath, table1); File.WriteAllText(sqlTable1DefinitionPath, table1);
File.WriteAllText(sqlTable2DefinitionPath, table2); File.WriteAllText(sqlTable2DefinitionPath, table2);
File.WriteAllText(view1DefinitionPath, view1); File.WriteAllText(view1DefinitionPath, view1);
var generateTSqlScriptParams = new GenerateTSqlModelParams var generateTSqlScriptParams = new GenerateTSqlModelParams
{ {
ProjectUri = Path.Join(TSqlModelTestFolder, "test.sqlproj"), ProjectUri = Path.Join(TSqlModelTestFolder, "test.sqlproj"),
ModelTargetVersion = "Sql160", ModelTargetVersion = "Sql160",
FilePaths = new[] { sqlTable1DefinitionPath, sqlTable2DefinitionPath } FilePaths = new[] { sqlTable1DefinitionPath, sqlTable2DefinitionPath }
}; };
GenerateTSqlModelOperation op = new GenerateTSqlModelOperation(generateTSqlScriptParams);
var model = op.GenerateTSqlModel();
service.projectModels.Value.TryAdd(generateTSqlScriptParams.ProjectUri, model); GenerateTSqlModelOperation op = new GenerateTSqlModelOperation(generateTSqlScriptParams);
var model = op.GenerateTSqlModel();
var getObjectsParams = new GetObjectsFromTSqlModelParams
{
ProjectUri = Path.Join(TSqlModelTestFolder, "test.sqlproj"),
ObjectTypes = new[] { "Table" }
};
var requestContext = new Mock<RequestContext<TSqlObjectInfo[]>>(); service.projectModels.Value.TryAdd(generateTSqlScriptParams.ProjectUri, model);
var actualResponse = new List<TSqlObjectInfo>();
requestContext.Setup(x => x.SendResult(It.IsAny<TSqlObjectInfo[]>()))
.Callback<TSqlObjectInfo[]>(actual => actualResponse = actual.ToList())
.Returns(Task.CompletedTask);
await service.HandleGetObjectsFromTSqlModelRequest(getObjectsParams, requestContext.Object);
Assert.IsNotNull(actualResponse); var getObjectsParams = new GetObjectsFromTSqlModelParams
Assert.AreEqual(actualResponse.Count, 2); {
CollectionAssert.AreEquivalent(actualResponse.Select(o => o.Name), new[] { "[dbo].[table1]", "[dbo].[table2]" }, "Table names do not match"); ProjectUri = Path.Join(TSqlModelTestFolder, "test.sqlproj"),
ObjectTypes = new[] { "Table" }
};
var requestContext = new Mock<RequestContext<TSqlObjectInfo[]>>();
var actualResponse = new List<TSqlObjectInfo>();
requestContext.Setup(x => x.SendResult(It.IsAny<TSqlObjectInfo[]>()))
.Callback<TSqlObjectInfo[]>(actual => actualResponse = actual.ToList())
.Returns(Task.CompletedTask);
await service.HandleGetObjectsFromTSqlModelRequest(getObjectsParams, requestContext.Object);
Assert.IsNotNull(actualResponse);
Assert.AreEqual(actualResponse.Count, 2);
CollectionAssert.AreEquivalent(actualResponse.Select(o => o.Name), new[] { "[dbo].[table1]", "[dbo].[table2]" }, "Table names do not match");
}
} }
} }

View File

@@ -46,11 +46,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility
} }
public static TestConnectionResult InitLiveConnectionInfo(string databaseName = null, string ownerUri = null) public static TestConnectionResult InitLiveConnectionInfo(string databaseName = null, string ownerUri = null)
{ => InitLiveConnectionInfoAsync(databaseName, ownerUri, ServiceLayer.Connection.ConnectionType.Default).ConfigureAwait(false).GetAwaiter().GetResult();
var task = InitLiveConnectionInfoAsync(databaseName, ownerUri, ServiceLayer.Connection.ConnectionType.Default);
task.Wait();
return task.Result;
}
public static async Task<TestConnectionResult> InitLiveConnectionInfoAsync(string databaseName = "master", string ownerUri = null, public static async Task<TestConnectionResult> InitLiveConnectionInfoAsync(string databaseName = "master", string ownerUri = null,
string connectionType = ServiceLayer.Connection.ConnectionType.Default, TestServerType serverType = TestServerType.OnPrem) string connectionType = ServiceLayer.Connection.ConnectionType.Default, TestServerType serverType = TestServerType.OnPrem)

View File

@@ -16,9 +16,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
public class ConnectionSetting public class ConnectionSetting
{ {
[JsonProperty("mssql.connections")] [JsonProperty("mssql.connections")]
public List<InstanceInfo> Connections { get; set; } public List<InstanceInfo>? Connections { get; set; }
public InstanceInfo GetConnectionProfile(string profileName, string serverName) public InstanceInfo? GetConnectionProfile(string profileName, string serverName)
{ {
if (!string.IsNullOrEmpty(profileName) && Connections != null) if (!string.IsNullOrEmpty(profileName) && Connections != null)
{ {
@@ -28,7 +28,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
return byProfileName; return byProfileName;
} }
} }
return Connections.FirstOrDefault(x => x.ServerName == serverName); return Connections?.FirstOrDefault(x => x.ServerName == serverName);
} }
} }
@@ -47,23 +47,29 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
public string ServerName { get; set; } public string ServerName { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string Database { get; set; } public string? Database { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string User { get; set; } public string? User { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string Password { get; set; } public string? Password { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string ProfileName { get; set; } public string? ProfileName { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string? Encrypt { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string? HostNameInCertificate { get; set; }
public TestServerType ServerType { get; set; } public TestServerType ServerType { get; set; }
public AuthenticationType AuthenticationType { get; set; } public AuthenticationType AuthenticationType { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string RemoteSharePath { get; set; } public string? RemoteSharePath { get; set; }
public int ConnectTimeout { get; set; } public int ConnectTimeout { get; set; }

View File

@@ -35,6 +35,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
{ {
DataSource = connectParams.Connection.ServerName, DataSource = connectParams.Connection.ServerName,
InitialCatalog = connectParams.Connection.DatabaseName, InitialCatalog = connectParams.Connection.DatabaseName,
TrustServerCertificate = true
}; };
if (connectParams.Connection.AuthenticationType == "Integrated") if (connectParams.Connection.AuthenticationType == "Integrated")
@@ -45,6 +46,23 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
{ {
builder.UserID = connectParams.Connection.UserName; builder.UserID = connectParams.Connection.UserName;
builder.Password = connectParams.Connection.Password; builder.Password = connectParams.Connection.Password;
builder.PersistSecurityInfo = true;
}
if (!string.IsNullOrEmpty(connectParams.Connection.Encrypt))
{
builder.Encrypt = connectParams.Connection.Encrypt switch
{
"optional" or "false" or "no" => SqlConnectionEncryptOption.Optional,
"mandatory" or "true" or "yes" => SqlConnectionEncryptOption.Mandatory,
"strict" => SqlConnectionEncryptOption.Strict,
_ => SqlConnectionEncryptOption.Optional
};
}
if (!string.IsNullOrEmpty(connectParams.Connection.HostNameInCertificate))
{
builder.HostNameInCertificate = connectParams.Connection.HostNameInCertificate;
} }
return builder.ToString(); return builder.ToString();

View File

@@ -6,6 +6,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using Microsoft.Data.SqlClient;
using Microsoft.SqlTools.Credentials.Contracts; using Microsoft.SqlTools.Credentials.Contracts;
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
using NUnit.Framework; using NUnit.Framework;
@@ -37,12 +38,12 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
} }
} }
public static InstanceInfo SqlAzure public static InstanceInfo? SqlAzure
{ {
get { return GetInstance(SqlAzureInstanceKey); } get { return GetInstance(SqlAzureInstanceKey); }
} }
public static InstanceInfo SqlOnPrem public static InstanceInfo? SqlOnPrem
{ {
get { return GetInstance(SqlOnPremInstanceKey); } get { return GetInstance(SqlOnPremInstanceKey); }
} }
@@ -50,30 +51,23 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
/// <summary> /// <summary>
/// Returns the SQL connection info for given version key /// Returns the SQL connection info for given version key
/// </summary> /// </summary>
public static InstanceInfo GetInstance(string key) public static InstanceInfo? GetInstance(string key)
{ {
InstanceInfo instanceInfo; connectionProfilesCache.TryGetValue(key, out InstanceInfo? instanceInfo);
connectionProfilesCache.TryGetValue(key, out instanceInfo);
Assert.True(instanceInfo != null, string.Format(CultureInfo.InvariantCulture, "Cannot find any instance for version key: {0}", key)); Assert.True(instanceInfo != null, string.Format(CultureInfo.InvariantCulture, "Cannot find any instance for version key: {0}", key));
return instanceInfo; return instanceInfo;
} }
public ConnectParams GetConnectionParameters(string key = SqlOnPremInstanceKey, string databaseName = null) public ConnectParams? GetConnectionParameters(string key = SqlOnPremInstanceKey, string databaseName = null)
{ {
InstanceInfo instanceInfo = GetInstance(key); InstanceInfo? instanceInfo = GetInstance(key);
if (instanceInfo != null) return instanceInfo != null ? CreateConnectParams(instanceInfo, key, databaseName) : null;
{
ConnectParams connectParam = CreateConnectParams(instanceInfo, key, databaseName);
return connectParam;
}
return null;
} }
/// <summary> /// <summary>
/// Returns database connection parameters for given server type /// Returns database connection parameters for given server type
/// </summary> /// </summary>
public ConnectParams GetConnectionParameters(TestServerType serverType = TestServerType.OnPrem, string databaseName = null) public ConnectParams? GetConnectionParameters(TestServerType serverType = TestServerType.OnPrem, string databaseName = null)
{ {
string key = ConvertServerTypeToVersionKey(serverType); string key = ConvertServerTypeToVersionKey(serverType);
return GetConnectionParameters(key, databaseName); return GetConnectionParameters(key, databaseName);
@@ -94,11 +88,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
Console.WriteLine("DBTestInstance not configured. Run 'dotnet run Microsoft.SqlTools.ServiceLayer.TestEnvConfig' from the command line to configure"); Console.WriteLine("DBTestInstance not configured. Run 'dotnet run Microsoft.SqlTools.ServiceLayer.TestEnvConfig' from the command line to configure");
} }
if (testServers != null && settings != null) if (testServers != null)
{ {
foreach (var serverIdentity in testServers) foreach (var serverIdentity in testServers)
{ {
var instance = settings != null ? settings.GetConnectionProfile(serverIdentity.ProfileName, serverIdentity.ServerName) : null; var instance = settings?.GetConnectionProfile(serverIdentity.ProfileName, serverIdentity.ServerName);
if (instance?.ServerType == TestServerType.None) if (instance?.ServerType == TestServerType.None)
{ {
instance.ServerType = serverIdentity.ServerType; instance.ServerType = serverIdentity.ServerType;
@@ -106,7 +100,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
} }
} }
} }
if (settings != null) if (settings?.Connections != null)
{ {
foreach (var instance in settings.Connections) foreach (var instance in settings.Connections)
{ {
@@ -162,12 +156,38 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
ConnectParams connectParams = new ConnectParams(); ConnectParams connectParams = new ConnectParams();
connectParams.Connection = new ConnectionDetails(); connectParams.Connection = new ConnectionDetails();
connectParams.Connection.ServerName = connectionProfile.ServerName; connectParams.Connection.ServerName = connectionProfile.ServerName;
connectParams.Connection.DatabaseName = connectionProfile.Database;
connectParams.Connection.DatabaseDisplayName = connectionProfile.Database; if (!string.IsNullOrEmpty(connectionProfile.Database))
connectParams.Connection.UserName = connectionProfile.User; {
connectParams.Connection.Password = connectionProfile.Password; connectParams.Connection.DatabaseName = connectionProfile.Database;
connectParams.Connection.MaxPoolSize = 200; connectParams.Connection.DatabaseDisplayName = connectionProfile.Database;
}
if (!string.IsNullOrEmpty(connectionProfile.User))
{
connectParams.Connection.UserName = connectionProfile.User;
}
if (!string.IsNullOrEmpty(connectionProfile.Password))
{
connectParams.Connection.Password = connectionProfile.Password;
}
connectParams.Connection.AuthenticationType = connectionProfile.AuthenticationType.ToString(); connectParams.Connection.AuthenticationType = connectionProfile.AuthenticationType.ToString();
connectParams.Connection.MaxPoolSize = 200;
if (!string.IsNullOrEmpty(connectionProfile.Encrypt))
{
connectParams.Connection.Encrypt = connectionProfile.Encrypt;
}
else
{
connectParams.Connection.Encrypt = SqlConnectionEncryptOption.Optional.ToString();
}
if (!string.IsNullOrEmpty(connectionProfile.HostNameInCertificate))
{
connectParams.Connection.HostNameInCertificate = connectionProfile.HostNameInCertificate;
}
if (!string.IsNullOrEmpty(databaseName)) if (!string.IsNullOrEmpty(databaseName))
{ {
connectParams.Connection.DatabaseName = databaseName; connectParams.Connection.DatabaseName = databaseName;
@@ -176,9 +196,10 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
if (key == SqlAzureInstanceKey || key == SqlAzureInstanceKey) if (key == SqlAzureInstanceKey || key == SqlAzureInstanceKey)
{ {
connectParams.Connection.ConnectTimeout = 30; connectParams.Connection.ConnectTimeout = 30;
connectParams.Connection.Encrypt = true; connectParams.Connection.Encrypt = SqlConnectionEncryptOption.Mandatory.ToString();
connectParams.Connection.TrustServerCertificate = false; connectParams.Connection.TrustServerCertificate = false;
} }
return connectParams; return connectParams;
} }
} }

View File

@@ -25,6 +25,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection
var expectedForStrings = default(string); var expectedForStrings = default(string);
var expectedForInt = default(int?); var expectedForInt = default(int?);
var expectedForBoolean = default(bool?); var expectedForBoolean = default(bool?);
var expectedEncryptOption = default(string?);
Assert.AreEqual(details.ApplicationIntent, expectedForStrings); Assert.AreEqual(details.ApplicationIntent, expectedForStrings);
Assert.AreEqual(details.ApplicationName, expectedForStrings); Assert.AreEqual(details.ApplicationName, expectedForStrings);
@@ -48,13 +49,14 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection
Assert.AreEqual(details.ColumnEncryptionSetting, expectedForStrings); Assert.AreEqual(details.ColumnEncryptionSetting, expectedForStrings);
Assert.AreEqual(details.EnclaveAttestationUrl, expectedForStrings); Assert.AreEqual(details.EnclaveAttestationUrl, expectedForStrings);
Assert.AreEqual(details.EnclaveAttestationProtocol, expectedForStrings); Assert.AreEqual(details.EnclaveAttestationProtocol, expectedForStrings);
Assert.AreEqual(details.Encrypt, expectedForBoolean); Assert.AreEqual(details.Encrypt, expectedEncryptOption);
Assert.AreEqual(details.MultipleActiveResultSets, expectedForBoolean); Assert.AreEqual(details.MultipleActiveResultSets, expectedForBoolean);
Assert.AreEqual(details.MultiSubnetFailover, expectedForBoolean); Assert.AreEqual(details.MultiSubnetFailover, expectedForBoolean);
Assert.AreEqual(details.PersistSecurityInfo, expectedForBoolean); Assert.AreEqual(details.PersistSecurityInfo, expectedForBoolean);
Assert.AreEqual(details.Pooling, expectedForBoolean); Assert.AreEqual(details.Pooling, expectedForBoolean);
Assert.AreEqual(details.Replication, expectedForBoolean); Assert.AreEqual(details.Replication, expectedForBoolean);
Assert.AreEqual(details.TrustServerCertificate, expectedForBoolean); Assert.AreEqual(details.TrustServerCertificate, expectedForBoolean);
Assert.AreEqual(details.HostNameInCertificate, expectedForStrings);
Assert.AreEqual(details.Port, expectedForInt); Assert.AreEqual(details.Port, expectedForInt);
} }
@@ -88,13 +90,14 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection
details.ColumnEncryptionSetting = expectedForStrings + index++; details.ColumnEncryptionSetting = expectedForStrings + index++;
details.EnclaveAttestationProtocol = expectedForStrings + index++; details.EnclaveAttestationProtocol = expectedForStrings + index++;
details.EnclaveAttestationUrl = expectedForStrings + index++; details.EnclaveAttestationUrl = expectedForStrings + index++;
details.Encrypt = (index++ % 2 == 0); details.Encrypt = expectedForStrings + index++;
details.MultipleActiveResultSets = (index++ % 2 == 0); details.MultipleActiveResultSets = (index++ % 2 == 0);
details.MultiSubnetFailover = (index++ % 2 == 0); details.MultiSubnetFailover = (index++ % 2 == 0);
details.PersistSecurityInfo = (index++ % 2 == 0); details.PersistSecurityInfo = (index++ % 2 == 0);
details.Pooling = (index++ % 2 == 0); details.Pooling = (index++ % 2 == 0);
details.Replication = (index++ % 2 == 0); details.Replication = (index++ % 2 == 0);
details.TrustServerCertificate = (index++ % 2 == 0); details.TrustServerCertificate = (index++ % 2 == 0);
details.HostNameInCertificate = expectedForStrings + index++;
details.Port = expectedForInt + index++; details.Port = expectedForInt + index++;
index = 0; index = 0;
@@ -120,13 +123,14 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection
Assert.AreEqual(details.ColumnEncryptionSetting, expectedForStrings + index++); Assert.AreEqual(details.ColumnEncryptionSetting, expectedForStrings + index++);
Assert.AreEqual(details.EnclaveAttestationProtocol, expectedForStrings + index++); Assert.AreEqual(details.EnclaveAttestationProtocol, expectedForStrings + index++);
Assert.AreEqual(details.EnclaveAttestationUrl, expectedForStrings + index++); Assert.AreEqual(details.EnclaveAttestationUrl, expectedForStrings + index++);
Assert.AreEqual(details.Encrypt, (index++ % 2 == 0)); Assert.AreEqual(details.Encrypt, expectedForStrings + index++);
Assert.AreEqual(details.MultipleActiveResultSets, (index++ % 2 == 0)); Assert.AreEqual(details.MultipleActiveResultSets, (index++ % 2 == 0));
Assert.AreEqual(details.MultiSubnetFailover, (index++ % 2 == 0)); Assert.AreEqual(details.MultiSubnetFailover, (index++ % 2 == 0));
Assert.AreEqual(details.PersistSecurityInfo, (index++ % 2 == 0)); Assert.AreEqual(details.PersistSecurityInfo, (index++ % 2 == 0));
Assert.AreEqual(details.Pooling, (index++ % 2 == 0)); Assert.AreEqual(details.Pooling, (index++ % 2 == 0));
Assert.AreEqual(details.Replication, (index++ % 2 == 0)); Assert.AreEqual(details.Replication, (index++ % 2 == 0));
Assert.AreEqual(details.TrustServerCertificate, (index++ % 2 == 0)); Assert.AreEqual(details.TrustServerCertificate, (index++ % 2 == 0));
Assert.AreEqual(details.HostNameInCertificate, expectedForStrings + index++);
Assert.AreEqual(details.Port, (expectedForInt + index++)); Assert.AreEqual(details.Port, (expectedForInt + index++));
} }
@@ -161,16 +165,17 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection
details.ColumnEncryptionSetting = expectedForStrings + index++; details.ColumnEncryptionSetting = expectedForStrings + index++;
details.EnclaveAttestationProtocol = expectedForStrings + index++; details.EnclaveAttestationProtocol = expectedForStrings + index++;
details.EnclaveAttestationUrl = expectedForStrings + index++; details.EnclaveAttestationUrl = expectedForStrings + index++;
details.Encrypt = (index++ % 2 == 0); details.Encrypt = expectedForStrings + index++;
details.MultipleActiveResultSets = (index++ % 2 == 0); details.MultipleActiveResultSets = (index++ % 2 == 0);
details.MultiSubnetFailover = (index++ % 2 == 0); details.MultiSubnetFailover = (index++ % 2 == 0);
details.PersistSecurityInfo = (index++ % 2 == 0); details.PersistSecurityInfo = (index++ % 2 == 0);
details.Pooling = (index++ % 2 == 0); details.Pooling = (index++ % 2 == 0);
details.Replication = (index++ % 2 == 0); details.Replication = (index++ % 2 == 0);
details.TrustServerCertificate = (index++ % 2 == 0); details.TrustServerCertificate = (index++ % 2 == 0);
details.HostNameInCertificate = expectedForStrings + index++;
details.Port = expectedForInt + index++; details.Port = expectedForInt + index++;
if(optionMetadata.Options.Count() != details.Options.Count) if (optionMetadata.Options.Count() != details.Options.Count)
{ {
var optionsNotInMetadata = details.Options.Where(o => !optionMetadata.Options.Any(m => m.Name == o.Key)); var optionsNotInMetadata = details.Options.Where(o => !optionMetadata.Options.Any(m => m.Name == o.Key));
var optionNames = optionsNotInMetadata.Any() ? optionsNotInMetadata.Select(s => s.Key).Aggregate((i, j) => i + "," + j) : null; var optionNames = optionsNotInMetadata.Any() ? optionsNotInMetadata.Select(s => s.Key).Aggregate((i, j) => i + "," + j) : null;
@@ -180,7 +185,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection
{ {
var metadata = optionMetadata.Options.FirstOrDefault(x => x.Name == option.Key); var metadata = optionMetadata.Options.FirstOrDefault(x => x.Name == option.Key);
Assert.NotNull(metadata); Assert.NotNull(metadata);
if(metadata.ValueType == ConnectionOption.ValueTypeString) if (metadata.ValueType == ConnectionOption.ValueTypeString)
{ {
Assert.True(option.Value is string); Assert.True(option.Value is string);
} }
@@ -200,7 +205,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection
public void SettingConnectiomTimeoutToLongShouldStillReturnInt() public void SettingConnectiomTimeoutToLongShouldStillReturnInt()
{ {
ConnectionDetails details = new ConnectionDetails(); ConnectionDetails details = new ConnectionDetails();
long timeout = 30; long timeout = 30;
int? expectedValue = 30; int? expectedValue = 30;
details.Options["connectTimeout"] = timeout; details.Options["connectTimeout"] = timeout;
@@ -226,44 +231,21 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection
} }
[Test] [Test]
public void SettingEncryptToStringShouldStillReturnBoolean() public void SettingEncrypShouldReturnExpectedEncryptOption()
{ {
ConnectionDetails details = new ConnectionDetails(); ConnectionDetails details = new ConnectionDetails();
details.Options["Encrypt"] = true.ToString();
Assert.That(details.Encrypt, Is.EqualTo(true.ToString()), "Encrypt should be Mandatory.");
string encrypt = "True"; details.Options["Encrypt"] = "Strict";
bool? expectedValue = true; Assert.That(details.Encrypt, Is.EqualTo("Strict"), "Encrypt should be Strict.");
details.Options["encrypt"] = encrypt;
Assert.AreEqual(details.Encrypt, expectedValue);
} }
[Test] [Test]
public void SettingEncryptToLowecaseStringShouldStillReturnBoolean() public void EncryptShouldReturnMandatoryIfNotSet()
{ {
ConnectionDetails details = new ConnectionDetails(); ConnectionDetails details = new ConnectionDetails();
Assert.That(details.Encrypt, Is.Null, "Encrypt should be null when set to null");
string encrypt = "true";
bool? expectedValue = true;
details.Options["encrypt"] = encrypt;
Assert.AreEqual(details.Encrypt, expectedValue);
}
[Test]
public void EncryptShouldReturnNullIfNotSet()
{
ConnectionDetails details = new ConnectionDetails();
bool? expectedValue = null;
Assert.AreEqual(details.Encrypt, expectedValue);
}
[Test]
public void EncryptShouldReturnNullIfSetToNull()
{
ConnectionDetails details = new ConnectionDetails();
details.Options["encrypt"] = null;
int? expectedValue = null;
Assert.AreEqual(details.ConnectTimeout, expectedValue);
} }
[Test] [Test]
@@ -273,11 +255,12 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection
long timeout = long.MaxValue; long timeout = long.MaxValue;
int? expectedValue = null; int? expectedValue = null;
string? expectedEncryptValue = "Mandatory";
details.Options["connectTimeout"] = timeout; details.Options["connectTimeout"] = timeout;
details.Options["encrypt"] = true; details.Options["encrypt"] = expectedEncryptValue;
Assert.AreEqual(details.ConnectTimeout, expectedValue); Assert.That(details.ConnectTimeout, Is.EqualTo(expectedValue), "Connect Timeout not as expected");
Assert.AreEqual(true, details.Encrypt); Assert.That(details.Encrypt, Is.EqualTo("Mandatory"), "Encrypt should be mandatory.");
} }
} }
} }

View File

@@ -273,7 +273,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection
/// provided as a parameter. /// provided as a parameter.
/// </summary> /// </summary>
[Test] [Test]
public async Task CanConnectWithEmptyDatabaseName([Values(null, "")]string databaseName) public async Task CanConnectWithEmptyDatabaseName([Values(null, "")] string databaseName)
{ {
// Connect // Connect
var connectionDetails = TestObjects.GetTestConnectionDetails(); var connectionDetails = TestObjects.GetTestConnectionDetails();
@@ -294,7 +294,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection
/// provided as a parameter. /// provided as a parameter.
/// </summary> /// </summary>
[Test] [Test]
public async Task ConnectToDefaultDatabaseRespondsWithActualDbName([Values("master", "nonMasterDb")]string expectedDbName) public async Task ConnectToDefaultDatabaseRespondsWithActualDbName([Values("master", "nonMasterDb")] string expectedDbName)
{ {
// Given connecting with empty database name will return the expected DB name // Given connecting with empty database name will return the expected DB name
var connectionMock = new Mock<DbConnection> { CallBase = true }; var connectionMock = new Mock<DbConnection> { CallBase = true };
@@ -440,11 +440,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection
new object[] {"Integrated", "file://my/sample/file.sql", null, "test", "sa", "123456"}, new object[] {"Integrated", "file://my/sample/file.sql", null, "test", "sa", "123456"},
new object[] {"Integrated", "", "my-server", "test", "sa", "123456"}, new object[] {"Integrated", "", "my-server", "test", "sa", "123456"},
new object[] {"Integrated", "file://my/sample/file.sql", "", "test", "sa", "123456"} new object[] {"Integrated", "file://my/sample/file.sql", "", "test", "sa", "123456"}
}; };
/// <summary> /// <summary>
/// Verify that when connecting with invalid parameters, an error is thrown. /// Verify that when connecting with invalid parameters, an error is thrown.
/// </summary> /// </summary>
[Test, TestCaseSource(nameof(invalidParameters))] [Test, TestCaseSource(nameof(invalidParameters))]
public async Task ConnectingWithInvalidParametersYieldsErrorMessage(string authType, string ownerUri, string server, string database, string userName, string password) public async Task ConnectingWithInvalidParametersYieldsErrorMessage(string authType, string ownerUri, string server, string database, string userName, string password)
{ {
// Connect with invalid parameters // Connect with invalid parameters
@@ -521,8 +521,9 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection
{ {
new object[] {"AuthenticationType", "Integrated", "Integrated Security" }, new object[] {"AuthenticationType", "Integrated", "Integrated Security" },
new object[] {"AuthenticationType", "SqlLogin", ""}, new object[] {"AuthenticationType", "SqlLogin", ""},
new object[] {"Encrypt", true, "Encrypt"}, new object[] {"Encrypt", "Mandatory", "Encrypt"},
new object[] {"Encrypt", false, "Encrypt"}, new object[] {"Encrypt", "Optional", "Encrypt"},
new object[] {"Encrypt", "Strict", "Encrypt"},
new object[] {"ColumnEncryptionSetting", "Enabled", "Column Encryption Setting=Enabled"}, new object[] {"ColumnEncryptionSetting", "Enabled", "Column Encryption Setting=Enabled"},
new object[] {"ColumnEncryptionSetting", "Disabled", "Column Encryption Setting=Disabled"}, new object[] {"ColumnEncryptionSetting", "Disabled", "Column Encryption Setting=Disabled"},
new object[] {"ColumnEncryptionSetting", "enabled", "Column Encryption Setting=Enabled"}, new object[] {"ColumnEncryptionSetting", "enabled", "Column Encryption Setting=Enabled"},
@@ -533,6 +534,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection
new object[] {"ColumnEncryptionSetting", "DiSaBlEd", "Column Encryption Setting=Disabled"}, new object[] {"ColumnEncryptionSetting", "DiSaBlEd", "Column Encryption Setting=Disabled"},
new object[] {"TrustServerCertificate", true, "Trust Server Certificate"}, new object[] {"TrustServerCertificate", true, "Trust Server Certificate"},
new object[] {"TrustServerCertificate", false, "Trust Server Certificate"}, new object[] {"TrustServerCertificate", false, "Trust Server Certificate"},
new object[] {"HostNameInCertificate", "hostname", "Host Name In Certificate"},
new object[] {"PersistSecurityInfo", true, "Persist Security Info"}, new object[] {"PersistSecurityInfo", true, "Persist Security Info"},
new object[] {"PersistSecurityInfo", false, "Persist Security Info"}, new object[] {"PersistSecurityInfo", false, "Persist Security Info"},
new object[] {"ConnectTimeout", 15, "Connect Timeout"}, new object[] {"ConnectTimeout", 15, "Connect Timeout"},
@@ -603,7 +605,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection
.SetValue(details, propertyValue); .SetValue(details, propertyValue);
// Test that a connection string can be created without exceptions // Test that a connection string can be created without exceptions
string connectionString = ConnectionService.BuildConnectionString(details); string connectionString = ConnectionService.BuildConnectionString(details);
Assert.That(connectionString, Contains.Substring(connectionStringMarker), "Verify that the parameter is in the connection string"); Assert.That(connectionString, Contains.Substring(connectionStringMarker), "Verify that the parameter is in the connection string");
} }
@@ -613,6 +615,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection
new object[] {"ColumnEncryptionSetting", "NotAValidColumnEncryptionSetting" }, new object[] {"ColumnEncryptionSetting", "NotAValidColumnEncryptionSetting" },
new object[] {"EnclaveAttestationProtocol", "NotAValidEnclaveAttestationProtocol" }, new object[] {"EnclaveAttestationProtocol", "NotAValidEnclaveAttestationProtocol" },
}; };
/// <summary> /// <summary>
/// Build connection string with an invalid property type /// Build connection string with an invalid property type
/// </summary> /// </summary>
@@ -625,7 +628,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection
Assert.Throws<ArgumentException>(() => ConnectionService.BuildConnectionString(details)); Assert.Throws<ArgumentException>(() => ConnectionService.BuildConnectionString(details));
} }
private static readonly Tuple<string,object>[][] optionCombos = private static readonly Tuple<string, object>[][] optionCombos =
{ {
new [] new []
{ {
@@ -647,6 +650,29 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection
} }
}; };
private static readonly object[] EncryptionCombinations =
{
new object[] { SqlConnectionEncryptOption.Optional, SqlConnectionEncryptOption.Optional },
new object[] { SqlConnectionEncryptOption.Mandatory, SqlConnectionEncryptOption.Mandatory },
new object[] { SqlConnectionEncryptOption.Strict, SqlConnectionEncryptOption.Strict },
};
/// <summary>
/// Verify that Strict Encryption parameters can be built into a connection string for connecting.
/// </summary>
[Test, TestCaseSource(nameof(EncryptionCombinations))]
public void ConnectingWithStrictEncryptionBuildsConnectionString(SqlConnectionEncryptOption encryptValue, SqlConnectionEncryptOption expected)
{
// Create a test connection details object and set the property to a specific value
ConnectionDetails details = TestObjects.GetTestConnectionDetails();
details.Encrypt = encryptValue.ToString();
// Test that a connection string can be created without exceptions
string connectionString = ConnectionService.BuildConnectionString(details);
Assert.That(connectionString, Contains.Substring("Encrypt=" + expected.ToString()), "Encrypt not as expected.");
}
/// <summary> /// <summary>
/// Build connection string with an invalid property combinations /// Build connection string with an invalid property combinations
/// </summary> /// </summary>
@@ -1137,10 +1163,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection
/// Test that the connection summary comparer creates a hash code correctly /// Test that the connection summary comparer creates a hash code correctly
/// </summary> /// </summary>
[Test] [Test]
public void TestConnectionSummaryComparerHashCode([Values]bool objectNull, public void TestConnectionSummaryComparerHashCode([Values] bool objectNull,
[Values(null, "server")]string serverName, [Values(null, "server")] string serverName,
[Values(null, "test")]string databaseName, [Values(null, "test")] string databaseName,
[Values(null, "sa")]string userName) [Values(null, "sa")] string userName)
{ {
// Given a connection summary and comparer object // Given a connection summary and comparer object
ConnectionSummary summary = null; ConnectionSummary summary = null;
@@ -1341,13 +1367,13 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection
} }
[Test] [Test]
public async Task GetOrOpenNullOwnerUri([Values(null, "")]string ownerUri) public async Task GetOrOpenNullOwnerUri([Values(null, "")] string ownerUri)
{ {
// If: I have a connection service and I ask for a connection with an invalid ownerUri // If: I have a connection service and I ask for a connection with an invalid ownerUri
// Then: An exception should be thrown // Then: An exception should be thrown
var service = TestObjects.GetTestConnectionService(); var service = TestObjects.GetTestConnectionService();
Assert.ThrowsAsync<ArgumentException>( Assert.ThrowsAsync<ArgumentException>(
() => service.GetOrOpenConnection(ownerUri, ConnectionType.Default)); () => service.GetOrOpenConnection(ownerUri, ConnectionType.Default));
} }
[Test] [Test]
@@ -1643,19 +1669,43 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection
// If we make a connection to a live database // If we make a connection to a live database
ConnectionService service = ConnectionService.Instance; ConnectionService service = ConnectionService.Instance;
var connectionString = "Server=tcp:{servername},1433;Initial Catalog={databasename};Persist Security Info=False;User ID={your_username};Password={your_password};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"; var connectionString = "Server=tcp:{servername},1433;Initial Catalog={databasename};Persist Security Info=False;User ID={your_username};Password={your_password};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;HostNameInCertificate={servername}";
var details = service.ParseConnectionString(connectionString); var details = service.ParseConnectionString(connectionString);
Assert.That(details.ServerName, Is.EqualTo("tcp:{servername},1433"), "Unexpected server name");
Assert.That(details.DatabaseName, Is.EqualTo("{databasename}"), "Unexpected database name");
Assert.That(details.UserName, Is.EqualTo("{your_username}"), "Unexpected username");
Assert.That(details.Password, Is.EqualTo("{your_password}"), "Unexpected password");
Assert.That(details.PersistSecurityInfo, Is.False, "Unexpected Persist Security Info");
Assert.That(details.MultipleActiveResultSets, Is.False, "Unexpected Multiple Active Result Sets value");
Assert.That(details.Encrypt, Is.EqualTo("True"), "Unexpected Encrypt value");
Assert.That(details.TrustServerCertificate, Is.False, "Unexpected database name value");
Assert.That(details.HostNameInCertificate, Is.EqualTo("{servername}"), "Unexpected Host Name in Certificate value");
Assert.That(details.ConnectTimeout, Is.EqualTo(30), "Unexpected Connect Timeout value");
}
Assert.AreEqual("tcp:{servername},1433", details.ServerName); /// <summary>
Assert.AreEqual("{databasename}", details.DatabaseName); /// Test ParseConnectionString
Assert.AreEqual("{your_username}", details.UserName); /// </summary>
Assert.AreEqual("{your_password}", details.Password); [Test]
Assert.AreEqual(false, details.PersistSecurityInfo); public void ParseConnectionStringTest_StrictEncryption()
Assert.AreEqual(false, details.MultipleActiveResultSets); {
Assert.AreEqual(true, details.Encrypt); // If we make a connection to a live database
Assert.AreEqual(false, details.TrustServerCertificate); ConnectionService service = ConnectionService.Instance;
Assert.AreEqual(30, details.ConnectTimeout);
var connectionString = "Server=tcp:{servername},1433;Initial Catalog={databasename};Persist Security Info=False;User ID={your_username};Password={your_password};MultipleActiveResultSets=False;Encrypt=Strict;TrustServerCertificate=False;Connection Timeout=30;HostNameInCertificate={servername}";
var details = service.ParseConnectionString(connectionString);
Assert.That(details.ServerName, Is.EqualTo("tcp:{servername},1433"), "Unexpected server name");
Assert.That(details.DatabaseName, Is.EqualTo("{databasename}"), "Unexpected database name");
Assert.That(details.UserName, Is.EqualTo("{your_username}"), "Unexpected username");
Assert.That(details.Password, Is.EqualTo("{your_password}"), "Unexpected password");
Assert.That(details.PersistSecurityInfo, Is.False, "Unexpected Persist Security Info");
Assert.That(details.MultipleActiveResultSets, Is.False, "Unexpected Multiple Active Result Sets value");
Assert.That(details.Encrypt, Is.EqualTo(SqlConnectionEncryptOption.Strict.ToString()), "Unexpected Encrypt value");
Assert.That(details.TrustServerCertificate, Is.False, "Unexpected database name value");
Assert.That(details.HostNameInCertificate, Is.EqualTo("{servername}"), "Unexpected Host Name in Certificate value");
Assert.That(details.ConnectTimeout, Is.EqualTo(30), "Unexpected Connect Timeout value");
} }
[Test] [Test]

View File

@@ -169,7 +169,6 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ResourceProvider.Fakes
// connectionStringBuilder.ConnectTimeout = 123; // connectionStringBuilder.ConnectTimeout = 123;
// connectionStringBuilder.Encrypt = true; // connectionStringBuilder.Encrypt = true;
// connectionStringBuilder.ApplicationIntent = ApplicationIntent.ReadWrite; // connectionStringBuilder.ApplicationIntent = ApplicationIntent.ReadWrite;
// connectionStringBuilder.AsynchronousProcessing = true;
// connectionStringBuilder.MaxPoolSize = 45; // connectionStringBuilder.MaxPoolSize = 45;
// connectionStringBuilder.MinPoolSize = 3; // connectionStringBuilder.MinPoolSize = 3;
// connectionStringBuilder.PacketSize = 600; // connectionStringBuilder.PacketSize = 600;