Skip to content

Commit

Permalink
Refactor test and file impl
Browse files Browse the repository at this point in the history
  • Loading branch information
sfc-gh-ext-simba-lf committed Apr 19, 2024
1 parent 625e04b commit 383fe5e
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ class SFCredentialManager
[ThreadStatic]
private static Mock<UnixOperations> t_unixOperations;

[ThreadStatic]
private static Mock<EnvironmentOperations> t_environmentOperations;

private static readonly string s_expectedJsonDir = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);

private static readonly string s_expectedJsonPath = Path.Combine(s_expectedJsonDir, "temporary_credential.json");
Expand All @@ -37,6 +40,7 @@ [SetUp] public void SetUp()
t_fileOperations = new Mock<FileOperations>();
t_directoryOperations = new Mock<DirectoryOperations>();
t_unixOperations = new Mock<UnixOperations>();
t_environmentOperations = new Mock<EnvironmentOperations>();
SnowflakeCredentialManagerFactory.SetCredentialManager(SnowflakeCredentialManagerInMemoryImpl.Instance);
}

Expand All @@ -47,6 +51,7 @@ [TearDown] public void TearDown()

private void TestCredentialManagerImplementation()
{
// arrange
var key = SnowflakeCredentialManagerFactory.BuildCredentialKey("host", "user", "tokentype");
var expectedToken = "token";

Expand Down Expand Up @@ -122,6 +127,8 @@ public void TestAdysTechCredentialManager()
// arrange
SnowflakeCredentialManagerFactory.SetCredentialManager(SnowflakeCredentialManagerAdysTechImpl.Instance);
_credentialManager = SnowflakeCredentialManagerFactory.GetCredentialManager();

// act & assert
TestCredentialManagerImplementation();
}

Expand All @@ -131,6 +138,8 @@ public void TestInMemoryCredentialManager()
// arrange
SnowflakeCredentialManagerFactory.SetCredentialManager(SnowflakeCredentialManagerInMemoryImpl.Instance);
_credentialManager = SnowflakeCredentialManagerFactory.GetCredentialManager();

// act & assert
TestCredentialManagerImplementation();
}

Expand All @@ -140,6 +149,8 @@ public void TestJsonCredentialManager()
// arrange
SnowflakeCredentialManagerFactory.SetCredentialManager(SnowflakeCredentialManagerIFileImpl.Instance);
_credentialManager = SnowflakeCredentialManagerFactory.GetCredentialManager();

// act & assert
TestCredentialManagerImplementation();
}

Expand All @@ -152,23 +163,21 @@ public void TestThatThrowsErrorWhenCacheFileIsNotCreated()
}

// arrange
var key = SnowflakeCredentialManagerFactory.BuildCredentialKey("host", "user", "tokentype");
var token = "token";

t_directoryOperations
.Setup(d => d.Exists(s_expectedJsonDir))
.Returns(false);

t_unixOperations
.Setup(u => u.CreateFileWithPermissions(s_expectedJsonPath,
FilePermissions.S_IRUSR | FilePermissions.S_IWUSR | FilePermissions.S_IXUSR))
.Returns(-1);

SnowflakeCredentialManagerFactory.SetCredentialManager(new SnowflakeCredentialManagerIFileImpl(t_fileOperations.Object, t_directoryOperations.Object, t_unixOperations.Object));
t_environmentOperations
.Setup(e => e.GetEnvironmentVariable(SnowflakeCredentialManagerIFileImpl.CredentialCacheDirectoryEnvironmentName))
.Returns("testdirectory");
SnowflakeCredentialManagerFactory.SetCredentialManager(new SnowflakeCredentialManagerIFileImpl(t_fileOperations.Object, t_directoryOperations.Object, t_unixOperations.Object, t_environmentOperations.Object));
_credentialManager = SnowflakeCredentialManagerFactory.GetCredentialManager();

// act
var thrown = Assert.Throws<Exception>(() => _credentialManager.SaveCredentials(key, token));
var thrown = Assert.Throws<Exception>(() => _credentialManager.SaveCredentials("key", "token"));

// assert
Assert.That(thrown.Message, Does.Contain("Failed to create the JSON token cache file"));
Expand All @@ -183,22 +192,21 @@ public void TestThatThrowsErrorWhenCacheFileCanBeAccessedByOthers()
}

// arrange
var key = SnowflakeCredentialManagerFactory.BuildCredentialKey("host", "user", "tokentype");
var token = "token";

