public async Task Options() { var orgDirectory = Environment.CurrentDirectory; try { using (var testManager = new KubeTestManager()) { using (var runner = new ProgramRunner()) { using (var tempFolder = new TempFolder()) { Environment.CurrentDirectory = tempFolder.Path; //------------------------------------------------- // Verify that the [run] command handles command line options correctly. File.WriteAllText("test.cmd", "echo %* > output.txt"); var result = await runner.ExecuteAsync(Program.Main, "tool", "run", "--", "test.cmd", "-foo", "--bar=foobar", "--hello", "world"); Assert.Equal(0, result.ExitCode); Assert.Contains("-foo --bar=foobar --hello world", File.ReadAllText("output.txt")); } } } } finally { Environment.CurrentDirectory = orgDirectory; } }
public async Task VariableInjectEncrypted() { var orgDirectory = Environment.CurrentDirectory; try { using (var testManager = new KubeTestManager()) { using (var runner = new ProgramRunner()) { using (var tempFolder = new TempFolder()) { Environment.CurrentDirectory = tempFolder.Path; var vault = new NeonVault(Program.LookupPassword); // Create a test password and a [.password-name] file in the // temp test folder. var result = await runner.ExecuteAsync(Program.Main, "tool", "password", "set", "test"); Assert.Equal(0, result.ExitCode); //------------------------------------------------- // Verify that we can inject variables into an // ENCRYPTED file. File.WriteAllText("test.cmd", "type %1 > output.txt"); File.WriteAllText("file.txt", @" $<<TEST_A>> $<<TEST_B>> $<<TEST_C>> $<<TEST_D>> "); File.WriteAllBytes("file.txt", vault.Encrypt("file.txt", "test")); Assert.True(NeonVault.IsEncrypted("file.txt")); result = await runner.ExecuteAsync(Program.Main, "tool", "run", "--TEST_A=A-VALUE", "--TEST_B=B-VALUE", "--TEST_C=C-VALUE", "--TEST_D=D-VALUE", "--", "test.cmd", "_..file.txt"); Assert.Equal(0, result.ExitCode); var output = File.ReadAllText("output.txt"); Assert.Contains("A-VALUE", output); Assert.Contains("B-VALUE", output); Assert.Contains("C-VALUE", output); Assert.Contains("D-VALUE", output); File.Delete("output.txt"); File.Delete("file.txt"); } } } } finally { Environment.CurrentDirectory = orgDirectory; } }
public async Task PasswordList() { ExecuteResponse result; using (var testManager = new KubeTestManager()) { using (var runner = new ProgramRunner()) { // Verify that [help] works: result = await runner.ExecuteAsync(Program.Main, "help", "tool", "password", "list"); Assert.Equal(0, result.ExitCode); Assert.Contains("Lists passwords.", result.OutputText); // Add a few passwords: result = await runner.ExecuteAsync(Program.Main, "tool", "password", "rm", "--force", "*"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteWithInputAsync(Program.Main, "one", "tool", "password", "set", "pwd-1", "-"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteWithInputAsync(Program.Main, "two", "tool", "password", "set", "pwd-2", "-"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteWithInputAsync(Program.Main, "three", "tool", "password", "set", "pwd-3", "-"); Assert.Equal(0, result.ExitCode); // Verify that we can list via: list result = await runner.ExecuteAsync(Program.Main, "tool", "password", "list"); Assert.Equal(0, result.ExitCode); TestHelper.AssertEqualLines( @"pwd-1 pwd-2 pwd-3 ", result.OutputText); // Verify that we can list via: ls result = await runner.ExecuteAsync(Program.Main, "tool", "password", "ls"); Assert.Equal(0, result.ExitCode); TestHelper.AssertEqualLines( @"pwd-1 pwd-2 pwd-3 ", result.OutputText); } } }
public void LoadEnvironmentEncrypted() { // Verify that we can load an encryoted settings file into the // environment variables. using (var testManager = new KubeTestManager()) { try { using (var tempFile = new TempFile()) { // Initialze the file. using (var writer = new StreamWriter(tempFile.Path)) { foreach (var item in testSettings) { writer.WriteLine($"{item.Key}={item.Value}"); } } var passwordPath = Path.Combine(KubeHelper.PasswordsFolder, "test"); File.WriteAllText(passwordPath, password); var vault = new NeonVault(KubeHelper.LookupPassword); File.WriteAllBytes(tempFile.Path, vault.Encrypt(tempFile.Path, "test")); Assert.True(NeonVault.IsEncrypted(tempFile.Path)); // Perform the test. Assert.Null(TestContext.Current); using (var testContext = new TestContext()) { Assert.Same(testContext, TestContext.Current); testContext.LoadEnvironment(tempFile.Path, KubeHelper.LookupPassword); foreach (var item in testSettings) { Assert.Equal(item.Value, Environment.GetEnvironmentVariable(item.Key)); } } } } finally { // Be sure to remove the test enmvironment variables. foreach (var item in testSettings) { Environment.SetEnvironmentVariable(item.Key, null); } } } }
public void LoadEnvironmentDecrypted() { // Verify that we can load a decrypted settings file into the // environment variables. using (var testManager = new KubeTestManager()) { try { using (var tempFile = new TempFile()) { // Initialze the file. using (var writer = new StreamWriter(tempFile.Path)) { foreach (var item in testSettings) { writer.WriteLine($"{item.Key}={item.Value}"); } } // Perform the test. Assert.Null(TestContext.Current); using (var testContext = new TestContext()) { Assert.Same(testContext, TestContext.Current); testContext.LoadEnvironment(tempFile.Path); foreach (var item in testSettings) { Assert.Equal(item.Value, Environment.GetEnvironmentVariable(item.Key)); } } } } finally { // Be sure to remove the test enmvironment variables. foreach (var item in testSettings) { Environment.SetEnvironmentVariable(item.Key, null); } } } }
public void LoadSettingsEncrypted() { // Verify that we can load an encrypted settings file into the // [TestContext.Settings] dictionary. using (var testManager = new KubeTestManager()) { using (var tempFile = new TempFile()) { // Initialze the file. using (var writer = new StreamWriter(tempFile.Path)) { foreach (var item in testSettings) { writer.WriteLine($"{item.Key}={item.Value}"); } } var passwordPath = Path.Combine(KubeHelper.PasswordsFolder, "test"); File.WriteAllText(passwordPath, password); var vault = new NeonVault(KubeHelper.LookupPassword); File.WriteAllBytes(tempFile.Path, vault.Encrypt(tempFile.Path, "test")); Assert.True(NeonVault.IsEncrypted(tempFile.Path)); // Perform the test. Assert.Null(TestContext.Current); using (var testContext = new TestContext()) { Assert.Same(testContext, TestContext.Current); testContext.LoadSettings(tempFile.Path, KubeHelper.LookupPassword); foreach (var item in testSettings) { Assert.Equal(item.Value, testContext.Settings[item.Key]); } } } } }
public async Task VariableOptions() { var orgDirectory = Environment.CurrentDirectory; try { using (var testManager = new KubeTestManager()) { using (var runner = new ProgramRunner()) { using (var tempFolder = new TempFolder()) { Environment.CurrentDirectory = tempFolder.Path; var vault = new NeonVault(Program.LookupPassword); //------------------------------------------------- // Verify that we can process [--name=value] run command options. File.WriteAllText("test.cmd", "echo %* > output.txt"); var result = await runner.ExecuteAsync(Program.Main, "tool", "run", "--TEST_A=A-VALUE", "--TEST_B=B-VALUE", "--TEST_C=C-VALUE", "--TEST_D=D-VALUE", "--", "test.cmd", "_.TEST_A", "_.TEST_B", "_.TEST_C", "_.TEST_D"); Assert.Equal(0, result.ExitCode); var output = File.ReadAllText("output.txt"); Assert.Contains("A-VALUE", output); Assert.Contains("B-VALUE", output); Assert.Contains("C-VALUE", output); Assert.Contains("D-VALUE", output); File.Delete("output.txt"); } } } } finally { Environment.CurrentDirectory = orgDirectory; } }
public void LoadSettingsDecrypted() { // Verify that we can load a decrypted settings file into the // [TestContext.Settings] dictionary. using (var testManager = new KubeTestManager()) { using (var tempFile = new TempFile()) { // Initialze the file. using (var writer = new StreamWriter(tempFile.Path)) { foreach (var item in testSettings) { writer.WriteLine($"{item.Key}={item.Value}"); } } // Perform the test. Assert.Null(TestContext.Current); using (var testContext = new TestContext()) { Assert.Same(testContext, TestContext.Current); testContext.LoadSettings(tempFile.Path); foreach (var item in testSettings) { Assert.Equal(item.Value, testContext.Settings[item.Key]); } } } } }
public async Task StandardFiles() { // We had a problem with [NeonHelper_Execute] where standard output // and standard error streams weren't being relayed back to the // corresponding [neon-cli] streams when the sub-process was an // actual executable rather than a batch script. So the unit tests // above that ran a script passed. // // This test verifies that we get output from an actual executable. var orgDirectory = Environment.CurrentDirectory; try { using (var testManager = new KubeTestManager()) { using (var runner = new ProgramRunner()) { using (var tempFolder = new TempFolder()) { Environment.CurrentDirectory = tempFolder.Path; File.WriteAllText("test.txt", "Hello World!"); var result = await runner.ExecuteAsync(Program.Main, "tool", "run", "--", "cat", "test.txt"); Assert.Equal(0, result.ExitCode); Assert.Contains("Hello World!", result.AllText); } } } } finally { Environment.CurrentDirectory = orgDirectory; } }
public async Task ReadVariables_Decrypted() { var orgDirectory = Environment.CurrentDirectory; try { using (var testManager = new KubeTestManager()) { using (var runner = new ProgramRunner()) { using (var tempFolder = new TempFolder()) { Environment.CurrentDirectory = tempFolder.Path; var vault = new NeonVault(Program.LookupPassword); // Create a test password and a [.password-name] file in the // temp test folder. var result = await runner.ExecuteAsync(Program.Main, "tool", "password", "set", "test"); Assert.Equal(0, result.ExitCode); File.WriteAllText(".password-name", "test"); //------------------------------------------------- // Verify that we can read variables from a couple of // unencrypted variable files. File.WriteAllText("test.cmd", "echo %* > output.txt"); File.WriteAllText("var1.txt", @"# This is a comment. TEST_A=A-VALUE TEST_B=B-VALUE "); File.WriteAllText("var2.txt", @"# This is a comment. TEST_C=C-VALUE TEST_D=D-VALUE "); result = await runner.ExecuteAsync(Program.Main, "tool", "run", "var1.txt", "var2.txt", "--", "test.cmd", "_.TEST_A", "_.TEST_B", "_.TEST_C", "_.TEST_D"); Assert.Equal(0, result.ExitCode); var output = File.ReadAllText("output.txt"); Assert.Contains("A-VALUE", output); Assert.Contains("B-VALUE", output); Assert.Contains("C-VALUE", output); Assert.Contains("D-VALUE", output); File.Delete("output.txt"); File.Delete("var1.txt"); File.Delete("var2.txt"); } } } } finally { Environment.CurrentDirectory = orgDirectory; } }
public async Task PasswordRemove() { ExecuteResponse result; using (var testManager = new KubeTestManager()) { using (var runner = new ProgramRunner()) { // Verify that [help] works: result = await runner.ExecuteAsync(Program.Main, "help", "tool", "password", "remove"); Assert.Equal(0, result.ExitCode); Assert.Contains("Removes a specific named password or all passwords.", result.OutputText); // Add a few passwords: File.WriteAllText(Path.Combine(testManager.TestFolder, "pwd-1"), "one"); File.WriteAllText(Path.Combine(testManager.TestFolder, "pwd-2"), "two"); File.WriteAllText(Path.Combine(testManager.TestFolder, "pwd-3"), "three"); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "set", "pwd-1", Path.Combine(testManager.TestFolder, "pwd-1")); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "set", "pwd-2", Path.Combine(testManager.TestFolder, "pwd-2")); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "set", "pwd-3", Path.Combine(testManager.TestFolder, "pwd-3")); Assert.Equal(0, result.ExitCode); // Verify that we can list the passwords: result = await runner.ExecuteAsync(Program.Main, "tool", "password", "ls"); Assert.Equal(0, result.ExitCode); TestHelper.AssertEqualLines( @"pwd-1 pwd-2 pwd-3 ", result.OutputText); // Verify that we can remove a specific password. result = await runner.ExecuteAsync(Program.Main, "tool", "password", "rm", "--force", "pwd-2"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "ls"); Assert.Equal(0, result.ExitCode); TestHelper.AssertEqualLines( @"pwd-1 pwd-3 ", result.OutputText); // Verify that we can remove all passwords: result = await runner.ExecuteAsync(Program.Main, "tool", "password", "remove", "--force", "*"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "list"); Assert.Equal(0, result.ExitCode); Assert.Empty(result.OutputText); // Verify that we see errors for missing arguments: result = await runner.ExecuteAsync(Program.Main, "tool", "password", "rm"); Assert.NotEqual(0, result.ExitCode); Assert.Contains("NAME argument is required.", result.ErrorText); // Verify what we see an error when trying to remove a password // that doesn't exist: result = await runner.ExecuteAsync(Program.Main, "tool", "password", "rm", "BAD"); Assert.NotEqual(0, result.ExitCode); Assert.Contains("does not exist", result.ErrorText); } } }
public async Task PasswordGenerate() { ExecuteResponse result; using (var testManager = new KubeTestManager()) { using (var runner = new ProgramRunner()) { //// Verify that [help] works: result = await runner.ExecuteAsync(Program.Main, "help", "tool", "password", "generate"); Assert.Equal(0, result.ExitCode); Assert.Contains("Generates a cryptographically secure password.", result.OutputText); // Verify that we can generate a password with the default length. result = await runner.ExecuteAsync(Program.Main, "tool", "password", "generate"); Assert.Equal(0, result.ExitCode); Assert.Equal(20, result.OutputText.Trim().Length); // Verify that we can generate a password with a specific length. result = await runner.ExecuteAsync(Program.Main, "tool", "password", "generate", "30"); Assert.Equal(0, result.ExitCode); Assert.Equal(30, result.OutputText.Trim().Length); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "generate", "8"); Assert.Equal(0, result.ExitCode); Assert.Equal(8, result.OutputText.Trim().Length); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "generate", "100"); Assert.Equal(0, result.ExitCode); Assert.Equal(100, result.OutputText.Trim().Length); // Verify that invalid password lengths are detected. result = await runner.ExecuteAsync(Program.Main, "tool", "password", "generate", "BAD"); Assert.NotEqual(0, result.ExitCode); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "generate", "0"); Assert.NotEqual(0, result.ExitCode); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "generate", "7"); Assert.NotEqual(0, result.ExitCode); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "generate", "101"); Assert.NotEqual(0, result.ExitCode); // Verify that we get different passwords when we run this // multiple times. var previousPasswords = new HashSet <string>(); for (int i = 0; i < 50; i++) { result = await runner.ExecuteAsync(Program.Main, "tool", "password", "generate", "100"); Assert.Equal(0, result.ExitCode); var password = result.OutputText.Trim(); Assert.DoesNotContain(previousPasswords, p => p == password); previousPasswords.Add(password); } } } }
public async Task PasswordSet() { ExecuteResponse result; using (var testManager = new KubeTestManager()) { using (var runner = new ProgramRunner()) { // Verify that [help] works: result = await runner.ExecuteAsync(Program.Main, "help", "tool", "password", "set"); Assert.Equal(0, result.ExitCode); Assert.Contains("Creates or modifies a named password.", result.OutputText); // Add a few passwords via files and verify: File.WriteAllText(Path.Combine(testManager.TestFolder, "pwd-1"), "one"); File.WriteAllText(Path.Combine(testManager.TestFolder, "pwd-2"), "two"); File.WriteAllText(Path.Combine(testManager.TestFolder, "pwd-3"), "three"); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "set", "pwd-1", Path.Combine(testManager.TestFolder, "pwd-1")); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "set", "pwd-2", Path.Combine(testManager.TestFolder, "pwd-2")); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "set", "pwd-3", Path.Combine(testManager.TestFolder, "pwd-3")); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "get", "pwd-1"); Assert.Equal(0, result.ExitCode); Assert.Equal("one", result.OutputText.Trim()); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "get", "pwd-2"); Assert.Equal(0, result.ExitCode); Assert.Equal("two", result.OutputText.Trim()); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "get", "pwd-3"); Assert.Equal(0, result.ExitCode); Assert.Equal("three", result.OutputText.Trim()); // Verify that we can set a password from STDIN: result = await runner.ExecuteAsync(Program.Main, "tool", "password", "rm", "--force", "*"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteWithInputAsync(Program.Main, "one", "tool", "password", "set", "pwd-1", "-"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteWithInputAsync(Program.Main, "two", "tool", "password", "set", "pwd-2", "-"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteWithInputAsync(Program.Main, "three", "tool", "password", "set", "pwd-3", "-"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "get", "pwd-1"); Assert.Equal(0, result.ExitCode); Assert.Equal("one", result.OutputText.Trim()); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "get", "pwd-2"); Assert.Equal(0, result.ExitCode); Assert.Equal("two", result.OutputText.Trim()); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "get", "pwd-3"); Assert.Equal(0, result.ExitCode); Assert.Equal("three", result.OutputText.Trim()); // Verify that we can update a password. result = await runner.ExecuteAsync(Program.Main, "tool", "password", "rm", "--force", "*"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteWithInputAsync(Program.Main, "one", "tool", "password", "set", "pwd-1", "-"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "get", "pwd-1"); Assert.Equal(0, result.ExitCode); Assert.Equal("one", result.OutputText.Trim()); result = await runner.ExecuteWithInputAsync(Program.Main, "1", "tool", "password", "set", "pwd-1", "-"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "get", "pwd-1"); Assert.Equal(0, result.ExitCode); Assert.Equal("1", result.OutputText.Trim()); // Verify that password names with all possible character classes works: result = await runner.ExecuteAsync(Program.Main, "tool", "password", "rm", "--force", "*"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteWithInputAsync(Program.Main, "password", "tool", "password", "set", "a.1_2-3", "-"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "get", "a.1_2-3"); Assert.Equal(0, result.ExitCode); Assert.Equal("password", result.OutputText.Trim()); // Verify that a 20 character password is generated when no PATH argument is passed: result = await runner.ExecuteWithInputAsync(Program.Main, "password", "tool", "password", "set", "abc"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "get", "abc"); Assert.Equal(0, result.ExitCode); Assert.Equal(20, result.OutputText.Trim().Length); // Verify that we see errors for missing arguments: result = await runner.ExecuteWithInputAsync(Program.Main, "password", "tool", "password", "set"); Assert.NotEqual(0, result.ExitCode); Assert.Contains("NAME argument is required.", result.ErrorText); // Verify that password name error checking works: result = await runner.ExecuteAsync(Program.Main, "tool", "password", "rm", "--force", "*"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteWithInputAsync(Program.Main, "", "tool", "password", "set", "pwd@1", "-"); Assert.NotEqual(0, result.ExitCode); result = await runner.ExecuteWithInputAsync(Program.Main, "", "tool", "password", "set", $"{new string('a', 101)}", "-"); Assert.NotEqual(0, result.ExitCode); // Verify that password length error checking works: result = await runner.ExecuteAsync(Program.Main, "tool", "password", "rm", "--force", "*"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteWithInputAsync(Program.Main, "", "tool", "password", "set", "pwd-1", "-"); Assert.NotEqual(0, result.ExitCode); } } }
public async Task VaultPasswordName() { using (var testManager = new KubeTestManager()) { using (var tempFolder = new TempFolder()) { var orgDir = Environment.CurrentDirectory; Environment.CurrentDirectory = tempFolder.Path; NeonHelper.OpenEditorHandler = path => File.WriteAllText(path, plainText); try { using (var passwordFile = new TempFile(folder: KubeHelper.PasswordsFolder)) { File.WriteAllText(passwordFile.Path, testPassword); var vault = new NeonVault(passwordName => testPassword); using (var runner = new ProgramRunner()) { // Verify that the PATH argument is required. var result = await runner.ExecuteAsync(Program.Main, "tool", "vault", "password-name"); Assert.NotEqual(0, result.ExitCode); Assert.Contains("*** ERROR: The PATH argument is required.", result.ErrorText); // Verify that we can create an encrypted file with an explicitly // named password. result = await runner.ExecuteAsync(Program.Main, "tool", "vault", "create", "test1.txt", passwordFile.Name); Assert.Equal(0, result.ExitCode); Assert.True(NeonVault.IsEncrypted("test1.txt", out var passwordName)); Assert.Equal(passwordFile.Name, passwordName); Assert.Equal(plainText, Encoding.UTF8.GetString(vault.Decrypt("test1.txt"))); // Verify that we can get the password with a line ending. result = await runner.ExecuteAsync(Program.Main, "tool", "vault", "password-name", "test1.txt", passwordFile.Name); Assert.Equal(0, result.ExitCode); Assert.Contains(passwordFile.Name, result.OutputText); Assert.Contains('\n', result.OutputText); // Verify that we can get the password without a line ending. result = await runner.ExecuteAsync(Program.Main, "tool", "vault", "password-name", "-n", "test1.txt", passwordFile.Name); Assert.Equal(0, result.ExitCode); Assert.Equal(passwordFile.Name, result.OutputText); } } } finally { Environment.CurrentDirectory = orgDir; NeonHelper.OpenEditorHandler = null; } } } }
public async Task VaultEncrypt() { using (var testManager = new KubeTestManager()) { using (var tempFolder = new TempFolder()) { var orgDir = Environment.CurrentDirectory; Environment.CurrentDirectory = tempFolder.Path; NeonHelper.OpenEditorHandler = path => File.WriteAllText(path, plainText); try { using (var passwordFile = new TempFile(folder: KubeHelper.PasswordsFolder)) { File.WriteAllText(passwordFile.Path, testPassword); var vault = new NeonVault(passwordName => testPassword); using (var runner = new ProgramRunner()) { // Verify that the PATH argument is required. var result = await runner.ExecuteAsync(Program.Main, "tool", "vault", "encrypt"); Assert.NotEqual(0, result.ExitCode); Assert.Contains("*** ERROR: The PATH argument is required.", result.ErrorText); // Verify that the TARGET argument is required when [--password-name] // or [--p] is not present. result = await runner.ExecuteAsync(Program.Main, "tool", "vault", "decrypt", "source.txt"); Assert.NotEqual(0, result.ExitCode); Assert.Contains("*** ERROR: The TARGET argument is required.", result.ErrorText); // Verify that we can encrypt a file in-place, specifying an // explicit password name (using --password-name=NAME). File.WriteAllText("test1.txt", plainText); result = await runner.ExecuteAsync(Program.Main, "tool", "vault", "encrypt", "test1.txt", $"--password-name={passwordFile.Name}"); Assert.Equal(0, result.ExitCode); Assert.True(NeonVault.IsEncrypted("test1.txt", out var passwordName)); Assert.Equal(passwordFile.Name, passwordName); Assert.Equal(plainText, Encoding.UTF8.GetString(vault.Decrypt("test1.txt"))); // Verify that we can encrypt a file in-place, specifying an // explicit password name (using --p=NAME). File.WriteAllText("test2.txt", plainText); result = await runner.ExecuteAsync(Program.Main, "tool", "vault", "encrypt", "test2.txt", $"-p={passwordFile.Name}"); Assert.Equal(0, result.ExitCode); Assert.True(NeonVault.IsEncrypted("test2.txt", out passwordName)); Assert.Equal(passwordFile.Name, passwordName); Assert.Equal(plainText, Encoding.UTF8.GetString(vault.Decrypt("test2.txt"))); // Verify that we get an error trying to encrypt in-place without a // password name being explicitly specified and also without a // [.password-name] file present. File.WriteAllText("test3.txt", plainText); result = await runner.ExecuteAsync(Program.Main, "tool", "vault", "encrypt", "test3.txt"); Assert.NotEqual(0, result.ExitCode); Assert.Contains("*** ERROR: A PASSWORD-NAME argument or [.password-name] file is required.", result.ErrorText); // Verify that we get an error trying to encrypt (not in-place) without a // password name being explicitly specified and also without a // [.password-name] file present. File.WriteAllText("test4.txt", plainText); result = await runner.ExecuteAsync(Program.Main, "tool", "vault", "encrypt", "test4.txt", "test4.encypted.txt"); Assert.NotEqual(0, result.ExitCode); Assert.Contains("*** ERROR: A PASSWORD-NAME argument or [.password-name] file is required.", result.ErrorText); // Verify that we can encrypt a file to another with // and explicit password argument. File.WriteAllText("test5.txt", plainText); result = await runner.ExecuteAsync(Program.Main, "tool", "vault", "encrypt", "test5.txt", "test5.encypted.txt", passwordName); Assert.Equal(0, result.ExitCode); Assert.True(NeonVault.IsEncrypted("test5.encypted.txt", out passwordName)); Assert.Equal(passwordFile.Name, passwordName); Assert.Equal(plainText, Encoding.UTF8.GetString(vault.Decrypt("test5.encypted.txt"))); // Verify that we can encrypt a file to another with // and explicit [--password-name] option. File.WriteAllText("test6.txt", plainText); result = await runner.ExecuteAsync(Program.Main, "tool", "vault", "encrypt", "test6.txt", "test6.encypted.txt", $"--password-name={passwordName}"); Assert.Equal(0, result.ExitCode); Assert.True(NeonVault.IsEncrypted("test6.encypted.txt", out passwordName)); Assert.Equal(passwordFile.Name, passwordName); Assert.Equal(plainText, Encoding.UTF8.GetString(vault.Decrypt("test6.encypted.txt"))); // Verify that we can encrypt a file in-place using a [.password-name] file. File.WriteAllText("test7.txt", plainText); File.WriteAllText(".password-name", passwordName); result = await runner.ExecuteAsync(Program.Main, "tool", "vault", "encrypt", "test7.txt"); Assert.Equal(0, result.ExitCode); Assert.True(NeonVault.IsEncrypted("test7.txt", out passwordName)); Assert.Equal(passwordFile.Name, passwordName); Assert.Equal(plainText, Encoding.UTF8.GetString(vault.Decrypt("test7.txt"))); // Verify that we can encrypt a file (not in-place) to another where // the source file is located in a different directory from the target // to ensure that we look for the [.password-name] file starting at // the target directory. using (var tempFile = new TempFile()) { File.WriteAllText(tempFile.Path, plainText); result = await runner.ExecuteAsync(Program.Main, "tool", "vault", "encrypt", tempFile.Path, "test8.encrypted.txt"); Assert.Equal(0, result.ExitCode); Assert.True(NeonVault.IsEncrypted("test8.encrypted.txt", out passwordName)); Assert.Equal(passwordFile.Name, passwordName); Assert.Equal(plainText, Encoding.UTF8.GetString(vault.Decrypt("test8.encrypted.txt"))); } } } } finally { Environment.CurrentDirectory = orgDir; NeonHelper.OpenEditorHandler = null; } } } }
public async Task PasswordImportExport() { const string zipPassword = "******"; ExecuteResponse result; using (var testManager = new KubeTestManager()) { using (var runner = new ProgramRunner()) { // Verify that [help] works: result = await runner.ExecuteAsync(Program.Main, "help", "tool", "password", "import"); Assert.Equal(0, result.ExitCode); Assert.Contains("Imports passwords from an encrypted ZIP file.", result.OutputText); // Verify that [import] checks the PATH argument. result = await runner.ExecuteAsync(Program.Main, "tool", "password", "import"); Assert.NotEqual(0, result.ExitCode); Assert.Contains("PATH argument is required.", result.ErrorText); // Verify that [help] works: result = await runner.ExecuteAsync(Program.Main, "help", "tool", "password", "export"); Assert.Equal(0, result.ExitCode); Assert.Contains("Exports selected passwords to an encrypted ZIP file.", result.OutputText); // Verify that [export] checks the PATH argument. result = await runner.ExecuteAsync(Program.Main, "tool", "password", "export"); Assert.NotEqual(0, result.ExitCode); Assert.Contains("PATH argument is required.", result.ErrorText); // Verify that [export] checks the NAME argument. result = await runner.ExecuteAsync(Program.Main, "tool", "password", "export", "test.zip"); Assert.NotEqual(0, result.ExitCode); Assert.Contains("At least one NAME argument is required.", result.ErrorText); // Add a few passwords: result = await runner.ExecuteAsync(Program.Main, "tool", "password", "rm", "--force", "*"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteWithInputAsync(Program.Main, "one", "tool", "password", "set", "pwd-1", "-"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteWithInputAsync(Program.Main, "two", "tool", "password", "set", "pwd-2", "-"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteWithInputAsync(Program.Main, "three", "tool", "password", "set", "pwd-3", "-"); Assert.Equal(0, result.ExitCode); // Export all passwords to a ZIP file: var zipPath = Path.Combine(testManager.TestFolder, "passwords.zip"); result = await runner.ExecuteWithInputAsync(Program.Main, zipPassword, "tool", "password", "export", "--stdin", zipPath, "*"); Assert.Equal(0, result.ExitCode); Assert.True(File.Exists(zipPath)); // Remove all passwords, import the passwords using a zip password file, and verify. result = await runner.ExecuteAsync(Program.Main, "tool", "password", "rm", "--force", "*"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteWithInputAsync(Program.Main, zipPassword, "tool", "password", "import", "--stdin", zipPath); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "get", "pwd-1"); Assert.Equal(0, result.ExitCode); Assert.Equal("one", result.OutputText.Trim()); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "get", "pwd-2"); Assert.Equal(0, result.ExitCode); Assert.Equal("two", result.OutputText.Trim()); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "get", "pwd-3"); Assert.Equal(0, result.ExitCode); Assert.Equal("three", result.OutputText.Trim()); // Export two of the three passwords to a ZIP file: result = await runner.ExecuteWithInputAsync(Program.Main, zipPassword, "tool", "password", "export", "--stdin", zipPath, "pwd-1", "pwd-2"); Assert.Equal(0, result.ExitCode); Assert.True(File.Exists(zipPath)); // Remove all passwords, import the passwords using a zip password file, and verify. result = await runner.ExecuteAsync(Program.Main, "tool", "password", "rm", "--force", "*"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteWithInputAsync(Program.Main, zipPassword, "tool", "password", "import", "--stdin", zipPath); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "get", "pwd-1"); Assert.Equal(0, result.ExitCode); Assert.Equal("one", result.OutputText.Trim()); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "get", "pwd-2"); Assert.Equal(0, result.ExitCode); Assert.Equal("two", result.OutputText.Trim()); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "get", "pwd-3"); Assert.NotEqual(0, result.ExitCode); // This one wasn't exported. } } }
public async Task VaultCreate() { using (var testManager = new KubeTestManager()) { using (var tempFolder = new TempFolder()) { var orgDir = Environment.CurrentDirectory; Environment.CurrentDirectory = tempFolder.Path; NeonHelper.OpenEditorHandler = path => File.WriteAllText(path, plainText); try { using (var passwordFile = new TempFile(folder: KubeHelper.PasswordsFolder)) { File.WriteAllText(passwordFile.Path, testPassword); var vault = new NeonVault(passwordName => testPassword); using (var runner = new ProgramRunner()) { // Verify that the PATH argument is required. var result = await runner.ExecuteAsync(Program.Main, "tool", "vault", "create"); Assert.NotEqual(0, result.ExitCode); Assert.Contains("*** ERROR: The PATH argument is required.", result.ErrorText); // Verify that the PASSWORD-NAME argument is required when there's // no default [.password-name] file. result = await runner.ExecuteAsync(Program.Main, "tool", "vault", "create", "test1.txt"); Assert.NotEqual(0, result.ExitCode); Assert.Contains("*** ERROR: A PASSWORD-NAME argument or [.password-name] file is required.", result.ErrorText); // Verify that we can create an encrypted file with an explicitly // named password. result = await runner.ExecuteAsync(Program.Main, "tool", "vault", "create", "test2.txt", passwordFile.Name); Assert.Equal(0, result.ExitCode); Assert.True(NeonVault.IsEncrypted("test2.txt", out var passwordName)); Assert.Equal(passwordFile.Name, passwordName); Assert.Equal(plainText, Encoding.UTF8.GetString(vault.Decrypt("test2.txt"))); // Verify that we see an error for a missing password. result = await runner.ExecuteAsync(Program.Main, "tool", "vault", "create", "test3.txt", missingPasswordName); Assert.NotEqual(0, result.ExitCode); Assert.Contains($"*** ERROR: [System.Security.Cryptography.CryptographicException]: Password named [{missingPasswordName}] not found or is blank or whitespace.", result.ErrorText); // Verify that we see an error for an invalid password. result = await runner.ExecuteAsync(Program.Main, "tool", "vault", "create", "test4.txt", badPasswordName); Assert.NotEqual(0, result.ExitCode); Assert.Contains($"*** ERROR: [System.Security.Cryptography.CryptographicException]: Password name [bad/password] contains invalid characters. Only ASCII letters, digits, underscores, dashs and dots are allowed.", result.ErrorText); // Verify that a local [.password-name] file is used successfully when we don't // explicitly pass a password name. File.WriteAllText(".password-name", passwordFile.Name); result = await runner.ExecuteAsync(Program.Main, "tool", "vault", "create", "test5.txt"); Assert.Equal(0, result.ExitCode); Assert.True(NeonVault.IsEncrypted("test5.txt", out passwordName)); Assert.Equal(passwordFile.Name, passwordName); Assert.Equal(plainText, Encoding.UTF8.GetString(vault.Decrypt("test5.txt"))); // Verify that a [.password-name] file in the parent directory is used successfully // when we don't explicitly pass a password name. Directory.CreateDirectory("subfolder"); Environment.CurrentDirectory = Path.Combine(Environment.CurrentDirectory, "subfolder"); result = await runner.ExecuteAsync(Program.Main, "tool", "vault", "create", "test6.txt"); Assert.Equal(0, result.ExitCode); Assert.True(NeonVault.IsEncrypted("test6.txt", out passwordName)); Assert.Equal(passwordFile.Name, passwordName); Assert.Equal(plainText, Encoding.UTF8.GetString(vault.Decrypt("test6.txt"))); } } } finally { Environment.CurrentDirectory = orgDir; NeonHelper.OpenEditorHandler = null; } } } }
public async Task DecryptFile() { var orgDirectory = Environment.CurrentDirectory; try { using (var testManager = new KubeTestManager()) { using (var runner = new ProgramRunner()) { using (var tempFolder = new TempFolder()) { Environment.CurrentDirectory = tempFolder.Path; var vault = new NeonVault(Program.LookupPassword); // Create a test password and a [.password-name] file in the // temp test folder. var result = await runner.ExecuteAsync(Program.Main, "tool", "password", "set", "test"); Assert.Equal(0, result.ExitCode); //------------------------------------------------- // Verify that we can decrypt a file. File.WriteAllText("test.cmd", "type %1 > output.txt"); const string plainText = "The quick brown fox jumped over the lazy dog."; File.WriteAllText("file.txt", plainText); File.WriteAllBytes("file.txt", vault.Encrypt("file.txt", "test")); Assert.True(NeonVault.IsEncrypted("file.txt")); result = await runner.ExecuteAsync(Program.Main, "tool", "run", "--", "test.cmd", "_...file.txt"); Assert.Equal(0, result.ExitCode); var output = File.ReadAllText("output.txt"); Assert.Contains(plainText, output); File.Delete("output.txt"); File.Delete("file.txt"); //------------------------------------------------- // Try this again calling a command directly (batch files seem to have different behavior). File.WriteAllText("type", "%1"); File.WriteAllText("file.txt", plainText); File.WriteAllBytes("file.txt", vault.Encrypt("file.txt", "test")); Assert.True(NeonVault.IsEncrypted("file.txt")); result = await runner.ExecuteAsync(Program.Main, "tool", "run", "--", "cat", "_...file.txt"); Assert.Equal(0, result.ExitCode); Assert.Contains(plainText, result.OutputText); File.Delete("output.txt"); File.Delete("file.txt"); } } } } finally { Environment.CurrentDirectory = orgDirectory; } }
public async Task PasswordBasics() { ExecuteResponse result; // Verify basic password operations: get, set, list|ls, and remove|rm: using (var testManager = new KubeTestManager()) { using (var runner = new ProgramRunner()) { // We should start out with no passwords: result = await runner.ExecuteAsync(Program.Main, "tool", "password", "list"); Assert.Equal(0, result.ExitCode); Assert.Empty(result.OutputText.Trim()); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "ls"); Assert.Equal(0, result.ExitCode); Assert.Empty(result.OutputText.Trim()); // Add a few passwords via files and verify: File.WriteAllText(Path.Combine(testManager.TestFolder, "pwd-1"), "one"); File.WriteAllText(Path.Combine(testManager.TestFolder, "pwd-2"), "two"); File.WriteAllText(Path.Combine(testManager.TestFolder, "pwd-3"), "three"); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "set", "pwd-1", Path.Combine(testManager.TestFolder, "pwd-1")); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "set", "pwd-2", Path.Combine(testManager.TestFolder, "pwd-2")); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "set", "pwd-3", Path.Combine(testManager.TestFolder, "pwd-3")); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "get", "pwd-1"); Assert.Equal(0, result.ExitCode); Assert.Equal("one", result.OutputText.Trim()); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "get", "pwd-2"); Assert.Equal(0, result.ExitCode); Assert.Equal("two", result.OutputText.Trim()); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "get", "pwd-3"); Assert.Equal(0, result.ExitCode); Assert.Equal("three", result.OutputText.Trim()); // Verify that we can list the passwords: result = await runner.ExecuteAsync(Program.Main, "tool", "password", "ls"); Assert.Equal(0, result.ExitCode); TestHelper.AssertEqualLines( @"pwd-1 pwd-2 pwd-3 ", result.OutputText); // Verify that we can remove a specific password. result = await runner.ExecuteAsync(Program.Main, "tool", "password", "rm", "--force", "pwd-2"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "ls"); Assert.Equal(0, result.ExitCode); TestHelper.AssertEqualLines( @"pwd-1 pwd-3 ", result.OutputText); // Verify that we can remove all passwords: result = await runner.ExecuteAsync(Program.Main, "tool", "password", "rm", "--force", "*"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteAsync(Program.Main, "tool", "password", "ls"); Assert.Equal(0, result.ExitCode); Assert.Empty(result.OutputText); } } }
public void VaultDecrypt() { using (var manager = new KubeTestManager()) { using (var tempFolder = new TempFolder()) { var orgDir = Environment.CurrentDirectory; Environment.CurrentDirectory = tempFolder.Path; NeonHelper.OpenEditorHandler = path => File.WriteAllText(path, plainText); try { using (var passwordFile = new TempFile(folder: KubeHelper.PasswordsFolder)) { File.WriteAllText(passwordFile.Path, testPassword); var vault = new NeonVault(passwordName => testPassword); using (var runner = new ProgramRunner()) { // Verify that the SOURCE argument is required. var result = runner.Execute(Program.Main, "vault", "decrypt"); Assert.NotEqual(0, result.ExitCode); Assert.Contains("*** ERROR: The SOURCE argument is required.", result.ErrorText); // Verify that the TARGET argument is required. result = runner.Execute(Program.Main, "vault", "decrypt"); Assert.NotEqual(0, result.ExitCode); Assert.Contains("*** ERROR: The SOURCE argument is required.", result.ErrorText); // Verify that the SOURCE-PATH argument is required. result = runner.Execute(Program.Main, "vault", "decrypt", "test.txt"); Assert.NotEqual(0, result.ExitCode); Assert.Contains("*** ERROR: The TARGET argument is required.", result.ErrorText); // Verify that we can create an encrypted file with an explicitly // named password. result = runner.Execute(Program.Main, "vault", "create", "test1.txt", passwordFile.Name); Assert.Equal(0, result.ExitCode); Assert.True(NeonVault.IsEncrypted("test1.txt", out var passwordName)); Assert.Equal(passwordFile.Name, passwordName); Assert.Equal(plainText, Encoding.UTF8.GetString(vault.Decrypt("test1.txt"))); // Verify that we can decrypt the file. result = runner.Execute(Program.Main, "vault", "decrypt", "test1.txt", "decrypted.txt"); Assert.Equal(0, result.ExitCode); Assert.True(NeonVault.IsEncrypted("test1.txt", out passwordName)); Assert.True(!NeonVault.IsEncrypted("decrypted.txt", out passwordName)); Assert.Equal(plainText, File.ReadAllText("decrypted.txt")); } } } finally { Environment.CurrentDirectory = orgDir; NeonHelper.OpenEditorHandler = null; } } } }