Skip to content

Commit

Permalink
Enable Managed SNI on Windows with AppContext switch (#477)
Browse files Browse the repository at this point in the history
  • Loading branch information
cheenamalhotra authored Mar 23, 2020
1 parent 4b6f74d commit c5386a0
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 20 deletions.
7 changes: 7 additions & 0 deletions BUILDGUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ Tests can be built and run with custom Target Frameworks. See the below examples
# Build the tests for custom TargetFramework (.NET Core)
# Applicable values: netcoreapp2.1 | netcoreapp2.2 | netcoreapp3.0
```

### Running Tests:

```bash
Expand All @@ -171,3 +172,9 @@ Tests can be built and run with custom Target Frameworks. See the below examples
# Use above property to run Functional Tests with custom TargetFramework (.NET Core)
# Applicable values: netcoreapp2.1 | netcoreapp2.2 | netcoreapp3.0
```

## Using Managed SNI on Windows

Managed SNI can be enabled on Windows by enabling the below AppContext switch:

**"Microsoft.Data.SqlClient.UseManagedNetworkingOnWindows"**
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,15 @@ namespace Microsoft.Data.SqlClient
{
internal sealed class TdsParserStateObjectFactory
{

private const string UseLegacyNetworkingOnWindows = "Microsoft.Data.SqlClient.UseLegacyNetworkingOnWindows";

public static readonly TdsParserStateObjectFactory Singleton = new TdsParserStateObjectFactory();

private const string UseManagedNetworkingOnWindows = "Microsoft.Data.SqlClient.UseManagedNetworkingOnWindows";

// Temporary disabling App Context switching for managed SNI.
// If the appcontext switch is set then Use Managed SNI based on the value. Otherwise Managed SNI should always be used.
//private static bool shouldUseLegacyNetorking;
//public static bool UseManagedSNI { get; } = AppContext.TryGetSwitch(UseLegacyNetworkingOnWindows, out shouldUseLegacyNetorking) ? !shouldUseLegacyNetorking : true;
private static bool shouldUseManagedSNI;

#if DEBUG
private static Lazy<bool> useManagedSNIOnWindows = new Lazy<bool>(
() => bool.TrueString.Equals(Environment.GetEnvironmentVariable("Microsoft.Data.SqlClient.UseManagedSNIOnWindows"), StringComparison.InvariantCultureIgnoreCase)
);
public static bool UseManagedSNI => useManagedSNIOnWindows.Value;
#else
public static bool UseManagedSNI { get; } = false;
#endif
// If the appcontext switch is set then Use Managed SNI based on the value. Otherwise Native SNI.dll will be used by default.
public static bool UseManagedSNI { get; } =
AppContext.TryGetSwitch(UseManagedNetworkingOnWindows, out shouldUseManagedSNI) ? shouldUseManagedSNI : false;

public EncryptionOptions EncryptionOptions
{
Expand All @@ -49,10 +39,14 @@ public TdsParserStateObject CreateTdsParserStateObject(TdsParser parser)
{
if (UseManagedSNI)
{
SqlClientEventSource.Log.TraceEvent("<sc.TdsParserStateObjectFactory.CreateTdsParserStateObject|INFO> Found AppContext switch '{0}#' enabled, managed networking implementation will be used."
, UseManagedNetworkingOnWindows);
return new TdsParserStateObjectManaged(parser);
}
else
{
SqlClientEventSource.Log.TraceEvent("<sc.TdsParserStateObjectFactory.CreateTdsParserStateObject|INFO> AppContext switch '{0}#' not enabled, native networking implementation will be used."
, UseManagedNetworkingOnWindows);
return new TdsParserStateObjectNative(parser);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@ public static class DataTestUtility
public const string UdtTestDbName = "UdtTestDb";
public const string AKVKeyName = "TestSqlClientAzureKeyVaultProvider";

private static readonly Assembly MdsAssembly = typeof(Microsoft.Data.SqlClient.SqlConnection).GetTypeInfo().Assembly;
private static readonly Type TdsParserStateObjectFactoryInstance = MdsAssembly?.GetType("Microsoft.Data.SqlClient.TdsParserStateObjectFactory");
private static readonly PropertyInfo UseManagedSni = TdsParserStateObjectFactoryInstance?.GetProperty("UseManagedSNI", BindingFlags.Static | BindingFlags.Public);
private const string ManagedNetworkingAppContextSwitch = "Microsoft.Data.SqlClient.UseManagedNetworkingOnWindows";

private static bool UseManagedSNI =
bool.TryParse(Environment.GetEnvironmentVariable("Microsoft_Data_SqlClient_UseManagedSniOnWindows"), out UseManagedSNI) ? UseManagedSNI : false;

private static readonly string[] AzureSqlServerEndpoints = {".database.windows.net",
".database.cloudapi.de",
Expand Down Expand Up @@ -76,6 +77,12 @@ private class Config

static DataTestUtility()
{
if (UseManagedSNI)
{
AppContext.SetSwitch(ManagedNetworkingAppContextSwitch, true);
Console.WriteLine($"App Context switch {ManagedNetworkingAppContextSwitch} enabled on {Environment.OSVersion}");
}

using (StreamReader r = new StreamReader("config.json"))
{
string json = r.ReadToEnd();
Expand Down Expand Up @@ -231,7 +238,7 @@ public static bool IsAKVSetupAvailable()
return !string.IsNullOrEmpty(AKVUrl) && !string.IsNullOrEmpty(AKVClientId) && !string.IsNullOrEmpty(AKVClientSecret);
}

public static bool IsUsingManagedSNI() => (bool)(UseManagedSni?.GetValue(null) ?? false);
public static bool IsUsingManagedSNI() => UseManagedSNI;

public static bool IsUsingNativeSNI() => !IsUsingManagedSNI();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests
public static class IntegratedAuthenticationTest
{
private static bool IsIntegratedSecurityEnvironmentSet() => DataTestUtility.IsIntegratedSecuritySetup();
private static bool AreConnectionStringsSetup() => DataTestUtility.AreConnStringsSetup();

private static bool AreConnectionStringsSetup() => DataTestUtility.AreConnStringsSetup();

[ConditionalFact(nameof(IsIntegratedSecurityEnvironmentSet), nameof(AreConnectionStringsSetup))]
public static void IntegratedAuthenticationTestWithConnectionPooling()
Expand Down

0 comments on commit c5386a0

Please sign in to comment.