// Constructor. public CommandSettings(IHostContext context, string[] args) { ArgUtil.NotNull(context, nameof(context)); _context = context; _promptManager = context.GetService <IPromptManager>(); _secretMasker = context.GetService <ISecretMasker>(); _trace = context.GetTrace(nameof(CommandSettings)); // Parse the command line args. _parser = new CommandLineParser( hostContext: context, secretArgNames: Constants.Agent.CommandLine.Args.Secrets); _parser.Parse(args); // Store and remove any args passed via environment variables. IDictionary environment = Environment.GetEnvironmentVariables(); string envPrefix = "VSTS_AGENT_INPUT_"; foreach (DictionaryEntry entry in environment) { // Test if starts with VSTS_AGENT_INPUT_. string fullKey = entry.Key as string ?? string.Empty; if (fullKey.StartsWith(envPrefix, StringComparison.OrdinalIgnoreCase)) { string val = (entry.Value as string ?? string.Empty).Trim(); if (!string.IsNullOrEmpty(val)) { // Extract the name. string name = fullKey.Substring(envPrefix.Length); // Mask secrets. bool secret = Constants.Agent.CommandLine.Args.Secrets.Any(x => string.Equals(x, name, StringComparison.OrdinalIgnoreCase)); if (secret) { _secretMasker.AddValue(val); } // Store the value. _envArgs[name] = val; } // Remove from the environment block. _trace.Info($"Removing env var: '{fullKey}'"); Environment.SetEnvironmentVariable(fullKey, null); } } }
// TODO: Consider using SecureString. public string ReadSecret() { Trace.Info("READ SECRET"); var chars = new List <char>(); while (true) { ConsoleKeyInfo key = Console.ReadKey(intercept: true); if (key.Key == ConsoleKey.Enter) { Console.WriteLine(); break; } else if (key.Key == ConsoleKey.Backspace) { if (chars.Count > 0) { chars.RemoveAt(chars.Count - 1); Console.Write("\b \b"); } } else if (key.KeyChar > 0) { chars.Add(key.KeyChar); Console.Write("*"); } } // Trace whether a value was entered. string val = new String(chars.ToArray()); if (!string.IsNullOrEmpty(val)) { _secretMasker.AddValue(val); } Trace.Info($"Read value: '{val}'"); return(val); }
public void Parse(string[] args) { _trace.Info(nameof(Parse)); ArgUtil.NotNull(args, nameof(args)); _trace.Info("Parsing {0} args", args.Length); string argScope = null; foreach (string arg in args) { _trace.Info("parsing argument"); HasArgs = HasArgs || arg.StartsWith("--"); _trace.Info("HasArgs: {0}", HasArgs); if (string.Equals(arg, "/?", StringComparison.Ordinal)) { Flags.Add("help"); } else if (!HasArgs) { _trace.Info("Adding Command: {0}", arg); Commands.Add(arg.Trim()); } else { // it's either an arg, an arg value or a flag if (arg.StartsWith("--") && arg.Length > 2) { string argVal = arg.Substring(2); _trace.Info("arg: {0}", argVal); // this means two --args in a row which means previous was a flag if (argScope != null) { _trace.Info("Adding flag: {0}", argScope); Flags.Add(argScope.Trim()); } argScope = argVal; } else if (!arg.StartsWith("-")) { // we found a value - check if we're in scope of an arg if (argScope != null && !Args.ContainsKey(argScope = argScope.Trim())) { if (SecretArgNames.Contains(argScope)) { _secretMasker.AddValue(arg); } _trace.Info("Adding option '{0}': '{1}'", argScope, arg); // ignore duplicates - first wins - below will be val1 // --arg1 val1 --arg1 val1 Args.Add(argScope, arg); argScope = null; } } else { // // ignoring the second value for an arg (val2 below) // --arg val1 val2 // ignoring invalid things like empty - and -- // --arg val1 -- --flag _trace.Info("Ignoring arg"); } } } _trace.Verbose("done parsing arguments"); // handle last arg being a flag if (argScope != null) { Flags.Add(argScope); } _trace.Verbose("Exiting parse"); }