-
Notifications
You must be signed in to change notification settings - Fork 856
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Configurable masking token, perf improvements, refactoring. #4586
base: master
Are you sure you want to change the base?
Conversation
|
||
namespace Agent.Sdk.SecretMasking | ||
{ | ||
/// <summary> | ||
/// Extended secret masker service, that allows to log origins of secrets | ||
/// </summary> | ||
public class LoggedSecretMasker : ILoggedSecretMasker | ||
public class LoggedSecretMasker : SecretMasker, ILoggedSecretMasker |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logged secret masker (as opposed to the legacy logged secret masker) can extend SecretMasker
rather than wrapping it (because no other ILoggedSecretMasker
will be wrapped by this class). This change will help us switch over to using a SecretMasker
instance that 1ES provides that lives in a different repo (https://github.com/microsoft/security-utilities).
void AddValue(String value, string origin); | ||
void AddValueEncoder(ValueEncoder encoder, string origin); | ||
void SetTrace(ITraceWriter trace); | ||
IDictionary<string, string> GetTelemetry(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -8,5 +8,5 @@ internal interface ISecret | |||
/// <summary> | |||
/// Returns one item (start, length) for each match found in the input string. | |||
/// </summary> | |||
IEnumerable<ReplacementPosition> GetPositions(String input); | |||
IEnumerable<Replacement> GetReplacements(String input); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't find the use of secret masker clones in the code, does this utilization exist? One difference now between the legacy masker and the current is that the legacy masker doesn't retain elapsed masking time on clone. Is that an issue? Refers to: src/Agent.Sdk/SecretMasking/LegacyLoggedSecretMasker.cs:134 in a95cc17. [](commit_id = a95cc17, deletion_comment = False) |
} | ||
|
||
Sdk.SecretMasking.ISecretMasker Sdk.SecretMasking.ISecretMasker.Clone() | ||
{ | ||
return new LegacyLoggedSecretMasker(this._secretMasker.Clone()); | ||
} | ||
|
||
public IDictionary<string, string> GetTelemetry() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -50,7 +50,7 @@ public void IsUserInfoMaskedCorrectly() | |||
var testSecretMasker = initSecretMasker(); | |||
|
|||
Assert.Equal( | |||
"https://user:***@example.com", | |||
"https://user:+++@example.com", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return this._secretMasker.MaskSecrets(input); | ||
var stopwatch = Stopwatch.StartNew(); | ||
string result = this._secretMasker.MaskSecrets(input); | ||
Interlocked.Exchange(ref elapsedMaskingTime, stopwatch.ElapsedTicks); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} | ||
|
||
// Replace | ||
var stringBuilder = new StringBuilder(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{ | ||
startIndex = match.Index + 1; | ||
yield return new ReplacementPosition(match.Index, match.Length); | ||
if (input.IndexOf(sniffLiteral, StringComparison.Ordinal) != -1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A simple IndexOf check is 15x+ faster than something like RE2 in a typical perf test. And so using it as a first pass filter to decide whether to run a follow-on regex is likely to yield performance gains. These are typically 4o% or more in other scan scenarios 1ES owns that use the technique.
…for deleted agent knob.
@@ -347,6 +348,9 @@ public async Task<TaskResult> RunAsync(Pipelines.AgentJobRequestMessage message, | |||
finally | |||
{ | |||
Trace.Info("Finalize job."); | |||
|
|||
PublishSecretsMaskingTelemetry(jobContext); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me, considering we upload logs just after (UploadDiagnosticLogsAsync)
This change:
LoggedSecretMasker
derive fromSecretMasker
rather than wrapping an instance of this class.ReplacementPosition
class (now simple renamed toReplacement
). For secret values, we retain the existing default redaction string***
. For regexes that have no explicit rule information (an id and friendly name, together which comprise amoniker
), we use the string+++
. This change will allow users to easily search for logs looking for evidence of automatically redacted secrets. These secrets either should have been protected as secured variables OR there is an upstream leak of the secret in a script/dependency, etc.