Skip to content

Commit

Permalink
Implement encryption of password
Browse files Browse the repository at this point in the history
  • Loading branch information
nmklotas committed Oct 24, 2017
1 parent d856f8d commit b689f31
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 25 deletions.
2 changes: 2 additions & 0 deletions src/GitlabCLI.Console/Configuration/AppSettings.cs
Expand Up @@ -27,5 +27,7 @@ public sealed class AppSettings

[JsonProperty("default_issues_label")]
public string DefaulIssuesLabel { get; set; }

public AppSettings Clone() => (AppSettings)MemberwiseClone();
}
}
89 changes: 70 additions & 19 deletions src/GitlabCLI.Console/Configuration/AppSettingsStorage.cs
@@ -1,4 +1,6 @@
using System.IO;
using System.Security.Cryptography;
using GitLabCLI.Console.Parameters;
using GitLabCLI.Utilities;
using Newtonsoft.Json;

Expand All @@ -8,47 +10,96 @@ public sealed class AppSettingsStorage
{
private readonly JsonSerializer _serializer;
private readonly string _settingsFile;
private AppSettings _settings;
private readonly Encryptor _encryptor;

public AppSettingsStorage(JsonSerializer serializer, string settingsFile)
public AppSettingsStorage(JsonSerializer serializer, string settingsFile, Encryptor encryptor)
{
_serializer = serializer;
_settingsFile = settingsFile;
_encryptor = encryptor;
}

public AppSettings Load()
{
if (_settings != null)
return _settings;

EnsureSettingsDirectoryExists();

if (!File.Exists(_settingsFile))
return new AppSettings();

using (var settingsStream = File.OpenText(_settingsFile))
using (var textReader = new JsonTextReader(settingsStream))
{
_settings = new AppSettings();
return _settings;
var settings = _serializer.Deserialize<AppSettings>(textReader) ?? new AppSettings();
DecryptSensitiveData(settings);
return settings;
}

using (var file = File.OpenText(_settingsFile))
using (var reader = new JsonTextReader(file))
_settings = _serializer.Deserialize<AppSettings>(reader) ?? new AppSettings();

return _settings;
}

public void Save(AppSettings settings)
{
EnsureSettingsDirectoryExists();

using (var fs = File.OpenWrite(_settingsFile))
using (var sw = new StreamWriter(fs))
using (var jw = new JsonTextWriter(sw))
using (var settingsStream = File.OpenWrite(_settingsFile))
using (var streamWriter = new StreamWriter(settingsStream))
using (var textWriter = new JsonTextWriter(streamWriter))
{
jw.Formatting = Formatting.Indented;
_serializer.Serialize(jw, settings);
textWriter.Formatting = Formatting.Indented;
SerializeSettings(textWriter, settings);
}
}

private void SerializeSettings(JsonTextWriter textWriter, AppSettings settings)
{
var settingsClone = settings.Clone();
EncryptSensitiveData(settingsClone);
_serializer.Serialize(textWriter, settingsClone);
}

private void EncryptSensitiveData(AppSettings settings)
{
if (!settings.GitLabPassword.IsNullOrEmpty())
settings.GitLabPassword = _encryptor.Encrypt(settings.GitLabPassword);

if (!settings.GitLabAccessToken.IsNullOrEmpty())
settings.GitLabAccessToken = _encryptor.Encrypt(settings.GitLabAccessToken);
}

_settings = settings;
private void DecryptSensitiveData(AppSettings settings)
{
if (!settings.GitLabPassword.IsNullOrEmpty())
{
SafeDecryptPassword();
}
if (!settings.GitLabAccessToken.IsNullOrEmpty())
{
SafeDecryptToken();
}

void SafeDecryptPassword()
{
try
{
settings.GitLabPassword = _encryptor.Decrypt(settings.GitLabPassword);
}
catch (CryptographicException)
{
//if we can't decrypt it, reset it
settings.GitLabPassword = null;
}
}

void SafeDecryptToken()
{
try
{
settings.GitLabAccessToken = _encryptor.Decrypt(settings.GitLabAccessToken);
}
catch (CryptographicException)
{
//if we can't decrypt it, reset it
settings.GitLabAccessToken = null;
}
}
}

private void EnsureSettingsDirectoryExists()
Expand Down
6 changes: 2 additions & 4 deletions src/GitlabCLI.Console/Configuration/AppSettingsValidator.cs
Expand Up @@ -16,7 +16,7 @@ public Result Validate()
"Run 'gitlab config --host {host}' to set host url.");

if (!ValidateAuthorizationSettings())
return Result.Fail("GitLab authentication options are not set.\r\n" +
return Result.Fail("GitLab authentication options are not set or failed to decrypt.\r\n" +
"You can set authentication options two ways:\r\n" +
"1. Run 'gitlab config --token {token}' if you have auth token.\r\n" +
"2. Run 'gitlab config --username {username} --password {password}' " +
Expand All @@ -30,9 +30,7 @@ public Result Validate()
private bool ValidateAuthorizationSettings()
{
bool tokenExits = !_settings.GitLabAccessToken.IsNullOrEmpty();
bool credentialsExits = !_settings.GitLabUserName.IsNullOrEmpty() ||
!_settings.GitLabPassword.IsNullOrEmpty();

bool credentialsExits = !_settings.GitLabUserName.IsNullOrEmpty() && !_settings.GitLabPassword.IsNullOrEmpty();
return tokenExits || credentialsExits;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/GitlabCLI.Console/Container.cs
Expand Up @@ -62,7 +62,7 @@ private static void RegisterGitLabServices(WindsorContainer container)

private static void RegisterSettingsServices(WindsorContainer container)
=> container.
Register(Component.For<AppSettingsStorage>().UsingFactoryMethod(c => new AppSettingsStorage(c.Resolve<JsonSerializer>(), GetSettingsFile()))).
Register(Component.For<AppSettingsStorage>().UsingFactoryMethod(c => new AppSettingsStorage(c.Resolve<JsonSerializer>(), GetSettingsFile(), c.Resolve<Encryptor>()))).
Register(Component.For<AppSettings>().UsingFactoryMethod(c => c.Resolve<AppSettingsStorage>().Load())).
Register(Component.For<GitLabSettings>().UsingFactoryMethod(c => Map(c.Resolve<AppSettings>())));

Expand Down
Expand Up @@ -2,6 +2,7 @@
using System.IO;
using FluentAssertions;
using GitLabCLI.Console.Configuration;
using GitLabCLI.Console.Parameters;
using Newtonsoft.Json;
using Xunit;

Expand All @@ -10,7 +11,7 @@ namespace GitLabCLI.Console.Test.Configuration
public sealed class AppSettingsStorageTest
{
private readonly Func<string, AppSettingsStorage> _sut = p => new AppSettingsStorage(
JsonSerializer.CreateDefault(), p);
JsonSerializer.CreateDefault(), p, new Encryptor());

private readonly AppSettings _settings = new AppSettings
{
Expand Down

0 comments on commit b689f31

Please sign in to comment.