mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-22 01:25:44 -05:00
4094 Kusto AAD Authentication Refactor (#1115)
* 4094 Upgraded Kusto.Data and Kusto.Language to 9.0.3. Refactored KustoServiceLayer to use KustoConnectionStringBuilder instead of Sql. * 4094 Refactored KustoClient>Initialize to take connectionString as optional. Removed unused properties from ConnectionService>ParseConnectionString * 4094 Updated Kusto.Data and Kusto.Language nuget packages to 9.0.4. Removed IsDedicatedAdminConnection function in ConnectionService. * 4094 Fixed unit tests
This commit is contained in:
@@ -117,8 +117,11 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource.DataSourceIntellisense
|
||||
var query = "let fn = " + parameters + " { };";
|
||||
var code = KustoCode.ParseAndAnalyze(query);
|
||||
var let = code.Syntax.GetFirstDescendant<LetStatement>();
|
||||
var variable = let.Name.ReferencedSymbol as VariableSymbol;
|
||||
var function = variable.Type as FunctionSymbol;
|
||||
|
||||
FunctionSymbol function = let.Name.ReferencedSymbol is VariableSymbol variable
|
||||
? variable.Type as FunctionSymbol
|
||||
: let.Name.ReferencedSymbol as FunctionSymbol;
|
||||
|
||||
return function.Signatures[0].Parameters;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ using Kusto.Data.Exceptions;
|
||||
using Kusto.Data.Net.Client;
|
||||
using Kusto.Language;
|
||||
using Kusto.Language.Editor;
|
||||
using Microsoft.Data.SqlClient;
|
||||
using Microsoft.Kusto.ServiceLayer.Connection;
|
||||
using Microsoft.Kusto.ServiceLayer.DataSource.DataSourceIntellisense;
|
||||
using Microsoft.Kusto.ServiceLayer.Utility;
|
||||
@@ -36,26 +35,21 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
|
||||
/// </summary>
|
||||
public GlobalState SchemaState { get; private set; }
|
||||
|
||||
public string ClusterName { get; }
|
||||
public string ClusterName { get; private set; }
|
||||
public string DatabaseName { get; private set; }
|
||||
|
||||
public KustoClient(string connectionString, string azureAccountToken, string ownerUri)
|
||||
{
|
||||
_ownerUri = ownerUri;
|
||||
ClusterName = GetClusterName(connectionString);
|
||||
|
||||
var dbName = new SqlConnectionStringBuilder(connectionString).InitialCatalog;
|
||||
SetDatabaseName(dbName);
|
||||
|
||||
Initialize(ClusterName, DatabaseName, azureAccountToken);
|
||||
Initialize(azureAccountToken, connectionString);
|
||||
SchemaState = LoadSchemaState();
|
||||
}
|
||||
|
||||
private void SetDatabaseName(string databaseName)
|
||||
private string ParseDatabaseName(string databaseName)
|
||||
{
|
||||
var regex = new Regex(@"(?<=\().+?(?=\))");
|
||||
|
||||
DatabaseName = regex.IsMatch(databaseName)
|
||||
return regex.IsMatch(databaseName)
|
||||
? regex.Match(databaseName).Value
|
||||
: databaseName;
|
||||
}
|
||||
@@ -85,9 +79,9 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
|
||||
DatabaseName, ClusterName);
|
||||
}
|
||||
|
||||
private void Initialize(string clusterName, string databaseName, string azureAccountToken)
|
||||
private void Initialize(string azureAccountToken, string connectionString = "")
|
||||
{
|
||||
var stringBuilder = GetKustoConnectionStringBuilder(clusterName, databaseName, azureAccountToken, "", "");
|
||||
var stringBuilder = GetKustoConnectionStringBuilder(azureAccountToken, connectionString);
|
||||
_kustoQueryProvider = KustoClientFactory.CreateCslQueryProvider(stringBuilder);
|
||||
_kustoAdminProvider = KustoClientFactory.CreateCslAdminProvider(stringBuilder);
|
||||
}
|
||||
@@ -97,68 +91,26 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
|
||||
string azureAccountToken = ConnectionService.Instance.RefreshAzureToken(_ownerUri);
|
||||
_kustoQueryProvider.Dispose();
|
||||
_kustoAdminProvider.Dispose();
|
||||
Initialize(ClusterName, DatabaseName, azureAccountToken);
|
||||
Initialize(azureAccountToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts the cluster name from the connectionstring. The string looks like the following:
|
||||
/// "Data Source=clustername.kusto.windows.net;User ID=;Password=;Pooling=False;Application Name=azdata-GeneralConnection"
|
||||
/// <summary>
|
||||
/// <param name="connectionString">A connection string coming over the Data management protocol</param>
|
||||
private string GetClusterName(string connectionString)
|
||||
private KustoConnectionStringBuilder GetKustoConnectionStringBuilder(string userToken, string connectionString)
|
||||
{
|
||||
var csb = new SqlConnectionStringBuilder(connectionString);
|
||||
ValidationUtils.IsTrue<ArgumentException>(!string.IsNullOrWhiteSpace(userToken),
|
||||
$"the Kusto authentication is not specified - either set {nameof(userToken)}");
|
||||
|
||||
// If there is no https:// prefix, add it
|
||||
Uri uri;
|
||||
if ((Uri.TryCreate(csb.DataSource, UriKind.Absolute, out uri) ||
|
||||
Uri.TryCreate("https://" + csb.DataSource, UriKind.Absolute, out uri)) &&
|
||||
(uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps))
|
||||
{
|
||||
return uri.AbsoluteUri;
|
||||
}
|
||||
|
||||
throw new ArgumentException("Expected a URL of the form clustername.kusto.windows.net");
|
||||
}
|
||||
|
||||
private KustoConnectionStringBuilder GetKustoConnectionStringBuilder(string clusterName, string databaseName,
|
||||
string userToken, string applicationClientId, string applicationKey)
|
||||
{
|
||||
ValidationUtils.IsNotNull(clusterName, nameof(clusterName));
|
||||
ValidationUtils.IsTrue<ArgumentException>(
|
||||
!string.IsNullOrWhiteSpace(userToken)
|
||||
|| (!string.IsNullOrWhiteSpace(applicationClientId) && !string.IsNullOrWhiteSpace(applicationKey)),
|
||||
$"the Kusto authentication is not specified - either set {nameof(userToken)}, or set {nameof(applicationClientId)} and {nameof(applicationKey)}");
|
||||
|
||||
var kcsb = new KustoConnectionStringBuilder
|
||||
{
|
||||
DataSource = clusterName,
|
||||
|
||||
// Perform federated auth based on the AAD user token, or based on the AAD application client id and key.
|
||||
FederatedSecurity = true
|
||||
};
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(databaseName))
|
||||
{
|
||||
kcsb.InitialCatalog = databaseName;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(userToken))
|
||||
{
|
||||
kcsb.UserToken = userToken;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(applicationClientId))
|
||||
{
|
||||
kcsb.ApplicationClientId = applicationClientId;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(applicationKey))
|
||||
{
|
||||
kcsb.ApplicationKey = applicationKey;
|
||||
}
|
||||
|
||||
return kcsb;
|
||||
var stringBuilder = string.IsNullOrWhiteSpace(connectionString)
|
||||
? new KustoConnectionStringBuilder(ClusterName, DatabaseName)
|
||||
: new KustoConnectionStringBuilder(connectionString);
|
||||
|
||||
ClusterName = stringBuilder.DataSource;
|
||||
var databaseName = ParseDatabaseName(stringBuilder.InitialCatalog);
|
||||
DatabaseName = databaseName;
|
||||
stringBuilder.InitialCatalog = databaseName;
|
||||
|
||||
ValidationUtils.IsNotNull(ClusterName, nameof(ClusterName));
|
||||
|
||||
return stringBuilder.WithAadUserTokenAuthentication(userToken);
|
||||
}
|
||||
|
||||
private ClientRequestProperties GetClientRequestProperties(CancellationToken cancellationToken)
|
||||
@@ -310,7 +262,7 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
|
||||
|
||||
public void UpdateDatabase(string databaseName)
|
||||
{
|
||||
SetDatabaseName(databaseName);
|
||||
DatabaseName = ParseDatabaseName(databaseName);
|
||||
SchemaState = LoadSchemaState();
|
||||
}
|
||||
|
||||
|
||||
@@ -65,12 +65,12 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource.Metadata
|
||||
{
|
||||
var databaseDetails = new List<DatabaseInfo>();
|
||||
|
||||
if (typeof(DatabaseMetadata) == clusterDBDetails.FirstOrDefault().GetType())
|
||||
if (clusterDBDetails.FirstOrDefault() is DatabaseMetadata)
|
||||
{
|
||||
foreach (var dbDetail in clusterDBDetails)
|
||||
{
|
||||
DatabaseInfo databaseInfo = new DatabaseInfo();
|
||||
Int64.TryParse(dbDetail.SizeInMB.ToString(), out long sum_OriginalSize);
|
||||
long.TryParse(dbDetail.SizeInMB, out long sum_OriginalSize);
|
||||
databaseInfo.Options["name"] = dbDetail.Name;
|
||||
databaseInfo.Options["sizeInMB"] = (sum_OriginalSize / (1024 * 1024)).ToString();
|
||||
databaseDetails.Add(databaseInfo);
|
||||
|
||||
Reference in New Issue
Block a user