Skip to content

Commit

Permalink
Disable unit test for Linux SPN Port# issue using ActiveIssue 27824.
Browse files Browse the repository at this point in the history
  • Loading branch information
arellegue committed Dec 7, 2023
1 parent 030d8f7 commit 4a92bc7
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ private static byte[][] GetSqlServerSPNs(DataSource dataSource, string serverSPN
}
else if (!string.IsNullOrWhiteSpace(dataSource.InstanceName))
{
postfix = (dataSource._connectionProtocol == DataSource.Protocol.TCP ? dataSource.ResolvedPort.ToString() : dataSource.InstanceName);
postfix = dataSource._connectionProtocol == DataSource.Protocol.TCP ? dataSource.ResolvedPort.ToString() : dataSource.InstanceName;
}

SqlClientEventSource.Log.TryTraceEvent("SNIProxy.GetSqlServerSPN | Info | ServerName {0}, InstanceName {1}, Port {2}, postfix {3}", dataSource?.ServerName, dataSource?.InstanceName, dataSource?.Port, postfix);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ public static void ConnectManagedWithInstanceNameTest(bool useMultiSubnetFailove

// Note: This Unit test was tested in a domain-joined VM connecting to a remote
// SQL Server using Kerberos in the same domain.
// Disable this test for now as Davoud said there is an issue.
[ActiveIssue("27824")] // Per Davoud, "With specifying instance name and port number, this method call always returns false!"
[ConditionalFact(nameof(IsKerberos))]
public static void PortNumberInSPNTest()
{
Expand All @@ -99,25 +101,28 @@ public static void PortNumberInSPNTest()

SqlConnectionStringBuilder builder = new(connStr);

Assert.True(DataTestUtility.ParseDataSource(builder.DataSource, out string hostname, out _, out string instanceName));
Assert.True(DataTestUtility.ParseDataSource(builder.DataSource, out string hostname, out _, out string instanceName), "Data source to be parsed must contain a host name and instance name");

if (IsBrowserAlive(hostname) && IsValidInstance(hostname, instanceName))
bool condition = IsBrowserAlive(hostname) && IsValidInstance(hostname, instanceName);
Assert.True(condition, "Browser service is not running or instance name is invalid");

if (condition)
{
using SqlConnection connection = new(builder.ConnectionString);
connection.Open();
using SqlCommand command = new("SELECT auth_scheme, local_tcp_port from sys.dm_exec_connections where session_id = @@spid", connection);
using SqlDataReader reader = command.ExecuteReader();
Assert.True(reader.Read(), "Expected to receive one row data");
Assert.Equal("KERBEROS", reader.GetString(0));
int Port = reader.GetInt32(1);
int localTcpPort = reader.GetInt32(1);

int port = -1;
string spnInfo = GetSPNInfo(builder.DataSource, out port);
int spnPort = -1;
string spnInfo = GetSPNInfo(builder.DataSource, out spnPort);

// sample output to validate = MSSQLSvc/machine.domain.tld:port"
// sample output to validate = MSSQLSvc/machine.domain.tld:spnPort"
Assert.Contains($"MSSQLSvc/{hostname}", spnInfo);
// the local_tcp_port Port is the same as the inferred port from instance name
Assert.Equal(Port, port);
// the local_tcp_port should be the same as the inferred SPN port from instance name
Assert.Equal(localTcpPort, spnPort);
}
}

Expand Down Expand Up @@ -146,29 +151,29 @@ private static string GetSPNInfo(string datasource, out int out_port)
// Get all types constructors
ConstructorInfo sniProxyCtor = sniProxyType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, Type.EmptyTypes, null);
ConstructorInfo SSRPCtor = ssrpType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, Type.EmptyTypes, null);
ConstructorInfo dataSourceCtor = dataSourceType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, dataSourceConstructorTypesArray , null);
ConstructorInfo dataSourceCtor = dataSourceType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, dataSourceConstructorTypesArray, null);
ConstructorInfo timeoutTimerCtor = timeoutTimerType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, Type.EmptyTypes, null);

