public async Task Password() { ExecuteResponse result; using (new KubeTestManager()) { using (var runner = new ProgramRunner()) { // Verify that [neon password] returns help/usage text: result = await runner.ExecuteAsync(Program.Main, "tool", "password"); Assert.Equal(0, result.ExitCode); Assert.Contains("Manages neonKUBE passwords.", result.OutputText); result = await runner.ExecuteAsync(Program.Main, "help", "tool", "password"); Assert.Equal(0, result.ExitCode); Assert.Contains("Manages neonKUBE passwords.", result.OutputText); // Verify that an invalid command fails. result = await runner.ExecuteAsync(Program.Main, "tool", "password", "bad"); Assert.NotEqual(0, result.ExitCode); Assert.Contains("Unexpected [bad] command.", result.ErrorText); } } }
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 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 static Task <int> Main(string[] args2) { RunnerArgs args = RunnerArgs.FromCommandLine(args2); ProgramRunner runner = new ProgramRunner(args); try { await runner.ExecuteAsync(); } catch (ToolException ex) { if (!string.IsNullOrWhiteSpace(ex.StdOut)) { WriteLine(ex.StdOut, ConsoleColor.Red); } if (!string.IsNullOrWhiteSpace(ex.StdErr)) { WriteLine(ex.StdErr, ConsoleColor.Red); } return(-1); } catch (Exception ex) { WriteLine(ex.Message, ConsoleColor.Red); return(-1); } return(0); }
public async Task Vault() { using (var runner = new ProgramRunner()) { var result = await runner.ExecuteAsync(Program.Main, "tool", "vault"); Assert.Equal(0, result.ExitCode); } }
public async Task Base() { using (var runner = new ProgramRunner()) { // Verify that base command returns some help. var result = await runner.ExecuteAsync(Program.Main, "tool"); Assert.Equal(0, result.ExitCode); Assert.Contains("USAGE:", result.OutputText); // Verify that we see an error for an unrecognized command., result = await runner.ExecuteAsync(Program.Main, "tool", "invalid-command"); Assert.NotEqual(0, result.ExitCode); } }
public async Task Run() { using (var runner = new ProgramRunner()) { // Verify that the help command works. var result = await runner.ExecuteAsync(Program.Main, "tool", "run", "--help"); Assert.Equal(0, result.ExitCode); Assert.Contains("Runs a sub-command, optionally injecting settings and secrets and/or", result.OutputText); // Verify ther error we get when there's no right command line. result = await runner.ExecuteAsync(Program.Main, "tool", "run"); Assert.NotEqual(0, result.ExitCode); Assert.Contains("*** ERROR: Expected a command after a [--] argument.", result.ErrorText); } }
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 async Task Version() { using (var runner = new ProgramRunner()) { var result = await runner.ExecuteAsync(Program.Main, "tool", "version"); Assert.Equal(0, result.ExitCode); Assert.Equal(KubeVersions.Kubernetes, result.OutputText.Trim()); result = await runner.ExecuteAsync(Program.Main, "tool", "version", "-n"); Assert.Equal(0, result.ExitCode); Assert.Equal(KubeVersions.Kubernetes, result.OutputText.Trim()); Assert.DoesNotContain('\n', result.OutputText); result = await runner.ExecuteAsync(Program.Main, "tool", "version", "-n", "--git"); Assert.Equal(0, result.ExitCode); Assert.Equal($"{KubeVersions.Kubernetes}/{ThisAssembly.Git.Branch}-{ThisAssembly.Git.Commit}", result.OutputText.Trim()); Assert.DoesNotContain('\n', result.OutputText); result = await runner.ExecuteAsync(Program.Main, "tool", "version", $"--minimum={Program.Version}"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteAsync(Program.Main, "tool", "version", $"--minimum=0"); Assert.Equal(0, result.ExitCode); result = await runner.ExecuteAsync(Program.Main, "tool", "version", $"--minimum=64000.0.0"); Assert.NotEqual(0, result.ExitCode); var curVersion = SemanticVersion.Parse(Program.Version); var newerVersion = SemanticVersion.Create(curVersion.Major, curVersion.Minor, curVersion.Patch + 1, curVersion.Build, curVersion.Prerelease); Assert.True(newerVersion > curVersion); result = await runner.ExecuteAsync(Program.Main, "tool", "version", $"--minimum={newerVersion}"); Assert.NotEqual(0, result.ExitCode); } }
public async Task NoServices() { using (var runner = new ProgramRunner()) { // Verify that all types are generated when no targets // are specified. var result = await runner.ExecuteAsync(Program.Main, $"--source-namespace={typeof(Test_ModelGeneration).Namespace}", "--no-services", thisAssemblyPath); Assert.Equal(0, result.ExitCode); var sourceCode = result.OutputText; CSharpHelper.Compile(sourceCode, "test-assembly", references => ModelGenTestHelper.ReferenceHandler(references)); Assert.Contains("class Class1", sourceCode); Assert.Contains("class Class2", sourceCode); Assert.Contains("class Class3", sourceCode); Assert.DoesNotContain("class Service1", sourceCode); Assert.DoesNotContain("class Service2", sourceCode); } }
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 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 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 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 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 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 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 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 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; } } } }