diff --git a/Snowflake.Data.Tests/UnitTests/Tools/FileOperationsTest.cs b/Snowflake.Data.Tests/UnitTests/Tools/FileOperationsTest.cs new file mode 100644 index 000000000..b175dd079 --- /dev/null +++ b/Snowflake.Data.Tests/UnitTests/Tools/FileOperationsTest.cs @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2024 Snowflake Computing Inc. All rights reserved. + */ + + +namespace Snowflake.Data.Tests.Tools +{ + using System.IO; + using System.Runtime.InteropServices; + using Mono.Unix; + using Mono.Unix.Native; + using NUnit.Framework; + using Snowflake.Data.Core.Tools; + using static Snowflake.Data.Tests.UnitTests.Configuration.EasyLoggingConfigGenerator; + using System.Security; + + [TestFixture, NonParallelizable] + public class FileOperationsTest + { + private static FileOperations s_fileOperations; + private static readonly string s_workingDirectory = Path.Combine(Path.GetTempPath(), "file_operations_test_", Path.GetRandomFileName()); + + [OneTimeSetUp] + public static void BeforeAll() + { + if (!Directory.Exists(s_workingDirectory)) + { + Directory.CreateDirectory(s_workingDirectory); + } + + s_fileOperations = new FileOperations(); + } + + [OneTimeTearDown] + public static void AfterAll() + { + Directory.Delete(s_workingDirectory, true); + } + + [Test] + public void TestReadAllTextOnWindows() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + Assert.Ignore("skip test only runs on Windows"); + } + + var content = "random text"; + var filePath = CreateConfigTempFile(s_workingDirectory, content); + + // act + var result = s_fileOperations.ReadAllText(filePath); + + // assert + Assert.AreEqual(content, result); + } + + [Test] + public void TestReadAllTextCheckingPermissions() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + Assert.Ignore("skip test on Windows"); + } + + var content = "random text"; + var filePath = CreateConfigTempFile(s_workingDirectory, content); + var filePermissions = FileAccessPermissions.UserReadWriteExecute; + Syscall.chmod(filePath, (FilePermissions)filePermissions); + + // act + var result = s_fileOperations.ReadAllText(filePath); + + // assert + Assert.AreEqual(content, result); + } + + [Test] + public void TestShouldThrowExceptionIfOtherPermissionsIsSetWhenReadAllText() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + Assert.Ignore("skip test on Windows"); + } + + var content = "random text"; + var filePath = CreateConfigTempFile(s_workingDirectory, content); + var filePermissions = FileAccessPermissions.UserReadWriteExecute | FileAccessPermissions.OtherReadWriteExecute; + Syscall.chmod(filePath, (FilePermissions)filePermissions); + + // act and assert + Assert.Throws(() => s_fileOperations.ReadAllText(filePath), + "Attempting to read a file with too broad permissions assigned"); + } + } +} diff --git a/Snowflake.Data.Tests/UnitTests/Tools/UnixOperationsTest.cs b/Snowflake.Data.Tests/UnitTests/Tools/UnixOperationsTest.cs index fde51602c..c3931e30e 100644 --- a/Snowflake.Data.Tests/UnitTests/Tools/UnixOperationsTest.cs +++ b/Snowflake.Data.Tests/UnitTests/Tools/UnixOperationsTest.cs @@ -9,12 +9,14 @@ namespace Snowflake.Data.Tests.Tools { + using System.Security; + [TestFixture, NonParallelizable] public class UnixOperationsTest { private static UnixOperations s_unixOperations; private static readonly string s_workingDirectory = Path.Combine(Path.GetTempPath(), "easy_logging_test_configs_", Path.GetRandomFileName()); - + [OneTimeSetUp] public static void BeforeAll() { @@ -34,7 +36,7 @@ public static void AfterAll() return; Directory.Delete(s_workingDirectory, true); } - + [Test] public void TestDetectGroupOrOthersWritablePermissions( [ValueSource(nameof(GroupOrOthersWritablePermissions))] FilePermissions groupOrOthersWritablePermissions, @@ -45,23 +47,23 @@ public void TestDetectGroupOrOthersWritablePermissions( { Assert.Ignore("skip test on Windows"); } - + // arrange var filePath = CreateConfigTempFile(s_workingDirectory, "random text"); var readWriteUserPermissions = FilePermissions.S_IRUSR | FilePermissions.S_IWUSR; var filePermissions = readWriteUserPermissions | groupOrOthersWritablePermissions | groupNotWritablePermissions | otherNotWritablePermissions; Syscall.chmod(filePath, filePermissions); - + // act var result = s_unixOperations.CheckFileHasAnyOfPermissions(filePath, FileAccessPermissions.GroupWrite | FileAccessPermissions.OtherWrite); - + // assert Assert.IsTrue(result); } [Test] public void TestDetectGroupOrOthersNotWritablePermissions( - [ValueSource(nameof(UserPermissions))] FilePermissions userPermissions, + [ValueSource(nameof(UserPermissions))] FilePermissions userPermissions, [ValueSource(nameof(GroupNotWritablePermissions))] FilePermissions groupNotWritablePermissions, [ValueSource(nameof(OtherNotWritablePermissions))] FilePermissions otherNotWritablePermissions) { @@ -69,18 +71,52 @@ public void TestDetectGroupOrOthersNotWritablePermissions( { Assert.Ignore("skip test on Windows"); } - + var filePath = CreateConfigTempFile(s_workingDirectory, "random text"); var filePermissions = userPermissions | groupNotWritablePermissions | otherNotWritablePermissions; Syscall.chmod(filePath, filePermissions); - + // act var result = s_unixOperations.CheckFileHasAnyOfPermissions(filePath, FileAccessPermissions.GroupWrite | FileAccessPermissions.OtherWrite); - + // assert Assert.IsFalse(result); } + [Test] + public void TestReadAllTextCheckingPermissions() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + Assert.Ignore("skip test on Windows"); + } + var content = "random text"; + var filePath = CreateConfigTempFile(s_workingDirectory, content); + var filePermissions = FileAccessPermissions.UserReadWriteExecute; + Syscall.chmod(filePath, (FilePermissions)filePermissions); + + // act + var result = s_unixOperations.ReadAllText(filePath); + + // assert + Assert.AreEqual(content, result); + } + + [Test] + public void TestShouldThrowExceptionIfOtherPermissionsIsSetWhenReadAllText() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + Assert.Ignore("skip test on Windows"); + } + var content = "random text"; + var filePath = CreateConfigTempFile(s_workingDirectory, content); + var filePermissions = FileAccessPermissions.UserReadWriteExecute | FileAccessPermissions.OtherReadWriteExecute; + Syscall.chmod(filePath, (FilePermissions)filePermissions); + + // act and assert + Assert.Throws(() => s_unixOperations.ReadAllText(filePath), "Attempting to read a file with too broad permissions assigned"); + } public static IEnumerable UserPermissions() { @@ -89,14 +125,14 @@ public static IEnumerable UserPermissions() yield return FilePermissions.S_IXUSR; yield return FilePermissions.S_IRUSR | FilePermissions.S_IWUSR | FilePermissions.S_IXUSR; } - + public static IEnumerable GroupOrOthersWritablePermissions() { yield return FilePermissions.S_IWGRP; yield return FilePermissions.S_IWOTH; yield return FilePermissions.S_IWGRP | FilePermissions.S_IWOTH; } - + public static IEnumerable GroupNotWritablePermissions() { yield return 0; diff --git a/Snowflake.Data/Client/SnowflakeDbConnection.cs b/Snowflake.Data/Client/SnowflakeDbConnection.cs index a7290ab26..0bd9b0d94 100755 --- a/Snowflake.Data/Client/SnowflakeDbConnection.cs +++ b/Snowflake.Data/Client/SnowflakeDbConnection.cs @@ -2,18 +2,16 @@ * Copyright (c) 2012-2021 Snowflake Computing Inc. All rights reserved. */ -using System; -using System.Data.Common; -using Snowflake.Data.Core; -using System.Security; -using System.Threading.Tasks; -using System.Data; -using System.Threading; -using Snowflake.Data.Log; - namespace Snowflake.Data.Client { - using Core.Tools; + using System; + using System.Data.Common; + using Snowflake.Data.Core; + using System.Security; + using System.Threading.Tasks; + using System.Data; + using System.Threading; + using Snowflake.Data.Log; [System.ComponentModel.DesignerCategory("Code")] public class SnowflakeDbConnection : DbConnection @@ -320,6 +318,7 @@ public override Task OpenAsync(CancellationToken cancellationToken) } registerConnectionCancellationCallback(cancellationToken); OnSessionConnecting(); + FillConnectionStringFromTomlConfigIfNotSet(); return SnowflakeDbConnectionPool .GetSessionAsync(ConnectionString, Password, cancellationToken) .ContinueWith(previousTask =>