diff --git a/src/Agent.Listener/Configuration/FeatureFlagProvider.cs b/src/Agent.Listener/Configuration/FeatureFlagProvider.cs index cdf9d6a8ed..67f85ffcc6 100644 --- a/src/Agent.Listener/Configuration/FeatureFlagProvider.cs +++ b/src/Agent.Listener/Configuration/FeatureFlagProvider.cs @@ -49,7 +49,7 @@ public async Task GetFeatureFlagAsync(IHostContext context, string var client = vssConnection.GetClient(); try { - return await client.GetFeatureFlagByNameAsync(featureFlagName); + return await client.GetFeatureFlagByNameAsync(featureFlagName, checkFeatureExists: false); } catch(VssServiceException e) { Trace.Warning("Unable to retrive feature flag status: " + e.ToString()); diff --git a/src/Agent.Listener/JobDispatcher.cs b/src/Agent.Listener/JobDispatcher.cs index aa5834110b..c7a2f7813f 100644 --- a/src/Agent.Listener/JobDispatcher.cs +++ b/src/Agent.Listener/JobDispatcher.cs @@ -17,7 +17,7 @@ using System.Linq; using Microsoft.VisualStudio.Services.Common; using System.Diagnostics; - +using Agent.Listener.Configuration; namespace Microsoft.VisualStudio.Services.Agent.Listener { @@ -88,6 +88,18 @@ public void Run(Pipelines.AgentJobRequestMessage jobRequestMessage, bool runOnce } } + var service = HostContext.GetService(); + string ffState; + try + { + ffState = service.GetFeatureFlagAsync(HostContext, "DistributedTask.Agent.EnableAdditionalMaskingRegexes", Trace)?.Result?.EffectiveState; + } + catch (Exception) + { + ffState = "Off"; + } + jobRequestMessage.Variables[Constants.Variables.Features.EnableAdditionalMaskingRegexes] = ffState; + WorkerDispatcher newDispatch = new WorkerDispatcher(jobRequestMessage.JobId, jobRequestMessage.RequestId); if (runOnce) { diff --git a/src/Agent.Sdk/Knob/AgentKnobs.cs b/src/Agent.Sdk/Knob/AgentKnobs.cs index 224370922b..c61b8997e0 100644 --- a/src/Agent.Sdk/Knob/AgentKnobs.cs +++ b/src/Agent.Sdk/Knob/AgentKnobs.cs @@ -284,12 +284,6 @@ public class AgentKnobs new EnvironmentKnobSource("SYSTEM_UNSAFEALLOWMULTILINESECRET"), new BuiltInDefaultKnobSource("false")); - public static readonly Knob MaskUsingCredScanRegexes = new Knob( - nameof(MaskUsingCredScanRegexes), - "Use the CredScan regexes for masking secrets. CredScan is an internal tool developed at Microsoft to keep passwords and authentication keys from being checked in. This defaults to disabled, as there are performance problems with some task outputs.", - new EnvironmentKnobSource("AZP_USE_CREDSCAN_REGEXES"), - new BuiltInDefaultKnobSource("false")); - public static readonly Knob MaskedSecretMinLength = new Knob( nameof(MaskedSecretMinLength), "Specify the length of the secrets, which, if shorter, will be ignored in the logs.", diff --git a/src/Agent.Worker/Worker.cs b/src/Agent.Worker/Worker.cs index 9f7172709e..e4de9d4e0a 100644 --- a/src/Agent.Worker/Worker.cs +++ b/src/Agent.Worker/Worker.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using Microsoft.VisualStudio.Services.WebApi; using Agent.Sdk.Util; +using Agent.Sdk.Knob; namespace Microsoft.VisualStudio.Services.Agent.Worker { @@ -67,6 +68,19 @@ public async Task RunAsync(string pipeIn, string pipeOut) InitializeSecretMasker(jobMessage); SetCulture(jobMessage); + var maskUsingCredScanRegexesState = "Off"; + + if(jobMessage.Variables.TryGetValue(Constants.Variables.Agent.EnableAdditionalMaskingRegexes, out var enableAdditionalMaskingRegexes)) + { + maskUsingCredScanRegexesState = enableAdditionalMaskingRegexes.Value; + } + + if(maskUsingCredScanRegexesState == "On") + { + Trace.Verbose($"{Constants.Variables.Agent.EnableAdditionalMaskingRegexes} is On, adding additional masking regexes"); + HostContext.AddAdditionalMaskingRegexes(); + } + // Start the job. Trace.Info($"Job message:{Environment.NewLine} {StringUtil.ConvertToJson(WorkerUtilities.ScrubPiiData(jobMessage))}"); Task jobRunnerTask = jobRunner.RunAsync(jobMessage, jobRequestCancellationToken.Token); diff --git a/src/Microsoft.VisualStudio.Services.Agent/AdditionalMaskingRegexes.CredScan.cs b/src/Microsoft.VisualStudio.Services.Agent/AdditionalMaskingRegexes.CredScan.cs index a2af9a961f..e786fa36a6 100644 --- a/src/Microsoft.VisualStudio.Services.Agent/AdditionalMaskingRegexes.CredScan.cs +++ b/src/Microsoft.VisualStudio.Services.Agent/AdditionalMaskingRegexes.CredScan.cs @@ -30,176 +30,50 @@ public static partial class AdditionalMaskingRegexes private static IEnumerable credScanPatterns = new List() { - // AnsibleVaultData - @"" // pre-match - + @"\$ANSIBLE_VAULT;\d+\.\d+;AES256\s+\d+" // match + // AAD client app, most recent two versions. + @"\b" // pre-match + + @"[0-9A-Za-z-_~.]{3}7Q~[0-9A-Za-z-_~.]{31}\b|\b[0-9A-Za-z-_~.]{3}8Q~[0-9A-Za-z-_~.]{34}" // match + + @"\b", // post-match + + // Prominent Azure provider 512-bit symmetric keys. + @"\b" // pre-match + + @"[0-9A-Za-z+/]{76}(APIM|ACDb|\+(ABa|AMC|ASt))[0-9A-Za-z+/]{5}[AQgw]==" // match + @"", // post-match - - // AzurePowerShellTokenCache - @"" // pre-match - + @"[""']TokenCache[""']\s*:\s*\{\s*[""']CacheData[""']\s*:\s*[""'][a-z0-9/\+]{86}" // match - + @"", // post-match - - // Base64EncodedStringLiteral - @"(?<=(^|[""'>;=\s#]))" // pre-match - + @"(?(?-i)MI(?i)[a-z0-9/+\s\u0085\u200b""',\\]{200,20000}[a-z0-9/+]={0,2})" // match + // + // Prominent Azure provider 256-bit symmetric keys. + @"\b" // pre-match + + @"[0-9A-Za-z+/]{33}(AIoT|\+(ASb|AEh|ARm))[A-P][0-9A-Za-z+/]{5}=" // match + @"", // post-match - - // JsonWebToken - @"" // pre-match - + @"(?-i)(?eyJ(?i)[a-z0-9\-_%]+\.(?-i)eyJ(?i)[a-z0-9\-_%]+\.[a-z0-9\-_%]+)|([rR]efresh_?[tT]oken|REFRESH_?TOKEN)[""']?\s*[:=]{1,2}\s*[""']?(?(\w+-)+\w+)[""']?" // match - + @"", // post-match - - // SlackTokens - @"" // pre-match - + @"xox[pbar]\-[a-z0-9\-]+" // match - + @"", // post-match - - // SymmetricKey128 - @"(?<=[^\w/\+\._\$,\\])" // pre-match - + @"(?[a-z0-9/\+]{22}==)" // match - + @"(?=([^\w/\+\.\$]|$))", // post-match - - // SymmetricKey128Hex - @"(?<=[^\w/\+\._\$,\\][dapi]+)" // pre-match - + @"(?[a-f0-9]{32})" // match - + @"(?=([^\w/\+\.\$]|$))", // post-match - - // SymmetricKey160Hex - @"(?<=[^\w/\+\._\$,\\])" // pre-match - + @"(?[a-f0-9/\+]{40})" // match - + @"(?=([^\w/\+\.\$]|$))", // post-match - - // SymmetricKey232 - @"(?<=[^\w/\+\._\$,\\])" // pre-match - + @"(?(?-i)AIza(?i)[a-z0-9_\\\-]{35})" // match - + @"(?=([^\w/\+\.\$]|$))", // post-match - - // SymmetricKey240 - @"(?<=[^\w/\+\.\-\$,\\])" // pre-match - + @"(?[a-z0-9/\+]{40})" // match - + @"(?=([^\w/\+\.\-\$,\\]|$))", // post-match - - // SymmetricKey256 - @"(?<=[^\w/\+\.\$,\\])" // pre-match - + @"(?[a-z0-9/\+]{43}=)" // match - + @"(?=([^\w/\+\.\$]|$))", // post-match - - // SymmetricKey256B32 - @"(?<=[^\w/\+\._\-\$,\\])" // pre-match - + @"(?(?-i)[a-z2-7]{52}(?i))" // match - + @"(?=(?<=[0-9]+[a-z]+[0-9]+.{0,49})([^\w/\+\.\-\$,]|$))", // post-match - - // SymmetricKey256UrlEncoded - @"(?<=[^\w/\+\._\-\$,\\%])" // pre-match - + @"(?[a-z0-9%]{43,63}%3d)" // match + + // Azure Function key. + @"\b" // pre-match + + @"[0-9A-Za-z_\-]{44}AzFu[0-9A-Za-z\-_]{5}[AQgw]==" // match + @"", // post-match - // SymmetricKey320 - @"(?<=[^\w/\+\.\-\$,\\])" // pre-match - + @"(?[a-z0-9/\+]{54}={2})" // match - + @"(?=([^\w/\+\.\-\$,\\]|$))", // post-match - - // SymmetricKey320UrlEncoded - @"(?<=[^\w/\+\.\-\$,\\%])" // pre-match - + @"(?[a-z0-9%]{54,74}(%3d){2})" // match + // Azure Search keys. + @"\b" // pre-match + + @"[0-9A-Za-z]{42}AzSe[A-D][0-9A-Za-z]{5}" // match + + @"\b", // post-match + + // Azure Container Registry keys. + @"\b" // pre-match + + @"[0-9A-Za-z+/]{42}\+ACR[A-D][0-9A-Za-z+/]{5}" // match + + @"\b", // post-match + + // Azure Cache for Redis keys. + @"\b" // pre-match + + @"[0-9A-Za-z]{33}AzCa[A-P][0-9A-Za-z]{5}=" // match + @"", // post-match - - // SymmetricKey360 - @"(?<=[^\w/\+\.\-\$,\\])" // pre-match - + @"(?[a-z0-9/\+]{60})" // match - + @"(?=[^\w/\+\.\-\$,\\])", // post-match - - // SymmetricKey512 - @"(?<=[^\r\n\t\w/\+\.\-\$,\\])" // pre-match - + @"(?[a-z0-9/\+]{86}==)" // match - + @"(?=([^\w/\+\.\-\$]|$))", // post-match - - // AzureActiveDirectoryLoginCredentials - @"(?<=@([a-z0-9.]+\.(on)?)?microsoft\.com[ -~\s\u200b]{1,80}?(userpass|password|pwd|pw|\wpass[ =:>]+|(get|make)securestring)\W)" // pre-match - + @"(?[^\s;`,""'\(\)]{10,80})" // match - + @"(?=[\s;`,""'\(\)])", // post-match - - // AzureActiveDirectoryLoginCredentials - @"" // pre-match - + @"(?(\-destinationPasswordPlain ""[^""]+?""))" // match - + @"(?=[ -~\s\u200b]{1,150}?@([a-z0-9.]+\.(on)?)?microsoft\.com)", // post-match - - // AzureActiveDirectoryLoginCredentials - @"(?<=(sign_in|SharePointOnlineAuthenticatedContext|(User|Exchange)Credentials?|password)[ -~\s\u200b]{1,100}?@([a-z0-9.]+\.(on)?)?microsoft\.com['""]?( \|\| \w+)?\s*,[\s\u200b]['""]?)" // pre-match - + @"(?[^`'""\s,;\(\)]+?)" // match - + @"(?=[`'""\s,;\(\)])", // post-match - - // AzureActiveDirectoryLoginCredentials - @"" // pre-match - + @"(?password[\W_][ -~\s\u200b]{40,100}?)" // match - + @"(?=@([a-z0-9\.]+\.(on)?)?microsoft\.com)", // post-match - - // LoginCredentials - @"" // pre-match - + @"[^a-z\$](DB_USER|user id|uid|(sql)?user(name)?|service\s?account)\s*[^\w\s,]([ -~\s\u200b]{2,120}?|[ -~]{2,30}?)([^a-z\s\$]|\s)\s*(DB_PASS|(sql|service)?password|pwd)\s*[^a-z,\+&\)\]\}\[\{_][ -~\s\u200b]{2,700}?([;|<,})]|$)|[^a-z\s\$]\s*(DB_PASS|password|pwd)\s*[^a-z,\+&\)\]\}\[\{_][ -~\s\u200b]{2,60}?[^a-z\$](DB_USER|user id|uid|user(name)?)\s*[^\w\s,]([ -~\s\u200b]{2,60}?|[ -~]{2,30}?)([;|<,})]|$)" // match - + @"", // post-match - - // LoginCredentialsInUrl - @"(?<=(amqp|ssh|(ht|f)tps?)://[^%:\s""'/][^:\s""'/\$]+[^:\s""'/\$%]:)" // pre-match - + @"(?[^%\s""'/][^@\s""'/]{0,100}[^%\s""'/])" // match - + @"(?=@[\$a-z0-9:\.\-_%\?=/]+)", // post-match - - // CertificatePrivateKeyHeader - @"" // pre-match - + @"(?-i)\-{5}BEGIN( ([DR]SA|EC|OPENSSH|PGP))? PRIVATE KEY( BLOCK)?\-{5}" // match - + @"", // post-match - - // HttpAuthorizationHeader - @"(?<=authorization[,\[:= ""']+(basic|digest|hoba|mutual|negotiate|oauth( oauth_token=)?|bearer [^e""'&]|scram\-sha\-1|scram\-sha\-256|vapid|aws4\-hmac\-sha256)[\s\r\n]{0,10})" // pre-match - + @"(?[a-z0-9/+_.=]{10,})" // match - + @"", // post-match - - // ClientSecretContext - @"(?<=(^|[a-z\s""'_])((app(lication)?|client)[_\- ]?(key(url)?|secret)|refresh[_\-]?token|[^t]AccessToken(Secret)?|(Consumer|api)[_\- ]?(Secret|Key)|(Twilio(Account|Auth)[_\- ]?(Sid|Token)))([\s=:>]{1,10}|[\s""':=|>,]{3,15}|[""'=:\(]{2}))" // pre-match - + @"(?(""data:text/plain,.+""|[a-z0-9/+=_.-]{10,200}[^\(\[\{;,\r\n]|[^\s""';<,\)]{5,200}))" // match - + @"", // post-match - - // CommunityStringContext - @"(?<=(^|\W{2}|set )snmp(\-server)?( | [ -~]+? )(community|priv)\s[""']?)" // pre-match - + @"(?[^\s]+)" // match - + @"(?=[""']?(\s|$))", // post-match - - // PasswordContextInScript - @"(?<=\s-(admin|user|vm)?password\s+[""']?)" // pre-match - + @"(?[^$\(\[<\{\-\s,""']+)[""']?(\s|$)" // match - + @"", // post-match - - // PasswordContextInScript - @"(?<=certutil(\.exe)?.{1,10}\-p\s+[""']?)" // pre-match - + @"(?[^\s,]{2,50})" // match - + @"(?=[""']?)", // post-match - - // PasswordContextInScript - @"(?<=(^|[_\s\$])[a-z]*(password|secret(key)?)[ \t]*[=:]+[ \t]*)" // pre-match - + @"(?[^:\s""';,<]{2,200})" // match - + @"", // post-match - - // PasswordContextInScript - @"(?<=\s-Name\s+[""']\w+Password[""']\s+-Value\s+[""']?)" // pre-match - + @"(?[^\s""']{2,1100})" // match - + @"(?=[""']?)", // post-match - - // PasswordContextInScript - @"(?<=(^|[\s\r\n\\])net(\.exe)?[""'\s\\]{1,5}(user\s+|share\s+/user:)[^\s,/]+[ \t]+[""']?)" // pre-match - + @"(?[^\s,""'>/]{2,50})" // match - + @"(?=[""']?)", // post-match - - // PasswordContextInScript - @"(?<=psexec(\.exe)?.{1,50}-u.{1,50}-p\s+[""']?)" // pre-match - + @"(?[^\s,]{2,50})" // match - + @"(?=[""']?)", // post-match - - // SymmetricKeyContextInXml - @"" // pre-match - + @"<(machineKey|parameter name=""|[a-z]+AccountInfo[^a-z])" // match - + @"", // post-match - + + // NuGet API keys. + @"\b" // pre-match + + @"oy2[a-p][0-9a-z]{15}[aq][0-9a-z]{11}[eu][bdfhjlnprtvxz357][a-p][0-9a-z]{11}[aeimquy4]" // match + + @"\b", // post-match + + // NPM author keys. + @"\b" // pre-match + + @"npm_[0-9A-Za-z]{36}" // match + + @"\b", // post-match }; } } diff --git a/src/Microsoft.VisualStudio.Services.Agent/Constants.cs b/src/Microsoft.VisualStudio.Services.Agent/Constants.cs index b817df299e..b84419abb9 100644 --- a/src/Microsoft.VisualStudio.Services.Agent/Constants.cs +++ b/src/Microsoft.VisualStudio.Services.Agent/Constants.cs @@ -322,6 +322,7 @@ public static class Agent public static readonly string Version = "agent.version"; public static readonly string WorkFolder = "agent.workfolder"; public static readonly string WorkingDirectory = "agent.WorkingDirectory"; + public static readonly string EnableAdditionalMaskingRegexes = "agent.enableadditionalmaskingregexes"; } public static class Build @@ -371,6 +372,7 @@ public static class Features public static readonly string GitLfsSupport = "agent.source.git.lfs"; public static readonly string GitShallowDepth = "agent.source.git.shallowFetchDepth"; public static readonly string SkipSyncSource = "agent.source.skip"; + public static readonly string EnableAdditionalMaskingRegexes = "agent.enableadditionalmaskingregexes"; } public static class Maintenance @@ -511,6 +513,7 @@ public static class Task Agent.Version, Agent.WorkFolder, Agent.WorkingDirectory, + Agent.EnableAdditionalMaskingRegexes, // Build variables Build.ArtifactStagingDirectory, Build.BinariesDirectory, diff --git a/src/Microsoft.VisualStudio.Services.Agent/HostContext.cs b/src/Microsoft.VisualStudio.Services.Agent/HostContext.cs index ce085db951..17fbb2d586 100644 --- a/src/Microsoft.VisualStudio.Services.Agent/HostContext.cs +++ b/src/Microsoft.VisualStudio.Services.Agent/HostContext.cs @@ -21,6 +21,7 @@ using System.Net.Http.Headers; using Pipelines = Microsoft.TeamFoundation.DistributedTask.Pipelines; using Agent.Sdk.Util; +using BuildXL.Cache.ContentStore.Interfaces.Tracing; namespace Microsoft.VisualStudio.Services.Agent { @@ -88,6 +89,7 @@ public class HostContext : EventListener, IObserver, IObserv public ShutdownReason AgentShutdownReason { get; private set; } public ILoggedSecretMasker SecretMasker => _secretMasker; public ProductInfoHeaderValue UserAgent => _userAgent; + public HostContext(HostType hostType, string logFile = null) { _secretMasker = new LoggedSecretMasker(_basicSecretMasker); @@ -106,13 +108,6 @@ public HostContext(HostType hostType, string logFile = null) this.SecretMasker.AddValueEncoder(ValueEncoders.UriDataEscape, $"HostContext_{WellKnownSecretAliases.UriDataEscape}"); this.SecretMasker.AddValueEncoder(ValueEncoders.BackslashEscape, $"HostContext_{WellKnownSecretAliases.UriDataEscape}"); this.SecretMasker.AddRegex(AdditionalMaskingRegexes.UrlSecretPattern, $"HostContext_{WellKnownSecretAliases.UrlSecretPattern}"); - if (AgentKnobs.MaskUsingCredScanRegexes.GetValue(this).AsBoolean()) - { - foreach (var pattern in AdditionalMaskingRegexes.CredScanPatterns) - { - this.SecretMasker.AddRegex(pattern, $"HostContext_{WellKnownSecretAliases.CredScanPatterns}"); - } - } // Create the trace manager. if (string.IsNullOrEmpty(logFile)) @@ -741,6 +736,15 @@ public static HttpClientHandler CreateHttpClientHandler(this IHostContext contex return clientHandler; } + + public static void AddAdditionalMaskingRegexes(this IHostContext context) + { + ArgUtil.NotNull(context, nameof(context)); + foreach (var pattern in AdditionalMaskingRegexes.CredScanPatterns) + { + context.SecretMasker.AddRegex(pattern, $"HostContext_{WellKnownSecretAliases.CredScanPatterns}"); + } + } } public enum ShutdownReason diff --git a/src/Test/L0/HostContextL0.cs b/src/Test/L0/HostContextL0.cs index ede7406606..47cc14a6c6 100644 --- a/src/Test/L0/HostContextL0.cs +++ b/src/Test/L0/HostContextL0.cs @@ -89,13 +89,27 @@ public void UrlSecretsAreMasked(string input, string expected) [Theory] [Trait("Level", "L0")] [Trait("Category", "Common")] - // some secrets that CredScan should suppress - [InlineData("xoxr-1xwlcyhsnfn9k69m4efzj3zkfhk", "***")] // Slack token - [InlineData("(+n97tcqhcpvu9zkhwwiwx4==)", "(***)")] // 128-bit symmetric key - [InlineData("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c", "***")] - // some secrets that CredScan should NOT suppress - [InlineData("The password is knock knock knock", "The password is knock knock knock")] + // Some secrets that the scanner SHOULD suppress. + [InlineData("deaddeaddeaddeaddeaddeaddeaddeadde/dead+deaddeaddeaddeaddeaddeaddeaddeaddeadAPIMxxxxxQ==", "***")] + [InlineData("deaddeaddeaddeaddeaddeaddeaddeadde/dead+deaddeaddeaddeaddeaddeaddeaddeaddeadACDbxxxxxQ==", "***")] + [InlineData("deaddeaddeaddeaddeaddeaddeaddeadde/dead+deaddeaddeaddeaddeaddeaddeaddeaddead+ABaxxxxxQ==", "***")] + [InlineData("deaddeaddeaddeaddeaddeaddeaddeadde/dead+deaddeaddeaddeaddeaddeaddeaddeaddead+AMCxxxxxQ==", "***")] + [InlineData("deaddeaddeaddeaddeaddeaddeaddeadde/dead+deaddeaddeaddeaddeaddeaddeaddeaddead+AStxxxxxQ==", "***")] + [InlineData("deaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeadAzFuxdeadQ==", "***")] + [InlineData("deaddeaddeaddeaddeaddeaddeaddeaddeaddeadxxAzSeDeadxx", "***")] + [InlineData("deaddeaddeaddeaddeaddeaddeaddeaddeaddeadde+ACRDeadxx", "***")] + [InlineData("oy2mdeaddeaddeadeadqdeaddeadxxxezodeaddeadwxuq", "***")] + [InlineData("deaddeaddeaddeaddeaddeaddeaddeadxAIoTDeadxx=", "***")] + [InlineData("deaddeaddeaddeaddeaddeaddeaddeadx+ASbDeadxx=", "***")] + [InlineData("deaddeaddeaddeaddeaddeaddeaddeadx+AEhDeadxx=", "***")] + [InlineData("deaddeaddeaddeaddeaddeaddeaddeadx+ARmDeadxx=", "***")] + [InlineData("deaddeaddeaddeaddeaddeaddeaddeaddAzCaDeadxx=", "***")] + [InlineData("xxx8Q~dead.dead.DEAD-DEAD-dead~deadxxxxx", "***")] + [InlineData("npm_deaddeaddeaddeaddeaddeaddeaddeaddead", "***")] + [InlineData("xxx7Q~dead.dead.DEAD-DEAD-dead~deadxx", "***")] + // Some secrets that the scanner should NOT suppress. [InlineData("SSdtIGEgY29tcGxldGVseSBpbm5vY3VvdXMgc3RyaW5nLg==", "SSdtIGEgY29tcGxldGVseSBpbm5vY3VvdXMgc3RyaW5nLg==")] + [InlineData("The password is knock knock knock", "The password is knock knock knock")] public void OtherSecretsAreMasked(string input, string expected) { // Arrange. @@ -144,9 +158,11 @@ public void LogFileChangedAccordingToEnvVariable() public HostContext Setup([CallerMemberName] string testName = "") { - return new HostContext( + var hc = new HostContext( hostType: HostType.Agent, logFile: Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), $"trace_{nameof(HostContextL0)}_{testName}.log")); + hc.AddAdditionalMaskingRegexes(); + return hc; } } } diff --git a/src/Test/L0/Listener/JobDispatcherL0.cs b/src/Test/L0/Listener/JobDispatcherL0.cs index 3195a54975..0393448c02 100644 --- a/src/Test/L0/Listener/JobDispatcherL0.cs +++ b/src/Test/L0/Listener/JobDispatcherL0.cs @@ -6,6 +6,7 @@ using System.Reflection; using System.Threading; using System.Threading.Tasks; +using Agent.Listener.Configuration; using Microsoft.TeamFoundation.DistributedTask.WebApi; using Microsoft.VisualStudio.Services.Agent.Listener; using Microsoft.VisualStudio.Services.WebApi; @@ -22,6 +23,7 @@ public sealed class JobDispatcherL0 private Mock _processInvoker; private Mock _agentServer; private Mock _configurationStore; + private Mock _featureFlagProvider; public JobDispatcherL0() { @@ -29,6 +31,7 @@ public JobDispatcherL0() _processInvoker = new Mock(); _agentServer = new Mock(); _configurationStore = new Mock(); + _featureFlagProvider = new Mock(); } private Pipelines.AgentJobRequestMessage CreateJobRequestMessage() @@ -53,6 +56,7 @@ public async void DispatchesJobRequest() var jobDispatcher = new JobDispatcher(); hc.SetSingleton(_configurationStore.Object); hc.SetSingleton(_agentServer.Object); + hc.SetSingleton(_featureFlagProvider.Object); hc.EnqueueInstance(_processChannel.Object); hc.EnqueueInstance(_processInvoker.Object); @@ -465,6 +469,7 @@ public async void DispatchesOneTimeJobRequest() var jobDispatcher = new JobDispatcher(); hc.SetSingleton(_configurationStore.Object); hc.SetSingleton(_agentServer.Object); + hc.SetSingleton(_featureFlagProvider.Object); hc.EnqueueInstance(_processChannel.Object); hc.EnqueueInstance(_processInvoker.Object); diff --git a/src/agentversion b/src/agentversion index 38ff051be7..354dbdca39 100644 --- a/src/agentversion +++ b/src/agentversion @@ -1 +1 @@ -3.227.1 +3.227.2