From d6fe3ab95d434858e0918344450097577afb3027 Mon Sep 17 00:00:00 2001 From: Christian Specht Date: Sun, 5 Apr 2020 22:19:28 +0200 Subject: [PATCH] If passwords contain names of environment variables, replace with variable value (fixes #26) --- .../EnvironmentVariableConfigReaderTests.cs | 46 +++++++++++++++++++ src/ScmBackup/CompositionRoot/Bootstrapper.cs | 4 +- .../EnvironmentVariableConfigReader.cs | 41 +++++++++++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 src/ScmBackup.Tests/ConfigTests/EnvironmentVariableConfigReaderTests.cs create mode 100644 src/ScmBackup/Configuration/EnvironmentVariableConfigReader.cs diff --git a/src/ScmBackup.Tests/ConfigTests/EnvironmentVariableConfigReaderTests.cs b/src/ScmBackup.Tests/ConfigTests/EnvironmentVariableConfigReaderTests.cs new file mode 100644 index 0000000..8703b79 --- /dev/null +++ b/src/ScmBackup.Tests/ConfigTests/EnvironmentVariableConfigReaderTests.cs @@ -0,0 +1,46 @@ +using ScmBackup.Configuration; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Xunit; + +namespace ScmBackup.Tests.ConfigTests +{ + public class EnvironmentVariableConfigReaderTests + { + private IConfigReader sut; + private FakeConfigReader reader; + + public EnvironmentVariableConfigReaderTests() + { + reader = new FakeConfigReader(); + reader.SetDefaultFakeConfig(); + sut = new EnvironmentVariableConfigReader(reader); + + Environment.SetEnvironmentVariable("scmbackup_test", "foo"); + } + + [Theory] + [InlineData("%scmbackup_test%bar", "foobar")] // part of the password + [InlineData("%scmbackup_test%", "foo")] // whole password + public void ReplacesInPassword(string originalPw, string changedPw) + { + reader.FakeConfig.Sources.First().Password = originalPw; + + var result = sut.ReadConfig(); + + Assert.Equal(changedPw, result.Sources.First().Password); + } + + [Fact] + public void DoesNothingWhenPasswordContainsNoVariable() + { + reader.FakeConfig.Sources.First().Password = "bar"; + + var result = sut.ReadConfig(); + + Assert.Equal("bar", result.Sources.First().Password); + } + } +} diff --git a/src/ScmBackup/CompositionRoot/Bootstrapper.cs b/src/ScmBackup/CompositionRoot/Bootstrapper.cs index d186611..3b2711f 100644 --- a/src/ScmBackup/CompositionRoot/Bootstrapper.cs +++ b/src/ScmBackup/CompositionRoot/Bootstrapper.cs @@ -1,4 +1,5 @@ -using ScmBackup.Hosters; +using ScmBackup.Configuration; +using ScmBackup.Hosters; using ScmBackup.Http; using ScmBackup.Loggers; using ScmBackup.Scm; @@ -34,6 +35,7 @@ public static Container BuildContainer() container.Register(); container.Register(Lifestyle.Singleton); + container.RegisterDecorator(Lifestyle.Singleton); container.RegisterDecorator(Lifestyle.Singleton); container.Register(); diff --git a/src/ScmBackup/Configuration/EnvironmentVariableConfigReader.cs b/src/ScmBackup/Configuration/EnvironmentVariableConfigReader.cs new file mode 100644 index 0000000..09d5898 --- /dev/null +++ b/src/ScmBackup/Configuration/EnvironmentVariableConfigReader.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ScmBackup.Configuration +{ + /// + /// decorator for ConfigReader, replaces %foo% values with the respective environment variables + /// + internal class EnvironmentVariableConfigReader : IConfigReader + { + private readonly IConfigReader configReader; + private Config config = null; + + public EnvironmentVariableConfigReader(IConfigReader configReader) + { + this.configReader = configReader; + } + + public Config ReadConfig() + { + if (this.config != null) + { + return this.config; + } + + var config = this.configReader.ReadConfig(); + + foreach (var source in config.Sources) + { + if (!string.IsNullOrWhiteSpace(source.Password)) + { + source.Password = Environment.ExpandEnvironmentVariables(source.Password); + } + } + + this.config = config; + return config; + } + } +}