From a43166b169526d30b5d02fcbb52c31ec671deee7 Mon Sep 17 00:00:00 2001 From: Alberto Spelta Date: Sun, 14 May 2023 17:41:59 +0200 Subject: [PATCH 1/2] Add 'Identity Provider' to the PBICloudDataset connection string --- src/Infrastructure/Helpers/ConnectionStringHelper.cs | 10 +++++++--- .../Models/PBICloud/PBICloudEnvironment.cs | 8 ++++++++ src/Models/PBICloudDataset.cs | 4 ++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/Infrastructure/Helpers/ConnectionStringHelper.cs b/src/Infrastructure/Helpers/ConnectionStringHelper.cs index e4a7df43..494c90c4 100644 --- a/src/Infrastructure/Helpers/ConnectionStringHelper.cs +++ b/src/Infrastructure/Helpers/ConnectionStringHelper.cs @@ -20,6 +20,7 @@ internal static class ConnectionStringHelper //private const string UseEncryptionForDataKey = "Use Encryption for Data"; private const string ApplicationNameKey = "Application Name"; private const string ConnectTimeoutKey = "Connect Timeout"; + private const string IdentityProviderKey = "Identity Provider"; private const string ProviderMsolapValue = "MSOLAP"; private const string IntegratedSecuritySspiValue = "SSPI"; @@ -83,6 +84,7 @@ public static string BuildFor(PBICloudDataset dataset, string accessToken) // https://docs.microsoft.com/en-us/power-bi/admin/service-premium-connect-tools#duplicate-dataset-name BravoUnexpectedException.ThrowIfNull(dataset.WorkspaceName); + BravoUnexpectedException.ThrowIfNull(dataset.IdentityProvider); BravoUnexpectedException.ThrowIfNull(dataset.ExternalServerName); BravoUnexpectedException.ThrowIfNull(dataset.ExternalDatabaseName); BravoUnexpectedException.ThrowIfNull(accessToken); @@ -100,7 +102,7 @@ public static string BuildFor(PBICloudDataset dataset, string accessToken) }; var serverName = serverNameBuilder.Uri.AbsoluteUri; var databaseName = dataset.ExternalDatabaseName; - var connectionString = Build(serverName, databaseName, accessToken); + var connectionString = Build(serverName, databaseName, accessToken, dataset.IdentityProvider); return connectionString.ToProtectedString(); } @@ -112,18 +114,19 @@ public static string BuildFor(PBICloudDataset dataset, string accessToken) } else { + BravoUnexpectedException.ThrowIfNull(dataset.IdentityProvider); BravoUnexpectedException.ThrowIfNull(dataset.ExternalServerName); BravoUnexpectedException.ThrowIfNull(dataset.ExternalDatabaseName); BravoUnexpectedException.ThrowIfNull(accessToken); var serverName = dataset.ExternalServerName; var databaseName = dataset.ExternalDatabaseName; - var connectionString = Build(serverName, databaseName, accessToken); + var connectionString = Build(serverName, databaseName, accessToken, dataset.IdentityProvider); return connectionString.ToProtectedString(); } - static string Build(string serverName, string databaseName, string accessToken) + static string Build(string serverName, string databaseName, string accessToken, string identityProvider) { var builder = new OleDbConnectionStringBuilder() { @@ -132,6 +135,7 @@ static string Build(string serverName, string databaseName, string accessToken) { InitialCatalogKey, databaseName }, { IntegratedSecurityKey, IntegratedSecurityClaimsTokenValue }, { PersistSecurityInfoKey, PersistSecurityInfoValue }, + { IdentityProviderKey, identityProvider }, { PasswordKey, accessToken }, // The Analysis Services client libraries automatically add the auth-scheme value "Bearer" to the access token { ApplicationNameKey, AppEnvironment.ApplicationInstanceUniqueName } }; diff --git a/src/Infrastructure/Models/PBICloud/PBICloudEnvironment.cs b/src/Infrastructure/Models/PBICloud/PBICloudEnvironment.cs index 858d0fc2..937d0e67 100644 --- a/src/Infrastructure/Models/PBICloud/PBICloudEnvironment.cs +++ b/src/Infrastructure/Models/PBICloud/PBICloudEnvironment.cs @@ -40,6 +40,9 @@ public class PBICloudEnvironment: IPBICloudEnvironment [JsonPropertyName("clusterEndpoint")] public string? ClusterEndpoint { get; set; } + [JsonPropertyName("identityProvider")] + public string? IdentityProvider => $"{AzureADAuthority}, {AzureADResource}, {AzureADClientId}"; + [JsonIgnore] public bool IsMicrosoftInternal => Type == PBICloudEnvironmentType.Custom && Name.EqualsI(PBICloudEnvironmentTypeExtensions.PpeCloudName); @@ -145,6 +148,11 @@ public interface IPBICloudEnvironment /// string? ClusterEndpoint { get; set; } + /// + /// MSOLAP OLEDB provider 'Identity Provider' + /// + string? IdentityProvider { get; } + [JsonIgnore] bool IsMicrosoftInternal { get; } diff --git a/src/Models/PBICloudDataset.cs b/src/Models/PBICloudDataset.cs index 15645b5b..7f7978d8 100644 --- a/src/Models/PBICloudDataset.cs +++ b/src/Models/PBICloudDataset.cs @@ -38,6 +38,9 @@ public class PBICloudDataset : IDataModel [JsonPropertyName("externalDatabaseName")] public string? ExternalDatabaseName { get; set; } + [JsonPropertyName("identityProvider")] + public string? IdentityProvider { get; set; } + [JsonPropertyName("name")] public string? DisplayName { get; set; } @@ -150,6 +153,7 @@ internal static PBICloudDataset CreateFrom(IPBICloudEnvironment environment, Clo DatabaseName = cloudModel.DBName, ExternalServerName = null, ExternalDatabaseName = null, + IdentityProvider = environment.IdentityProvider, DisplayName = cloudModel.DisplayName, Description = cloudModel.Description, Owner = $"{ cloudModel.CreatorUser?.GivenName } { cloudModel.CreatorUser?.FamilyName }", From 9302bab6b80a833824f7a710d6df0afc0b1a5ddc Mon Sep 17 00:00:00 2001 From: Alberto Spelta Date: Sun, 14 May 2023 17:47:50 +0200 Subject: [PATCH 2/2] Set connection string 'Persist Security Info' = true --- src/Infrastructure/Helpers/ConnectionStringHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Infrastructure/Helpers/ConnectionStringHelper.cs b/src/Infrastructure/Helpers/ConnectionStringHelper.cs index 494c90c4..7f5122b9 100644 --- a/src/Infrastructure/Helpers/ConnectionStringHelper.cs +++ b/src/Infrastructure/Helpers/ConnectionStringHelper.cs @@ -25,7 +25,7 @@ internal static class ConnectionStringHelper private const string ProviderMsolapValue = "MSOLAP"; private const string IntegratedSecuritySspiValue = "SSPI"; private const string IntegratedSecurityClaimsTokenValue = "ClaimsToken"; - private const string PersistSecurityInfoValue = "False"; // 'False' here is used as a best practice in order to discard security-sensitive information after the connection has been opened + private const string PersistSecurityInfoValue = "True"; public static string BuildFor(IPEndPoint endPoint) {