Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SNOW-715524: Add SSO token cache #921

Open
wants to merge 138 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
Show all changes
138 commits
Select commit Hold shift + click to select a range
7de3ea6
SNOW-715524: Add SSO token cache
sfc-gh-ext-simba-lf Apr 18, 2024
4457077
Add tests
sfc-gh-ext-simba-lf Apr 18, 2024
15a58be
Remove unused namespace
sfc-gh-ext-simba-lf Apr 18, 2024
632a6b0
Merge branch 'master' into SNOW-715524-SSO-Token-Cache
sfc-gh-ext-simba-lf Apr 18, 2024
7f28fa8
Fix unit test
sfc-gh-ext-simba-lf Apr 18, 2024
a317158
Refactor constructor and tests
sfc-gh-ext-simba-lf Apr 18, 2024
625e04b
Refactor test
sfc-gh-ext-simba-lf Apr 18, 2024
383fe5e
Refactor test and file impl
sfc-gh-ext-simba-lf Apr 19, 2024
8ce9d10
Refactor file name and fix test
sfc-gh-ext-simba-lf Apr 19, 2024
a460e4b
Merge branch 'master' of https://github.com/snowflakedb/snowflake-con…
sfc-gh-ext-simba-lf Apr 19, 2024
e0b65d0
Revert removed lines
sfc-gh-ext-simba-lf Apr 19, 2024
6606823
Refactor code and remove unnecessary check
sfc-gh-ext-simba-lf Apr 19, 2024
4e6869d
Add session test
sfc-gh-ext-simba-lf Apr 19, 2024
3788474
Fix test
sfc-gh-ext-simba-lf Apr 19, 2024
c597c64
Refactor test and rename file
sfc-gh-ext-simba-lf Apr 19, 2024
39b90b2
Merge branch 'master' of https://github.com/snowflakedb/snowflake-con…
sfc-gh-ext-simba-lf Apr 29, 2024
b4ab4ed
Add more logging
sfc-gh-ext-simba-lf May 1, 2024
13ba839
Change log from error to info
sfc-gh-ext-simba-lf May 1, 2024
b334fb3
Add file path to logs
sfc-gh-ext-simba-lf May 2, 2024
623ce6a
Add Meziantou package for credential manager implementation
sfc-gh-ext-simba-lf May 8, 2024
976bac2
Add native implementation of credential cache
sfc-gh-ext-simba-lf May 17, 2024
feab579
Add impl for ReleaseHandle
sfc-gh-ext-simba-lf May 17, 2024
61b2317
Merge branch 'master' of https://github.com/snowflakedb/snowflake-con…
sfc-gh-ext-simba-lf Jun 5, 2024
cb1c84f
Remove MfaToken from TokenType enum
sfc-gh-ext-simba-lf Jun 5, 2024
7f0f801
Add class name to the log
sfc-gh-ext-simba-lf Jun 5, 2024
780d213
Add class name to the log
sfc-gh-ext-simba-lf Jun 5, 2024
575c0a4
Add class name to the log
sfc-gh-ext-simba-lf Jun 5, 2024
aa00982
Add class name to default log message
sfc-gh-ext-simba-lf Jun 5, 2024
ecdcf37
Merge branch 'SNOW-715524-SSO-Token-Cache' of https://github.com/snow…
sfc-gh-ext-simba-lf Jun 5, 2024
6f31fe6
Rename native class and remove impl with external libs
sfc-gh-ext-simba-lf Jun 5, 2024
cdc9f80
Use HomeDirectoryProvider to retrieve the default location
sfc-gh-ext-simba-lf Jun 5, 2024
9622f5c
Check if json file already exists
sfc-gh-ext-simba-lf Jun 5, 2024
a2f9b50
Change parameter from string to enum
sfc-gh-ext-simba-lf Jun 5, 2024
739c40c
Remove encryption for in-memory credential manager
sfc-gh-ext-simba-lf Jun 6, 2024
c502e80
Change modifier for dictionary
sfc-gh-ext-simba-lf Jun 6, 2024
465da80
Change public modifier for credential manager factory
sfc-gh-ext-simba-lf Jun 6, 2024
94bce01
Move credential manager files to core folder
sfc-gh-ext-simba-lf Jun 6, 2024
83119f3
Move interface and implementations to subpackage
sfc-gh-ext-simba-lf Jun 6, 2024
4e57147
Merge branch 'master' of https://github.com/snowflakedb/snowflake-con…
sfc-gh-ext-simba-lf Jun 12, 2024
61855f2
Remove unused packages
sfc-gh-ext-simba-lf Jun 13, 2024
8b38fed
Include ".snowflake" to the default cache directory
sfc-gh-ext-simba-lf Jun 17, 2024
194eafa
Refactor credential manager
sfc-gh-ext-simba-lf Jun 17, 2024
8666194
Refactor credential manager
sfc-gh-ext-simba-lf Jun 17, 2024
403dbd2
Merge branch 'SNOW-715524-SSO-Token-Cache' of https://github.com/snow…
sfc-gh-ext-simba-lf Jun 17, 2024
33ebec5
Refactor external browser authentication
sfc-gh-ext-simba-lf Jun 18, 2024
512de5b
Remove modifying file permission on Windows
sfc-gh-ext-simba-lf Jun 20, 2024
6ef9b35
Modify test to open the second connection before calling close
sfc-gh-ext-simba-lf Jun 25, 2024
d616dcc
Modify session property test
sfc-gh-ext-simba-lf Jun 25, 2024
045fc04
Uncomment line in session property test
sfc-gh-ext-simba-lf Jun 25, 2024
5c9d8d7
Add check for new map parameter value
sfc-gh-ext-simba-lf Jun 25, 2024
adb3218
Replace user and add test explanation
sfc-gh-ext-simba-lf Jun 26, 2024
da0cffb
Remove unused packages
sfc-gh-ext-simba-lf Jun 28, 2024
44c746b
Add mock for browser and tests for external browser authentication
sfc-gh-ext-simba-lf Jul 4, 2024
590e98b
Merge branch 'master' of https://github.com/snowflakedb/snowflake-con…
sfc-gh-ext-simba-lf Jul 4, 2024
2abcad4
Temporarily ignore test while looking for fix
sfc-gh-ext-simba-lf Jul 4, 2024
dd24c76
Temporarily ignore test while looking for fix
sfc-gh-ext-simba-lf Jul 4, 2024
f8b3230
Merge branch 'master' of https://github.com/snowflakedb/snowflake-con…
sfc-gh-ext-simba-lf Jul 4, 2024
7a384e8
Rename internal property based on convention and fix missing comma
sfc-gh-ext-simba-lf Jul 4, 2024
7672901
Fix exception not being thrown while listening for browser response
sfc-gh-ext-simba-lf Jul 6, 2024
2cdbae4
Mark browser tests nonparallelizable
sfc-gh-ext-simba-lf Jul 6, 2024
524b78f
Catch HttpListenerException
sfc-gh-ext-simba-lf Jul 6, 2024
6fdf045
Catch HttpListenerException
sfc-gh-ext-simba-lf Jul 6, 2024
2d2870d
Add error logs
sfc-gh-ext-simba-lf Jul 6, 2024
f8f7336
Add check if event is still waiting for response before getting the c…
sfc-gh-ext-simba-lf Jul 8, 2024
8af5ba8
Revert event check and add log to check port number
sfc-gh-ext-simba-lf Jul 8, 2024
e56b086
Add log for browser port number
sfc-gh-ext-simba-lf Jul 8, 2024
2ba9aaf
Remove printing port number and add check if result is completed
sfc-gh-ext-simba-lf Jul 8, 2024
7e9c098
Remove printing result.IsCompleted line
sfc-gh-ext-simba-lf Jul 8, 2024
e49ed64
Remove catching HttpListenerException
sfc-gh-ext-simba-lf Jul 8, 2024
c434184
Catch HttpListenerException
sfc-gh-ext-simba-lf Jul 8, 2024
67a8fbf
Add check if result is completed and add wait for result
sfc-gh-ext-simba-lf Jul 8, 2024
f8fcf2b
Add detail for listener exception
sfc-gh-ext-simba-lf Jul 8, 2024
a46f1ad
Specify parameter as AsyncCallback
sfc-gh-ext-simba-lf Jul 8, 2024
52bfd3e
Refactor saml request functions
sfc-gh-ext-simba-lf Jul 9, 2024
9edfd79
Increase browser response timeout for test
sfc-gh-ext-simba-lf Jul 9, 2024
f6d8a0f
Remove catching HttpListenerException
sfc-gh-ext-simba-lf Jul 9, 2024
77a69b3
Remove unnecessary NonParallelizable attribute
sfc-gh-ext-simba-lf Jul 9, 2024
9038ba1
Revert remove catching HttpListenerException
sfc-gh-ext-simba-lf Jul 9, 2024
d800e6f
Refactor if check
sfc-gh-ext-simba-lf Jul 9, 2024
58b74d8
Add temp console lines
sfc-gh-ext-simba-lf Jul 9, 2024
8f919e7
Remove console lines
sfc-gh-ext-simba-lf Jul 9, 2024
fbbac23
Stop http listener before throwing browser exceptions
sfc-gh-ext-simba-lf Jul 9, 2024
d53dd8f
Close HttpListener before throwing exception
sfc-gh-ext-simba-lf Jul 9, 2024
98df45e
Close HttpListener before throwing exception
sfc-gh-ext-simba-lf Jul 9, 2024
359cfa3
Modify browser timeout test
sfc-gh-ext-simba-lf Jul 9, 2024
85d04ed
Abort HttpListener before throwing exception
sfc-gh-ext-simba-lf Jul 9, 2024
2d39171
Check if browser timeout already reached before getting context
sfc-gh-ext-simba-lf Jul 9, 2024
f7be152
Use SecureString for tokens
sfc-gh-ext-simba-lf Jul 9, 2024
2f20edd
Add security checks when reading the credential cache json
sfc-gh-ext-simba-lf Jul 10, 2024
ac1d659
Add error logs when reading the json cache file
sfc-gh-ext-simba-lf Jul 10, 2024
8c65f4d
Merge branch 'master' of https://github.com/snowflakedb/snowflake-con…
sfc-gh-ext-simba-lf Jul 17, 2024
330fca9
Merge branch 'master' of https://github.com/snowflakedb/snowflake-con…
sfc-gh-ext-simba-lf Jul 24, 2024
fc928fc
Merge branch 'master' of https://github.com/snowflakedb/snowflake-con…
sfc-gh-ext-simba-lf Aug 6, 2024
d53955a
Merge branch 'master' into SNOW-715524-SSO-Token-Cache
sfc-gh-ext-simba-lf Aug 21, 2024
d6ff05a
Merge branch 'master' of https://github.com/snowflakedb/snowflake-con…
sfc-gh-ext-simba-lf Aug 27, 2024
a1a6a31
Merge branch 'master' into SNOW-715524-SSO-Token-Cache
sfc-gh-ext-simba-lf Aug 30, 2024
74963c7
Merge branch 'master' of https://github.com/snowflakedb/snowflake-con…
sfc-gh-ext-simba-lf Sep 3, 2024
126e337
Merge branch 'master' into SNOW-715524-SSO-Token-Cache
sfc-gh-ext-simba-lf Sep 6, 2024
21b9f33
Merge branch 'master' of https://github.com/snowflakedb/snowflake-con…
sfc-gh-ext-simba-lf Jan 21, 2025
17877b8
Modify external browser test after rebase
sfc-gh-ext-simba-lf Jan 22, 2025
f6a536f
Fix session test
sfc-gh-ext-simba-lf Jan 22, 2025
d0c33e7
Merge branch 'master' into SNOW-715524-SSO-Token-Cache
sfc-gh-ext-simba-lf Jan 24, 2025
06020dd
Merge branch 'master' of https://github.com/snowflakedb/snowflake-con…
sfc-gh-ext-simba-lf Jan 24, 2025
41cadc3
Merge branch 'SNOW-715524-SSO-Token-Cache' of https://github.com/snow…
sfc-gh-ext-simba-lf Jan 24, 2025
03fd55c
Retrigger checks
sfc-gh-ext-simba-lf Jan 29, 2025
0fc3252
Merge branch 'master' into SNOW-715524-SSO-Token-Cache
sfc-gh-ext-simba-lf Jan 29, 2025
af2fb8c
Replace and remove SFCredentialManagerFactory class
sfc-gh-ext-simba-lf Jan 30, 2025
b4fdf7e
Revert external browser tests
sfc-gh-ext-simba-lf Jan 30, 2025
a941a25
Use SecureStringHelper.Decode
sfc-gh-ext-simba-lf Feb 5, 2025
8003c05
Revert newline
sfc-gh-ext-simba-lf Feb 5, 2025
6f64576
Refactor parameter name to CLIENT_STORE_TEMPORARY_CREDENTIAL
sfc-gh-ext-simba-lf Feb 12, 2025
35d37bb
Fix non-Windows test
sfc-gh-ext-simba-lf Feb 12, 2025
8e60e02
Merge branch 'master' of https://github.com/snowflakedb/snowflake-con…
sfc-gh-ext-simba-lf Feb 13, 2025
e18c93c
Replace using "cmd" for opening urls
sfc-gh-ext-simba-lf Feb 26, 2025
2d86687
Modify to only store token cache for connection strings with a user
sfc-gh-ext-simba-lf Feb 26, 2025
787a088
Modify from changing the permission to only log a warning for insecur…
sfc-gh-ext-simba-lf Feb 27, 2025
e5ef7ee
Modify test for security permission changes
sfc-gh-ext-simba-lf Feb 27, 2025
0a9c68f
Rename ALLOW_SSO_TOKEN_CACHING to CLIENT_STORE_TEMPORARY_CREDENTIAL
sfc-gh-ext-simba-lf Mar 4, 2025
e188833
Update default value for parameter
sfc-gh-ext-simba-lf Mar 4, 2025
f7fef4c
Modify test to use different connection and disable pooling
sfc-gh-ext-simba-lf Mar 5, 2025
8784fd0
Rename file to match class name
sfc-gh-ext-simba-lf Mar 5, 2025
7bb6971
Removed unused NETFRAMEWORK code
sfc-gh-ext-simba-lf Mar 5, 2025
09632d9
Remove new AsyncCallback
sfc-gh-ext-simba-lf Mar 5, 2025
ed728c7
Remove try catch clause
sfc-gh-ext-simba-lf Mar 5, 2025
b22d07d
Add extra check for test
sfc-gh-ext-simba-lf Mar 5, 2025
f85fc7a
Fix assertion check and apply same change to async versions
sfc-gh-ext-simba-lf Mar 5, 2025
29815db
Refactor exception on tests
sfc-gh-ext-simba-lf Mar 5, 2025
b32baf8
Refactor to get token from cache
sfc-gh-ext-simba-lf Mar 5, 2025
11865ba
Merge branch 'master' of https://github.com/snowflakedb/snowflake-con…
sfc-gh-ext-simba-lf Mar 6, 2025
1367720
Remove try catch statement
sfc-gh-ext-simba-lf Mar 6, 2025
ac8e490
Set default value
sfc-gh-ext-simba-lf Mar 6, 2025
380840b
Remove else statement
sfc-gh-ext-simba-lf Mar 7, 2025
9186c81
Move fields from Session to ExternalBrowserAuthenticator
sfc-gh-ext-simba-lf Mar 7, 2025
20cb14c
Move error check to ExternalBrowser
sfc-gh-ext-simba-lf Mar 7, 2025
91b0834
Save token as SecureString and only hit cache once
sfc-gh-ext-simba-lf Mar 7, 2025
ef168ad
Set default value for idTokenKey
sfc-gh-ext-simba-lf Mar 7, 2025
6bb9758
Revert "Move error check to ExternalBrowser"
sfc-gh-ext-simba-lf Mar 7, 2025
0ba57ed
Fix reference to idTokenKey
sfc-gh-ext-simba-lf Mar 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Refactor test and file impl
  • Loading branch information
sfc-gh-ext-simba-lf committed Apr 19, 2024
commit 383fe5eed92732c8edd2ac5fedfb2135e34ee296
Original file line number Diff line number Diff line change
@@ -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");
@@ -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);
}

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

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

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

// act & assert
TestCredentialManagerImplementation();
}

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

// act & assert
TestCredentialManagerImplementation();
}

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

// act & assert
TestCredentialManagerImplementation();
}

@@ -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"));
@@ -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"));
18 changes: 18 additions & 0 deletions Snowflake.Data.Tests/UnitTests/SFSessionTest.cs
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@ namespace Snowflake.Data.Tests.UnitTests
{
using Snowflake.Data.Core;
using NUnit.Framework;
using System;

[TestFixture]
class SFSessionTest
@@ -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
@@ -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),
@@ -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)
{
@@ -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";
@@ -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();

@@ -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);
@@ -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);
Loading