// Instantiate SNIProxy
object sniProxy = sniProxyCtor.Invoke(new object[] { });
object sniProxy = sniProxyCtor.Invoke(new object[] { });

// Instantiate datasource
object details = dataSourceCtor.Invoke(new object[] { datasource });
object dataSourceObj = dataSourceCtor.Invoke(new object[] { datasource });

// Instantiate SSRP
object ssrp = SSRPCtor.Invoke(new object[] { });
object ssrp = SSRPCtor.Invoke(new object[] { });

// Instantiate TimeoutTimer
object timeoutTimer = timeoutTimerCtor.Invoke(new object[] { });

// Get TimeoutTimer.StartSecondsTimeout Method
MethodInfo startSecondsTimeout = timeoutTimer.GetType().GetMethod("StartSecondsTimeout", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, startSecondsTimeoutTypesArray, null);
// Create a timeoutTimer that expires in 30 seconds
timeoutTimer = startSecondsTimeout.Invoke(details, new object[] { 30 });
timeoutTimer = startSecondsTimeout.Invoke(dataSourceObj, new object[] { 30 });

// Parse the datasource to separate the server name and instance name
MethodInfo ParseServerName = details.GetType().GetMethod("ParseServerName", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, dataSourceConstructorTypesArray, null);
object dataSrcInfo = ParseServerName.Invoke(details, new object[] { datasource });
MethodInfo ParseServerName = dataSourceObj.GetType().GetMethod("ParseServerName", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, dataSourceConstructorTypesArray, null);
object dataSrcInfo = ParseServerName.Invoke(dataSourceObj, new object[] { datasource });

// Get the GetPortByInstanceName method of SSRP
MethodInfo getPortByInstanceName = ssrp.GetType().GetMethod("GetPortByInstanceName", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, getPortByInstanceNameTypesArray, null);
Expand All @@ -182,7 +187,7 @@ private static string GetSPNInfo(string datasource, out int out_port)
string instanceName = instanceNameInfo.GetValue(dataSrcInfo, null).ToString();

// Get the port number using the GetPortByInstanceName method of SSRP
object port = getPortByInstanceName.Invoke(ssrp, parameters: new object[] { serverName, instanceName, timeoutTimer, false, 0 } );
object port = getPortByInstanceName.Invoke(ssrp, parameters: new object[] { serverName, instanceName, timeoutTimer, false, 0 });

// Set the resolved port property of datasource
PropertyInfo resolvedPortInfo = dataSrcInfo.GetType().GetProperty("ResolvedPort", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
Expand All @@ -193,8 +198,7 @@ private static string GetSPNInfo(string datasource, out int out_port)
MethodInfo getSqlServerSPNs = sniProxy.GetType().GetMethod("GetSqlServerSPNs", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, CallingConventions.Any, getSqlServerSPNsTypesArray, null);

// Finally call GetSqlServerSPNs
// Use dynamic type for indexing to work at design time
dynamic result = getSqlServerSPNs.Invoke(sniProxy, new object[] { dataSrcInfo, serverSPN });
byte[][] result = (byte[][])getSqlServerSPNs.Invoke(sniProxy, new object[] { dataSrcInfo, serverSPN });

// Example result: MSSQLSvc/machine.domain.tld:port"
string spnInfo = Encoding.Unicode.GetString(result[0]);
Expand All @@ -206,7 +210,11 @@ private static string GetSPNInfo(string datasource, out int out_port)

private static bool IsKerberos()
{
return (DataTestUtility.AreConnStringsSetup() && DataTestUtility.IsNotLocalhost() && DataTestUtility.IsKerberosTest && DataTestUtility.IsNotAzureServer() && DataTestUtility.IsNotAzureSynapse());
return (DataTestUtility.AreConnStringsSetup()
&& DataTestUtility.IsNotLocalhost()
&& DataTestUtility.IsKerberosTest
&& DataTestUtility.IsNotAzureServer()
&& DataTestUtility.IsNotAzureSynapse());
}

private static bool IsBrowserAlive(string browserHostname)
Expand Down

0 comments on commit 4a92bc7

Please sign in to comment.