From 7b102df5a75b34fe48687fb73347448bf9add914 Mon Sep 17 00:00:00 2001 From: Jeff Trimmer Date: Wed, 22 Jan 2020 16:02:05 -0800 Subject: [PATCH] Enable column encryption setting (#908) * Enable the Column Encryption advanced security connection setting and add supporting tests. --- .../Connection/ConnectionService.cs | 15 +++++++++++++++ .../Connection/Contracts/ConnectionDetails.cs | 16 ++++++++++++++++ .../Contracts/ConnectionDetailsExtensions.cs | 1 + .../Localization/sr.cs | 8 ++++++++ .../Localization/sr.resx | 7 ++++++- .../Localization/sr.strings | 2 ++ .../Connection/ConnectionDetailsTests.cs | 4 ++++ .../Connection/ConnectionServiceTests.cs | 19 +++++++++++++++---- 8 files changed, 67 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs index 984bbe84..2c950038 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ConnectionService.cs @@ -1142,6 +1142,20 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection throw new ArgumentException(SR.ConnectionServiceConnStringInvalidAuthType(connectionDetails.AuthenticationType)); } } + if (!string.IsNullOrEmpty(connectionDetails.ColumnEncryptionSetting)) + { + switch (connectionDetails.ColumnEncryptionSetting.ToUpper()) + { + case "ENABLED": + connectionBuilder.ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Enabled; + break; + case "DISABLED": + connectionBuilder.ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Disabled; + break; + default: + throw new ArgumentException(SR.ConnectionServiceConnStringInvalidColumnEncryptionSetting(connectionDetails.ColumnEncryptionSetting)); + } + } if (connectionDetails.Encrypt.HasValue) { connectionBuilder.Encrypt = connectionDetails.Encrypt.Value; @@ -1313,6 +1327,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection ConnectTimeout = builder.ConnectTimeout, CurrentLanguage = builder.CurrentLanguage, DatabaseName = builder.InitialCatalog, + ColumnEncryptionSetting = builder.ColumnEncryptionSetting.ToString(), Encrypt = builder.Encrypt, FailoverPartner = builder.FailoverPartner, LoadBalanceTimeout = builder.LoadBalanceTimeout, diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionDetails.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionDetails.cs index 62fe86b3..d16dc062 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionDetails.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionDetails.cs @@ -99,6 +99,22 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts } } + /// + /// Gets or sets a value that specifies that Always Encrypted functionality is enabled in a connection. + /// + public string ColumnEncryptionSetting + { + get + { + return GetOptionValue("columnEncryptionSetting"); + } + + set + { + SetOptionValue("columnEncryptionSetting", value); + } + } + /// /// Gets or sets a Boolean value that indicates whether SQL Server uses SSL encryption for all data sent between the client and server if the server has a certificate installed. /// diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionDetailsExtensions.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionDetailsExtensions.cs index aeee8760..200a6825 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionDetailsExtensions.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/Contracts/ConnectionDetailsExtensions.cs @@ -22,6 +22,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.Contracts UserName = details.UserName, Password = details.Password, AuthenticationType = details.AuthenticationType, + ColumnEncryptionSetting = details.ColumnEncryptionSetting, Encrypt = details.Encrypt, TrustServerCertificate = details.TrustServerCertificate, PersistSecurityInfo = details.PersistSecurityInfo, diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs index a020ee55..10d8670d 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.cs @@ -2987,6 +2987,11 @@ namespace Microsoft.SqlTools.ServiceLayer return Keys.GetString(Keys.ConnectionServiceConnStringInvalidAuthType, authType); } + public static string ConnectionServiceConnStringInvalidColumnEncryptionSetting(string columnEncryptionSetting) + { + return Keys.GetString(Keys.ConnectionServiceConnStringInvalidColumnEncryptionSetting, columnEncryptionSetting); + } + public static string ConnectionServiceConnStringInvalidIntent(string intent) { return Keys.GetString(Keys.ConnectionServiceConnStringInvalidIntent, intent); @@ -3160,6 +3165,9 @@ namespace Microsoft.SqlTools.ServiceLayer public const string ConnectionServiceConnStringInvalidAuthType = "ConnectionServiceConnStringInvalidAuthType"; + public const string ConnectionServiceConnStringInvalidColumnEncryptionSetting = "ConnectionServiceConnStringInvalidColumnEncryptionSetting"; + + public const string ConnectionServiceConnStringInvalidIntent = "ConnectionServiceConnStringInvalidIntent"; diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx index 84d53caf..50897977 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.resx @@ -139,7 +139,12 @@ Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. . Parameters: 0 - authType (string) - + + + Invalid value '{0}' for ComlumEncryption. Valid values are 'Enabled' and 'Disabled'. + . + Parameters: 0 - columnEncryptionSetting (string) + Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. . diff --git a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings index 90801b27..27bb8c0e 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings +++ b/src/Microsoft.SqlTools.ServiceLayer/Localization/sr.strings @@ -33,6 +33,8 @@ ConnectionServiceDbErrorDefaultNotConnected(string uri) = Specified URI '{0}' do ConnectionServiceConnStringInvalidAuthType(string authType) = Invalid value '{0}' for AuthenticationType. Valid values are 'Integrated' and 'SqlLogin'. +ConnectionServiceConnStringInvalidColumnEncryptionSetting(string columnEncryptionSetting) = Invalid value '{0}' for ComlumEncryption. Valid values are 'Enabled' and 'Disabled'. + ConnectionServiceConnStringInvalidIntent(string intent) = Invalid value '{0}' for ApplicationIntent. Valid values are 'ReadWrite' and 'ReadOnly'. ConnectionServiceConnectionCanceled = Connection canceled diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Connection/ConnectionDetailsTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Connection/ConnectionDetailsTests.cs index 6f32b3e7..7b1c2b62 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Connection/ConnectionDetailsTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Connection/ConnectionDetailsTests.cs @@ -44,6 +44,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection Assert.Equal(details.MaxPoolSize, expectedForInt); Assert.Equal(details.MinPoolSize, expectedForInt); Assert.Equal(details.PacketSize, expectedForInt); + Assert.Equal(details.ColumnEncryptionSetting, expectedForStrings); Assert.Equal(details.Encrypt, expectedForBoolean); Assert.Equal(details.MultipleActiveResultSets, expectedForBoolean); Assert.Equal(details.MultiSubnetFailover, expectedForBoolean); @@ -81,6 +82,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection details.MaxPoolSize = expectedForInt + index++; details.MinPoolSize = expectedForInt + index++; details.PacketSize = expectedForInt + index++; + details.ColumnEncryptionSetting = expectedForStrings + index++; details.Encrypt = (index++ % 2 == 0); details.MultipleActiveResultSets = (index++ % 2 == 0); details.MultiSubnetFailover = (index++ % 2 == 0); @@ -110,6 +112,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection Assert.Equal(details.MaxPoolSize, expectedForInt + index++); Assert.Equal(details.MinPoolSize, expectedForInt + index++); Assert.Equal(details.PacketSize, expectedForInt + index++); + Assert.Equal(details.ColumnEncryptionSetting, expectedForStrings + index++); Assert.Equal(details.Encrypt, (index++ % 2 == 0)); Assert.Equal(details.MultipleActiveResultSets, (index++ % 2 == 0)); Assert.Equal(details.MultiSubnetFailover, (index++ % 2 == 0)); @@ -148,6 +151,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection details.MaxPoolSize = expectedForInt + index++; details.MinPoolSize = expectedForInt + index++; details.PacketSize = expectedForInt + index++; + details.ColumnEncryptionSetting = expectedForStrings + index++; details.Encrypt = (index++ % 2 == 0); details.MultipleActiveResultSets = (index++ % 2 == 0); details.MultiSubnetFailover = (index++ % 2 == 0); diff --git a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Connection/ConnectionServiceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Connection/ConnectionServiceTests.cs index 87808943..c67a877d 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Connection/ConnectionServiceTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.UnitTests/Connection/ConnectionServiceTests.cs @@ -501,6 +501,14 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection [InlineData("AuthenticationType", "SqlLogin", "")] [InlineData("Encrypt", true, "Encrypt")] [InlineData("Encrypt", false, "Encrypt")] + [InlineData("ColumnEncryptionSetting", "Enabled", "Column Encryption Setting=Enabled")] + [InlineData("ColumnEncryptionSetting", "Disabled", "Column Encryption Setting=Disabled")] + [InlineData("ColumnEncryptionSetting", "enabled", "Column Encryption Setting=Enabled")] + [InlineData("ColumnEncryptionSetting", "disabled", "Column Encryption Setting=Disabled")] + [InlineData("ColumnEncryptionSetting", "ENABLED", "Column Encryption Setting=Enabled")] + [InlineData("ColumnEncryptionSetting", "DISABLED", "Column Encryption Setting=Disabled")] + [InlineData("ColumnEncryptionSetting", "eNaBlEd", "Column Encryption Setting=Enabled")] + [InlineData("ColumnEncryptionSetting", "DiSaBlEd", "Column Encryption Setting=Disabled")] [InlineData("TrustServerCertificate", true, "TrustServerCertificate")] [InlineData("TrustServerCertificate", false, "TrustServerCertificate")] [InlineData("PersistSecurityInfo", true, "Persist Security Info")] @@ -545,13 +553,16 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Connection } /// - /// Build connection string with an invalid auth type + /// Build connection string with an invalid property type /// - [Fact] - public void BuildConnectionStringWithInvalidAuthType() + [Theory] + [InlineData("AuthenticationType", "NotAValidAuthType")] + [InlineData("ColumnEncryptionSetting", "NotAValidColumnEncryptionSetting")] + public void BuildConnectionStringWithInvalidOptions(string propertyName, object propertyValue) { ConnectionDetails details = TestObjects.GetTestConnectionDetails(); - details.AuthenticationType = "NotAValidAuthType"; + PropertyInfo info = details.GetType().GetProperty(propertyName); + info.SetValue(details, propertyValue); Assert.Throws(() => ConnectionService.BuildConnectionString(details)); }