Introduce AAD interactive auth mode (#1860)

This commit is contained in:
Cheena Malhotra
2023-03-02 09:39:54 -08:00
committed by GitHub
parent 98e50c98fe
commit 187b6ecc14
47 changed files with 918 additions and 151 deletions

View File

@@ -6,6 +6,7 @@
#nullable disable
using Microsoft.SqlTools.Hosting.Contracts;
using static Microsoft.SqlTools.Shared.Utility.Constants;
namespace Microsoft.SqlTools.ServiceLayer.Connection
{
@@ -52,7 +53,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
CategoryValues = new CategoryValue[]
{ new CategoryValue { DisplayName = "SQL Login", Name = "SqlLogin" },
new CategoryValue { DisplayName = "Windows Authentication", Name = "Integrated" },
new CategoryValue { DisplayName = "Azure Active Directory - Universal with MFA support", Name = "AzureMFA" }
new CategoryValue { DisplayName = "Azure Active Directory - Universal with MFA support", Name = AzureMFA }
},
IsIdentity = true,
IsRequired = true,

View File

@@ -23,7 +23,9 @@ using Microsoft.SqlTools.ServiceLayer.LanguageServices;
using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts;
using Microsoft.SqlTools.ServiceLayer.Utility;
using Microsoft.SqlTools.Utility;
using static Microsoft.SqlTools.Shared.Utility.Constants;
using System.Diagnostics;
using Microsoft.SqlTools.Authentication.Sql;
namespace Microsoft.SqlTools.ServiceLayer.Connection
{
@@ -143,17 +145,23 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
{
RequestSecurityTokenParams message = new RequestSecurityTokenParams()
{
Authority = authority,
Provider = "Azure",
Authority = authority,
Resource = resource,
Scope = scope
Scopes = new string[] { scope }
};
RequestSecurityTokenResponse response = await Instance.ServiceHost.SendRequest(SecurityTokenRequest.Type, message, true);
RequestSecurityTokenResponse response = await Instance.ServiceHost.SendRequest(SecurityTokenRequest.Type, message, true).ConfigureAwait(false);
return response.Token;
}
/// <summary>
/// Enables configured 'Sql Authentication Provider' for 'Active Directory Interactive' authentication mode to be used
/// when user chooses 'Azure MFA'.
/// </summary>
public bool EnableSqlAuthenticationProvider { get; set; }
/// <summary>
/// Returns a connection queue for given type
/// </summary>
@@ -248,7 +256,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
if (this.TryFindConnection(ownerUri, out connInfo))
{
// If not an azure connection, no need to refresh token
if (connInfo.ConnectionDetails.AuthenticationType != "AzureMFA")
if (connInfo.ConnectionDetails.AuthenticationType != AzureMFA)
{
return false;
}
@@ -594,7 +602,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
connectionInfo.IsSqlDb = serverInfo.EngineEditionId == (int)DatabaseEngineEdition.SqlDatabase;
connectionInfo.IsSqlDW = (serverInfo.EngineEditionId == (int)DatabaseEngineEdition.SqlDataWarehouse);
// Determines that access token is used for creating connection.
connectionInfo.IsAzureAuth = connectionInfo.ConnectionDetails.AuthenticationType == "AzureMFA";
connectionInfo.IsAzureAuth = connectionInfo.ConnectionDetails.AuthenticationType == AzureMFA;
connectionInfo.EngineEdition = (DatabaseEngineEdition)serverInfo.EngineEditionId;
// Azure Data Studio supports SQL Server 2014 and later releases.
response.IsSupportedVersion = serverInfo.IsCloud || serverInfo.ServerMajorVersion >= 12;
@@ -1061,10 +1069,20 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
return handler.HandleRequest(this.connectionFactory, info);
}
public void InitializeService(IProtocolEndpoint serviceHost)
public void InitializeService(IProtocolEndpoint serviceHost, ServiceLayerCommandOptions commandOptions)
{
this.ServiceHost = serviceHost;
if (commandOptions != null && commandOptions.EnableSqlAuthenticationProvider)
{
// Register SqlAuthenticationProvider with SqlConnection for AAD Interactive (MFA) authentication.
var provider = new AuthenticationProvider(commandOptions.ApplicationName);
SqlAuthenticationProvider.SetProvider(SqlAuthenticationMethod.ActiveDirectoryInteractive, provider);
this.EnableSqlAuthenticationProvider = true;
Logger.Information("Registering implementation of SQL Authentication provider for 'Active Directory Interactive' authentication mode.");
}
// Register request and event handlers with the Service Host
serviceHost.SetRequestHandler(ConnectionRequest.Type, HandleConnectRequest, true);
serviceHost.SetRequestHandler(CancelConnectRequest.Type, HandleCancelConnectRequest, true);
@@ -1304,31 +1322,46 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
connectionBuilder = new SqlConnectionStringBuilder
{
["Data Source"] = dataSource,
["User Id"] = connectionDetails.UserName,
["Password"] = connectionDetails.Password
DataSource = dataSource
};
}
// Check for any optional parameters
if (!string.IsNullOrEmpty(connectionDetails.DatabaseName))
{
connectionBuilder["Initial Catalog"] = connectionDetails.DatabaseName;
connectionBuilder.InitialCatalog = connectionDetails.DatabaseName;
}
if (!string.IsNullOrEmpty(connectionDetails.AuthenticationType))
{
switch (connectionDetails.AuthenticationType)
{
case "Integrated":
case Integrated:
connectionBuilder.IntegratedSecurity = true;
break;
case "SqlLogin":
case SqlLogin:
connectionBuilder.UserID = connectionDetails.UserName;
connectionBuilder.Password = connectionDetails.Password;
connectionBuilder.Authentication = SqlAuthenticationMethod.SqlPassword;
break;
case "AzureMFA":
connectionBuilder.UserID = "";
connectionBuilder.Password = "";
case AzureMFA:
if (Instance.EnableSqlAuthenticationProvider)
{
connectionBuilder.UserID = connectionDetails.UserName;
connectionDetails.AuthenticationType = ActiveDirectoryInteractive;
connectionBuilder.Authentication = SqlAuthenticationMethod.ActiveDirectoryInteractive;
}
else
{
connectionBuilder.UserID = "";
}
break;
case "ActiveDirectoryPassword":
case ActiveDirectoryInteractive:
connectionBuilder.UserID = connectionDetails.UserName;
connectionBuilder.Authentication = SqlAuthenticationMethod.ActiveDirectoryInteractive;
break;
case ActiveDirectoryPassword:
connectionBuilder.UserID = connectionDetails.UserName;
connectionBuilder.Password = connectionDetails.Password;
connectionBuilder.Authentication = SqlAuthenticationMethod.ActiveDirectoryPassword;
break;
default:
@@ -1337,16 +1370,13 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
}
if (!string.IsNullOrEmpty(connectionDetails.ColumnEncryptionSetting))
{
switch (connectionDetails.ColumnEncryptionSetting.ToUpper())
if (Enum.TryParse<SqlConnectionColumnEncryptionSetting>(connectionDetails.ColumnEncryptionSetting, true, out var value))
{
case "ENABLED":
connectionBuilder.ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Enabled;
break;
case "DISABLED":
connectionBuilder.ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Disabled;
break;
default:
throw new ArgumentException(SR.ConnectionServiceConnStringInvalidColumnEncryptionSetting(connectionDetails.ColumnEncryptionSetting));
connectionBuilder.ColumnEncryptionSetting = value;
}
else
{
throw new ArgumentException(SR.ConnectionServiceConnStringInvalidColumnEncryptionSetting(connectionDetails.ColumnEncryptionSetting));
}
}
if (!string.IsNullOrEmpty(connectionDetails.SecureEnclaves))
@@ -1365,36 +1395,30 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
}
if (!string.IsNullOrEmpty(connectionDetails.EnclaveAttestationProtocol))
{
if (string.IsNullOrEmpty(connectionDetails.ColumnEncryptionSetting) || connectionDetails.ColumnEncryptionSetting.ToUpper() == "DISABLED"
if (connectionBuilder.ColumnEncryptionSetting != SqlConnectionColumnEncryptionSetting.Enabled
|| string.IsNullOrEmpty(connectionDetails.SecureEnclaves) || connectionDetails.SecureEnclaves.ToUpper() == "DISABLED")
{
throw new ArgumentException(SR.ConnectionServiceConnStringInvalidAlwaysEncryptedOptionCombination);
}
switch (connectionDetails.EnclaveAttestationProtocol.ToUpper())
if (Enum.TryParse<SqlConnectionAttestationProtocol>(connectionDetails.EnclaveAttestationProtocol, true, out var value))
{
case "AAS":
connectionBuilder.AttestationProtocol = SqlConnectionAttestationProtocol.AAS;
break;
case "HGS":
connectionBuilder.AttestationProtocol = SqlConnectionAttestationProtocol.HGS;
break;
case "NONE":
connectionBuilder.AttestationProtocol = SqlConnectionAttestationProtocol.None;
break;
default:
throw new ArgumentException(SR.ConnectionServiceConnStringInvalidEnclaveAttestationProtocol(connectionDetails.EnclaveAttestationProtocol));
connectionBuilder.AttestationProtocol = value;
}
else
{
throw new ArgumentException(SR.ConnectionServiceConnStringInvalidEnclaveAttestationProtocol(connectionDetails.EnclaveAttestationProtocol));
}
}
if (!string.IsNullOrEmpty(connectionDetails.EnclaveAttestationUrl))
{
if (string.IsNullOrEmpty(connectionDetails.ColumnEncryptionSetting) || connectionDetails.ColumnEncryptionSetting.ToUpper() == "DISABLED"
if (connectionBuilder.ColumnEncryptionSetting != SqlConnectionColumnEncryptionSetting.Enabled
|| string.IsNullOrEmpty(connectionDetails.SecureEnclaves) || connectionDetails.SecureEnclaves.ToUpper() == "DISABLED")
{
throw new ArgumentException(SR.ConnectionServiceConnStringInvalidAlwaysEncryptedOptionCombination);
}
if(connectionBuilder.AttestationProtocol == SqlConnectionAttestationProtocol.None)
if (connectionBuilder.AttestationProtocol == SqlConnectionAttestationProtocol.None)
{
throw new ArgumentException(SR.ConnectionServiceConnStringInvalidAttestationProtocolNoneWithUrl);
}
@@ -1456,19 +1480,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
}
if (!string.IsNullOrEmpty(connectionDetails.ApplicationIntent))
{
ApplicationIntent intent;
switch (connectionDetails.ApplicationIntent)
if (Enum.TryParse<ApplicationIntent>(connectionDetails.ApplicationIntent, true, out ApplicationIntent value))
{
case "ReadOnly":
intent = ApplicationIntent.ReadOnly;
break;
case "ReadWrite":
intent = ApplicationIntent.ReadWrite;
break;
default:
throw new ArgumentException(SR.ConnectionServiceConnStringInvalidIntent(connectionDetails.ApplicationIntent));
connectionBuilder.ApplicationIntent = value;
}
else
{
throw new ArgumentException(SR.ConnectionServiceConnStringInvalidIntent(connectionDetails.ApplicationIntent));
}
connectionBuilder.ApplicationIntent = intent;
}
if (!string.IsNullOrEmpty(connectionDetails.CurrentLanguage))
{
@@ -1585,7 +1604,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
ApplicationIntent = builder.ApplicationIntent.ToString(),
ApplicationName = builder.ApplicationName,
AttachDbFilename = builder.AttachDBFilename,
AuthenticationType = builder.IntegratedSecurity ? "Integrated" : "SqlLogin",
AuthenticationType = builder.IntegratedSecurity ? "Integrated" :
(builder.Authentication == SqlAuthenticationMethod.ActiveDirectoryInteractive
? "ActiveDirectoryInteractive" : "SqlLogin"),
ConnectRetryCount = builder.ConnectRetryCount,
ConnectRetryInterval = builder.ConnectRetryInterval,
ConnectTimeout = builder.ConnectTimeout,
@@ -1793,7 +1814,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
SqlConnection sqlConn = new SqlConnection(connectionString);
// Fill in Azure authentication token if needed
if (connInfo.ConnectionDetails.AzureAccountToken != null)
if (connInfo.ConnectionDetails.AzureAccountToken != null && connInfo.ConnectionDetails.AuthenticationType == AzureMFA)
{
sqlConn.AccessToken = connInfo.ConnectionDetails.AzureAccountToken;
}
@@ -1824,7 +1845,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
{
var sqlConnection = ConnectionService.OpenSqlConnection(connInfo, featureName);
ServerConnection serverConnection;
if (connInfo.ConnectionDetails.AzureAccountToken != null)
if (connInfo.ConnectionDetails.AzureAccountToken != null && connInfo.ConnectionDetails.AuthenticationType == AzureMFA)
{
serverConnection = new ServerConnection(sqlConnection, new AzureAccessToken(connInfo.ConnectionDetails.AzureAccountToken));
}

View File

@@ -11,25 +11,25 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts
{
class RequestSecurityTokenParams
{
/// <summary>
/// Gets or sets the address of the authority to issue token.
/// </summary>
public string Authority { get; set; }
/// <summary>
/// Gets or sets the provider that indicates the type of linked account to query.
/// </summary>
public string Provider { get; set; }
/// <summary>
/// Gets or sets the authority URL from where token is requested.
/// </summary>
public string Authority { get; set; }
/// <summary>
/// Gets or sets the identifier of the target resource that is the recipient of the requested token.
/// </summary>
public string Resource { get; set; }
/// <summary>
/// Gets or sets the scope of the authentication request.
/// Gets or sets the scope array of the authentication request.
/// </summary>
public string Scope { get; set; }
public string [] Scopes { get; set; }
}
class RequestSecurityTokenResponse

View File

@@ -8,6 +8,7 @@ using Microsoft.SqlServer.Dac;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.TaskServices;
using Microsoft.SqlTools.ServiceLayer.Utility;
using static Microsoft.SqlTools.Shared.Utility.Constants;
using Microsoft.SqlTools.Utility;
using System;
using System.Diagnostics;
@@ -86,7 +87,9 @@ namespace Microsoft.SqlTools.ServiceLayer.DacFx
try
{
// Pass in Azure authentication token if needed
this.DacServices = this.ConnInfo.ConnectionDetails.AzureAccountToken != null ? new DacServices(this.ConnectionString, new AccessTokenProvider(this.ConnInfo.ConnectionDetails.AzureAccountToken)) : new DacServices(this.ConnectionString);
this.DacServices = this.ConnInfo.ConnectionDetails.AzureAccountToken != null && this.ConnInfo.ConnectionDetails.AuthenticationType == AzureMFA
? new DacServices(this.ConnectionString, new AccessTokenProvider(this.ConnInfo.ConnectionDetails.AzureAccountToken))
: new DacServices(this.ConnectionString);
Execute();
}
catch (Exception e)

View File

@@ -40,6 +40,7 @@ using Microsoft.SqlTools.ServiceLayer.SqlAssessment;
using Microsoft.SqlTools.ServiceLayer.SqlContext;
using Microsoft.SqlTools.ServiceLayer.SqlProjects;
using Microsoft.SqlTools.ServiceLayer.TableDesigner;
using Microsoft.SqlTools.ServiceLayer.Utility;
using Microsoft.SqlTools.ServiceLayer.Workspace;
namespace Microsoft.SqlTools.ServiceLayer
@@ -53,7 +54,7 @@ namespace Microsoft.SqlTools.ServiceLayer
private static object lockObject = new object();
private static bool isLoaded;
internal static ServiceHost CreateAndStartServiceHost(SqlToolsContext sqlToolsContext, Stream? inputStream = null, Stream? outputStream = null)
internal static ServiceHost CreateAndStartServiceHost(SqlToolsContext sqlToolsContext, ServiceLayerCommandOptions? commandOptions, Stream? inputStream = null, Stream? outputStream = null)
{
ServiceHost serviceHost = ServiceHost.Instance;
lock (lockObject)
@@ -63,7 +64,7 @@ namespace Microsoft.SqlTools.ServiceLayer
// Grab the instance of the service host
serviceHost.Initialize(inputStream, outputStream);
InitializeRequestHandlersAndServices(serviceHost, sqlToolsContext);
InitializeRequestHandlersAndServices(serviceHost, sqlToolsContext, commandOptions);
// Start the service only after all request handlers are setup. This is vital
// as otherwise the Initialize event can be lost - it's processed and discarded before the handler
@@ -75,7 +76,7 @@ namespace Microsoft.SqlTools.ServiceLayer
return serviceHost;
}
private static void InitializeRequestHandlersAndServices(ServiceHost serviceHost, SqlToolsContext sqlToolsContext)
private static void InitializeRequestHandlersAndServices(ServiceHost serviceHost, SqlToolsContext sqlToolsContext, ServiceLayerCommandOptions? commandOptions)
{
// Load extension provider, which currently finds all exports in current DLL. Can be changed to find based
// on directory or assembly list quite easily in the future
@@ -96,7 +97,7 @@ namespace Microsoft.SqlTools.ServiceLayer
LanguageService.Instance.InitializeService(serviceHost, sqlToolsContext);
serviceProvider.RegisterSingleService(LanguageService.Instance);
ConnectionService.Instance.InitializeService(serviceHost);
ConnectionService.Instance.InitializeService(serviceHost, commandOptions);
serviceProvider.RegisterSingleService(ConnectionService.Instance);
CredentialService.Instance.InitializeService(serviceHost);

View File

@@ -57,6 +57,8 @@
<ProjectReference Include="../Microsoft.SqlTools.Hosting/Microsoft.SqlTools.Hosting.csproj" />
<ProjectReference Include="../Microsoft.SqlTools.Credentials/Microsoft.SqlTools.Credentials.csproj" />
<ProjectReference Include="../Microsoft.SqlTools.ManagedBatchParser/Microsoft.SqlTools.ManagedBatchParser.csproj" />
<ProjectReference Include="..\Microsoft.SqlTools.Authentication\Microsoft.SqlTools.Authentication.csproj" />
<ProjectReference Include="..\Microsoft.SqlTools.Shared\Microsoft.SqlTools.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<Content Include="..\..\Notice.txt">

View File

@@ -400,7 +400,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer
var builder = ConnectionService.CreateConnectionStringBuilder(session.ConnectionInfo.ConnectionDetails);
builder.InitialCatalog = node.NodeValue;
builder.ApplicationName = TableDesignerService.TableDesignerApplicationName;
var azureToken = session.ConnectionInfo.ConnectionDetails.AzureAccountToken;
// Set Access Token only when authentication mode is not specified.
var azureToken = builder.Authentication == SqlAuthenticationMethod.NotSpecified
? session.ConnectionInfo.ConnectionDetails.AzureAccountToken : null;
TableDesignerCacheManager.StartDatabaseModelInitialization(builder.ToString(), azureToken);
}
catch (Exception ex)

View File

@@ -41,7 +41,16 @@ namespace Microsoft.SqlTools.ServiceLayer
logFilePath = Logger.GenerateLogFilePath("sqltools");
}
Logger.Initialize(tracingLevel: commandOptions.TracingLevel, logFilePath: logFilePath, traceSource: "sqltools", commandOptions.AutoFlushLog);
Logger.Initialize(tracingLevel: commandOptions.TracingLevel, commandOptions.PiiLogging, logFilePath: logFilePath, traceSource: "sqltools", commandOptions.AutoFlushLog);
// Register PII Logging configuration change callback
Workspace.WorkspaceService<SqlToolsSettings>.Instance.RegisterConfigChangeCallback((newSettings, oldSettings, context) =>
{
Logger.IsPiiEnabled = newSettings?.MssqlTools?.PiiLogging ?? false;
Logger.Information(Logger.IsPiiEnabled ? "PII Logging enabled" : "PII Logging disabled");
return Task.FromResult(true);
});
// Only enable SQL Client logging when verbose or higher to avoid extra overhead when the
// detailed logging it provides isn't needed
if (Logger.TracingLevel.HasFlag(SourceLevels.Verbose))
@@ -53,7 +62,7 @@ namespace Microsoft.SqlTools.ServiceLayer
var hostDetails = new HostDetails(version: new Version(1, 0));
SqlToolsContext sqlToolsContext = new SqlToolsContext(hostDetails);
ServiceHost serviceHost = HostLoader.CreateAndStartServiceHost(sqlToolsContext);
ServiceHost serviceHost = HostLoader.CreateAndStartServiceHost(sqlToolsContext, commandOptions);
serviceHost.MessageDispatcher.ParallelMessageProcessing = commandOptions.ParallelMessageProcessing;
// If this service was started by another process, then it should shutdown when that parent process does.

View File

@@ -17,6 +17,7 @@ using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.DacFx.Contracts;
using Microsoft.SqlTools.ServiceLayer.SchemaCompare.Contracts;
using Microsoft.SqlTools.ServiceLayer.Utility;
using static Microsoft.SqlTools.Shared.Utility.Constants;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare
@@ -187,7 +188,9 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare
case SchemaCompareEndpointType.Database:
{
string connectionString = GetConnectionString(connInfo, endpointInfo.DatabaseName);
return connInfo.ConnectionDetails?.AzureAccountToken != null
// Set Access Token only when authentication mode is not specified.
return connInfo.ConnectionDetails?.AzureAccountToken != null && connInfo.ConnectionDetails.AuthenticationType == AzureMFA
? new SchemaCompareDatabaseEndpoint(connectionString, new AccessTokenProvider(connInfo.ConnectionDetails.AzureAccountToken))
: new SchemaCompareDatabaseEndpoint(connectionString);
}

View File

@@ -17,6 +17,7 @@ using Microsoft.SqlTools.ServiceLayer.Hosting;
using Microsoft.SqlTools.ServiceLayer.Scripting.Contracts;
using Microsoft.SqlTools.Utility;
using Microsoft.SqlTools.ServiceLayer.Utility;
using static Microsoft.SqlTools.Shared.Utility.Constants;
using System.Linq;
namespace Microsoft.SqlTools.ServiceLayer.Scripting
@@ -109,7 +110,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
if (connInfo != null)
{
parameters.ConnectionString = ConnectionService.BuildConnectionString(connInfo.ConnectionDetails);
accessToken = connInfo.ConnectionDetails.AzureAccountToken;
// Set Access Token only when authentication type is AzureMFA.
if (connInfo.ConnectionDetails.AuthenticationType == AzureMFA)
{
accessToken = connInfo.ConnectionDetails.AzureAccountToken;
}
}
else
{

View File

@@ -18,7 +18,7 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext
/// group such as Intellisense is defined on a serialized setting it's used in the order of mssql, then sql, then
/// falls back to a default value.
/// </summary>
public class CompoundToolsSettingsValues: ISqlToolsSettingsValues
public class CompoundToolsSettingsValues : ISqlToolsSettingsValues
{
private List<ISqlToolsSettingsValues> priorityList = new List<ISqlToolsSettingsValues>();
private SqlToolsSettingsValues defaultValues;
@@ -44,11 +44,11 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext
/// Gets or sets the detailed IntelliSense settings
/// </summary>
public IntelliSenseSettings IntelliSense
{
{
get
{
return GetSettingOrDefault((settings) => settings.IntelliSense);
}
}
set
{
priorityList[0].IntelliSense = value;
@@ -59,11 +59,11 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext
/// Gets or sets the query execution settings
/// </summary>
public QueryExecutionSettings QueryExecutionSettings
{
{
get
{
return GetSettingOrDefault((settings) => settings.QueryExecutionSettings);
}
}
set
{
priorityList[0].QueryExecutionSettings = value;
@@ -74,11 +74,11 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext
/// Gets or sets the formatter settings
/// </summary>
public FormatterSettings Format
{
{
get
{
return GetSettingOrDefault((settings) => settings.Format);
}
}
set
{
priorityList[0].Format = value;
@@ -89,15 +89,24 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext
/// Gets or sets the object explorer settings
/// </summary>
public ObjectExplorerSettings ObjectExplorer
{
{
get
{
return GetSettingOrDefault((settings) => settings.ObjectExplorer);
}
}
set
{
priorityList[0].ObjectExplorer = value;
}
}
/// <summary>
/// Gets or sets PII Logging setting.
/// </summary>
public bool PiiLogging
{
get => GetSettingOrDefault((settings) => settings.PiiLogging);
set => priorityList[0].PiiLogging = value;
}
}
}

View File

@@ -5,6 +5,8 @@
#nullable disable
using System;
namespace Microsoft.SqlTools.ServiceLayer.SqlContext
{
/// <summary>
@@ -31,5 +33,10 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext
/// Object Explorer specific settings
/// </summary>
ObjectExplorerSettings ObjectExplorer { get; set; }
/// <summary>
/// PII Logging setting
/// </summary>
Boolean PiiLogging { get; set; }
}
}

View File

@@ -5,6 +5,7 @@
#nullable disable
using System;
using Newtonsoft.Json;
namespace Microsoft.SqlTools.ServiceLayer.SqlContext
@@ -25,6 +26,7 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext
QueryExecutionSettings = new QueryExecutionSettings();
Format = new FormatterSettings();
TableDesigner = new TableDesignerSettings();
PiiLogging = false;
}
}
@@ -57,5 +59,11 @@ namespace Microsoft.SqlTools.ServiceLayer.SqlContext
/// </summary>
[JsonProperty("tableDesigner")]
public TableDesignerSettings TableDesigner { get; set; }
/// <summary>
/// Gets or sets the setting to enable PII Logging.
/// </summary>
[JsonProperty("piiLogging")]
public Boolean PiiLogging { get; set; }
}
}

View File

@@ -1800,7 +1800,11 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
connectionStringBuilder.InitialCatalog = tableInfo.Database;
connectionStringBuilder.ApplicationName = TableDesignerService.TableDesignerApplicationName;
var connectionString = connectionStringBuilder.ToString();
tableDesigner = new Dac.TableDesigner(connectionString, tableInfo.AccessToken, tableInfo.Schema, tableInfo.Name, tableInfo.IsNewTable);
// Set Access Token only when authentication mode is not specified.
var accessToken = connectionStringBuilder.Authentication == SqlAuthenticationMethod.NotSpecified
? tableInfo.AccessToken : null;
tableDesigner = new Dac.TableDesigner(connectionString, accessToken, tableInfo.Schema, tableInfo.Name, tableInfo.IsNewTable);
}
else
{

View File

@@ -12,7 +12,7 @@ using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.Utility
{
class ServiceLayerCommandOptions : CommandOptions
public class ServiceLayerCommandOptions : CommandOptions
{
internal const string ServiceLayerServiceName = "MicrosoftSqlToolsServiceLayer.exe";