t_unixOperations
.Setup(u => u.CreateFileWithPermissions(s_expectedJsonPath,
FilePermissions.S_IRUSR | FilePermissions.S_IWUSR | FilePermissions.S_IXUSR))
.Returns(0);
t_unixOperations
.Setup(u => u.GetFilePermissions(s_expectedJsonPath))
.Returns(FileAccessPermissions.AllPermissions);

SnowflakeCredentialManagerFactory.SetCredentialManager(new SnowflakeCredentialManagerIFileImpl(t_fileOperations.Object, t_directoryOperations.Object, t_unixOperations.Object));
t_environmentOperations
.Setup(e => e.GetEnvironmentVariable(SnowflakeCredentialManagerIFileImpl.CredentialCacheDirectoryEnvironmentName))
.Returns("testdirectory");
SnowflakeCredentialManagerFactory.SetCredentialManager(new SnowflakeCredentialManagerIFileImpl(t_fileOperations.Object, t_directoryOperations.Object, t_unixOperations.Object, t_environmentOperations.Object));
_credentialManager = SnowflakeCredentialManagerFactory.GetCredentialManager();

// act
var thrown = Assert.Throws<Exception>(() => _credentialManager.SaveCredentials(key, token));
var thrown = Assert.Throws<Exception>(() => _credentialManager.SaveCredentials("key", "token"));

// assert
Assert.That(thrown.Message, Does.Contain("Permission for the JSON token cache file should contain only the owner access"));
Expand Down
18 changes: 18 additions & 0 deletions Snowflake.Data.Tests/UnitTests/SFSessionTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace Snowflake.Data.Tests.UnitTests
{
using Snowflake.Data.Core;
using NUnit.Framework;
using System;

[TestFixture]
class SFSessionTest
Expand Down Expand Up @@ -61,5 +62,22 @@ public void TestThatConfiguresEasyLogging(string configPath)
// assert
easyLoggingStarter.Verify(starter => starter.Init(configPath));
}

[Test]
public void TestThatRetriesAuthenticationForInvalidIdToken()
{
// arrange
var connectionString = "account=test;user=test;password=test;allow_sso_token_caching=true";
var session = new SFSession(connectionString, null);
LoginResponse authnResponse = new LoginResponse
{
code = SFError.ID_TOKEN_INVALID.GetAttribute<SFErrorAttr>().errorCode,
message = "",
success = false
};

// assert
Assert.Throws<NullReferenceException>(() => session.ProcessLoginResponse(authnResponse));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,39 +18,46 @@ namespace Snowflake.Data.Client
{
public class SnowflakeCredentialManagerIFileImpl : ISnowflakeCredentialManager
{
private const string CredentialCacheDirectoryEnvironmentName = "SF_TEMPORARY_CREDENTIAL_CACHE_DIR";

private static readonly string CustomCredentialCacheDirectory = Environment.GetEnvironmentVariable(CredentialCacheDirectoryEnvironmentName);

private static readonly string DefaultCredentialCacheDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);

private static readonly string JsonCacheDirectory = string.IsNullOrEmpty(CustomCredentialCacheDirectory) ? DefaultCredentialCacheDirectory : CustomCredentialCacheDirectory;
internal const string CredentialCacheDirectoryEnvironmentName = "SF_TEMPORARY_CREDENTIAL_CACHE_DIR";

private static readonly SFLogger s_logger = SFLoggerFactory.GetLogger<SnowflakeCredentialManagerIFileImpl>();

private static readonly string s_jsonPath = Path.Combine(JsonCacheDirectory, "temporary_credential.json");
private readonly string _jsonCacheDirectory;

private readonly string _jsonCacheFilePath;

private readonly FileOperations _fileOperations;

private readonly DirectoryOperations _directoryOperations;

private readonly UnixOperations _unixOperations;

public static readonly SnowflakeCredentialManagerIFileImpl Instance = new SnowflakeCredentialManagerIFileImpl(FileOperations.Instance, DirectoryOperations.Instance, UnixOperations.Instance);
private readonly EnvironmentOperations _environmentOperations;

internal SnowflakeCredentialManagerIFileImpl(FileOperations fileOperations, DirectoryOperations directoryOperations, UnixOperations unixOperations)
public static readonly SnowflakeCredentialManagerIFileImpl Instance = new SnowflakeCredentialManagerIFileImpl(FileOperations.Instance, DirectoryOperations.Instance, UnixOperations.Instance, EnvironmentOperations.Instance);

internal SnowflakeCredentialManagerIFileImpl(FileOperations fileOperations, DirectoryOperations directoryOperations, UnixOperations unixOperations, EnvironmentOperations environmentOperations)
{
_fileOperations = fileOperations;
_directoryOperations = directoryOperations;
_unixOperations = unixOperations;
_environmentOperations = environmentOperations;
SetCredentialCachePath(ref _jsonCacheDirectory, ref _jsonCacheFilePath);
}

private void SetCredentialCachePath(ref string _jsonCacheDirectory, ref string _jsonCacheFilePath)
{
var customDirectory = _environmentOperations.GetEnvironmentVariable(CredentialCacheDirectoryEnvironmentName);
_jsonCacheDirectory = string.IsNullOrEmpty(customDirectory) ? _environmentOperations.GetFolderPath(Environment.SpecialFolder.UserProfile) : customDirectory;
_jsonCacheFilePath = Path.Combine(_jsonCacheDirectory, "temporary_credential.json");
}

internal void WriteToJsonFile(string content)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
_fileOperations.Write(s_jsonPath, content);
FileInfo info = new FileInfo(s_jsonPath);
_fileOperations.Write(_jsonCacheFilePath, content);
FileInfo info = new FileInfo(_jsonCacheFilePath);
FileSecurity security = info.GetAccessControl();
FileSystemAccessRule rule = new FileSystemAccessRule(
new SecurityIdentifier(WellKnownSidType.CreatorOwnerSid, null),
Expand All @@ -61,11 +68,11 @@ internal void WriteToJsonFile(string content)
}
else
{
if (!_directoryOperations.Exists(JsonCacheDirectory))
if (!_directoryOperations.Exists(_jsonCacheDirectory))
{
_directoryOperations.CreateDirectory(JsonCacheDirectory);
_directoryOperations.CreateDirectory(_jsonCacheDirectory);
}
var createFileResult = _unixOperations.CreateFileWithPermissions(s_jsonPath,
var createFileResult = _unixOperations.CreateFileWithPermissions(_jsonCacheFilePath,
FilePermissions.S_IRUSR | FilePermissions.S_IWUSR | FilePermissions.S_IXUSR);
if (createFileResult == -1)
{
Expand All @@ -75,10 +82,10 @@ internal void WriteToJsonFile(string content)
}
else
{
_fileOperations.Write(s_jsonPath, content);
_fileOperations.Write(_jsonCacheFilePath, content);
}

var jsonPermissions = _unixOperations.GetFilePermissions(s_jsonPath);
var jsonPermissions = _unixOperations.GetFilePermissions(_jsonCacheFilePath);
if (jsonPermissions != FileAccessPermissions.UserReadWriteExecute)
{
var errorMessage = "Permission for the JSON token cache file should contain only the owner access";
Expand All @@ -90,12 +97,12 @@ internal void WriteToJsonFile(string content)

internal KeyToken ReadJsonFile()
{
return JsonConvert.DeserializeObject<KeyToken>(File.ReadAllText(s_jsonPath));
return JsonConvert.DeserializeObject<KeyToken>(File.ReadAllText(_jsonCacheFilePath));
}

public string GetCredentials(string key)
{
if (_fileOperations.Exists(s_jsonPath))
if (_fileOperations.Exists(_jsonCacheFilePath))
{
var keyTokenPairs = ReadJsonFile();

Expand All @@ -111,7 +118,7 @@ public string GetCredentials(string key)

public void RemoveCredentials(string key)
{
if (_fileOperations.Exists(s_jsonPath))
if (_fileOperations.Exists(_jsonCacheFilePath))
{
var keyTokenPairs = ReadJsonFile();
keyTokenPairs.Remove(key);
Expand All @@ -121,7 +128,7 @@ public void RemoveCredentials(string key)

public void SaveCredentials(string key, string token)
{
KeyToken keyTokenPairs = _fileOperations.Exists(s_jsonPath) ? ReadJsonFile() : new KeyToken();
KeyToken keyTokenPairs = _fileOperations.Exists(_jsonCacheFilePath) ? ReadJsonFile() : new KeyToken();
keyTokenPairs[key] = token;

string jsonString = JsonConvert.SerializeObject(keyTokenPairs);
Expand Down

0 comments on commit 383fe5e

Please sign in to comment.