-
Notifications
You must be signed in to change notification settings - Fork 94
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
FEATURE: Add --normalize-for-ghas
argument to the rewrite
command
#2581
Changes from 1 commit
e66e7a1
b613f11
ac1d133
b6b98c0
2c7ec70
d1a8b18
b17469e
a79925e
cad8330
eae5a55
2df868a
fbb97ac
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ | |
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.IO; | ||
using System.Linq; | ||
|
||
using Microsoft.CodeAnalysis.Sarif.Driver; | ||
using Microsoft.CodeAnalysis.Sarif.Readers; | ||
|
@@ -64,6 +65,25 @@ public int Run(RewriteOptions options) | |
reformattedLog = new SortingVisitor().VisitSarifLog(reformattedLog); | ||
} | ||
|
||
if (options.NormalizeForGitHub) | ||
{ | ||
if ((reformattedLog.Runs?.Any(r => r.Artifacts?.Any(a => a.Location?.Uri?.IsAbsoluteUri == true) == true) == true) || | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So I don't like these two lines of code which will traverse the log file twice. Can't we simply invoke the RebaseUriVisitor in cases when those args are non-null. And then make the GitHubIngestionVisitor throw new arg exception on encountering the any absolute uri as you detect here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. made the suggested change. |
||
(reformattedLog.Runs?.Any(r => r.Results?.Any(s => s.Locations?.Any(l => l.PhysicalLocation?.ArtifactLocation?.Uri?.IsAbsoluteUri == true) == true) == true) == true)) | ||
{ | ||
if (options.BasePath == null || options.BasePathToken == null) | ||
{ | ||
throw new ArgumentException("The input SARIF file contains absolute Uri which will not work with GitHub. Please also provide `--base-path-value` and `--base-path-token` to convert them to relative Uri."); | ||
} | ||
else | ||
{ | ||
var visitor = new RebaseUriVisitor(options.BasePathToken, new Uri(options.BasePath), options.RebaseRelativeUris); | ||
reformattedLog = visitor.VisitSarifLog(reformattedLog); | ||
} | ||
} | ||
|
||
reformattedLog = new GitHubIngestionVisitor().VisitSarifLog(reformattedLog); | ||
} | ||
|
||
if (options.SarifOutputVersion == SarifVersion.OneZeroZero) | ||
{ | ||
var visitor = new SarifCurrentToVersionOneVisitor(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,5 +16,33 @@ public class RewriteOptions : SingleFileOptionsBase | |
Default = false, | ||
HelpText = "Sort results in the final output file.")] | ||
public bool SortResults { get; set; } | ||
|
||
[Option( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
"normalize-for-github", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. Convert means 'convert from some other non-SARIF format to SARIF.' This operation is a SARIF->SARIF transformation, not a 'conversion'. One thing, we could use 'normalize-for-ghas' instead as a more precise designation (though 'ghas' may be more opaque to users. I'm fine with either choice. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use 'normalize-for-ghas' instead as a more precise designation There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use 'normalize-for-ghas' instead as a more precise designation |
||
HelpText = "Normalize SARIF to conform to GitHub Advanced Security code scanning ingestion requirements.")] | ||
public bool NormalizeForGitHub { get; set; } | ||
|
||
[Option( | ||
'b', | ||
"base-path-value", | ||
Required = false, | ||
HelpText = "Base path value to use while rebasing all paths. E.x. 'C:\\bld\\1234\\bin\\'" | ||
)] | ||
public string BasePath { get; set; } | ||
|
||
[Option( | ||
't', | ||
"base-path-token", | ||
Required = false, | ||
HelpText = "Variable to use for the base path token (e.x. 'SRCROOT')" | ||
)] | ||
public string BasePathToken { get; set; } | ||
|
||
[Option( | ||
"rebase-relative-uris", | ||
Default = false, | ||
HelpText = "All relative uris will be rebased to the base-path-value if true. Default is false." | ||
)] | ||
public bool RebaseRelativeUris { get; set; } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
using System.Collections.Generic; | ||
using System.Globalization; | ||
using System.Linq; | ||
|
||
namespace Microsoft.CodeAnalysis.Sarif.Visitors | ||
|
@@ -12,42 +13,19 @@ public class GitHubIngestionVisitor : SarifRewritingVisitor | |
// Internal static rather than private const to allow a unit test with a practical limit. | ||
internal static int s_MaxResults = 5000; | ||
|
||
private Run run; | ||
private int ruleIndex = -1; | ||
private IList<Artifact> artifacts; | ||
private IList<ThreadFlowLocation> threadFlowLocations; | ||
|
||
public override Run VisitRun(Run node) | ||
{ | ||
this.run = node; | ||
this.artifacts = node.Artifacts; | ||
this.threadFlowLocations = node.ThreadFlowLocations; | ||
|
||
if (node.Results != null) | ||
{ | ||
int errorsCount = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. yes i think it supports warning, please see my other reply with screenshot. |
||
foreach (Result result in node.Results) | ||
{ | ||
if (result.Level == FailureLevel.Error) | ||
{ | ||
errorsCount++; | ||
} | ||
} | ||
|
||
if (errorsCount != node.Results.Count) | ||
{ | ||
var errors = new List<Result>(); | ||
|
||
foreach (Result result in node.Results) | ||
{ | ||
if (result.Level == FailureLevel.Error) | ||
{ | ||
errors.Add(result); | ||
} | ||
|
||
if (errors.Count == s_MaxResults) { break; } | ||
} | ||
|
||
node.Results = errors; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please also see the test file "NonErrorResults.sarif'. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps GitHub only used to process errors? Have you tested this in their system? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
if (node.Results.Count > s_MaxResults) | ||
{ | ||
node.Results = node.Results.Take(s_MaxResults).ToList(); | ||
|
@@ -89,10 +67,7 @@ public override ThreadFlowLocation VisitThreadFlowLocation(ThreadFlowLocation no | |
{ | ||
// Make sure there's a place to put the message. threadFlowLocation.Location | ||
// is not required, so the shared object might not have had one. | ||
if (node.Location == null) | ||
{ | ||
node.Location = new Location(); | ||
} | ||
node.Location ??= new Location(); | ||
|
||
node.Location.Message = message; | ||
} | ||
|
@@ -144,6 +119,8 @@ public override ArtifactLocation VisitArtifactLocation(ArtifactLocation node) | |
|
||
public override Result VisitResult(Result node) | ||
{ | ||
this.ruleIndex = node.RuleIndex; | ||
|
||
if (node.Fingerprints != null) | ||
{ | ||
// GitHub appears to require that fingerprints be emitted to the | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have a message string look-up helper that you should use. As Kalle notes, this is a pretty complex operation. OK, I see you grabbed this code from the insert optional data visitor. We shouldn't copy code like this, minimally, it should be in a common helper somewhere (you could have created a static in the other visitor, for example). Let me keep looking for a better helper, I could swear we have one. #Closed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, nope. It appears that we don't. So the correct course here is to please create a common helper for both this code and the insert optional data visitor to call. Second, create an issue for the problem that Kalle notes: 'Message creation logic does not properly search tool extensions for format strings.' There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. got it, will work on this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done both add helper method and create an issue There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
@@ -161,6 +138,32 @@ public override Result VisitResult(Result node) | |
return base.VisitResult(node); | ||
} | ||
|
||
public override Message VisitMessage(Message node) | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
if (node.Text == null) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this need the same for node.Markdown? #Closed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is form GitHub, I think GitHub requires .Text only |
||
{ | ||
ReportingDescriptor rule = this.ruleIndex != -1 ? this.run.Tool.Driver.Rules[this.ruleIndex] : null; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't fully implement SARIF-2.1.0 §3.11.7 Message string lookup. I think this won't find messages of tool extensions. #Resolved There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you are correct, created an issue to track. |
||
|
||
if (rule != null && | ||
rule.MessageStrings != null && | ||
rule.MessageStrings.TryGetValue(node.Id, out MultiformatMessageString formatString)) | ||
{ | ||
node.Text = node.Arguments?.Count > 0 | ||
? rule.Format(node.Id, node.Arguments) | ||
: formatString?.Text; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the result of string.Format still contains substrings like "{0}", should this double the braces, in order to prevent the SARIF consumer from treating those as placeholders and attempting to expand them again? Also, should this reset node.Arguments to null? #Resolved There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the result is put in should this reset node.Arguments to null ---- currently, .text is added side by side with .id and .arguments. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That's not how I read the standard.
So the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With more reading I think you are right! The Within both plain text and formatted message strings, the characters “{” and “}” SHALL be represented by the character sequences “{{” and “}}” respectively. ----- so, I think I will replace { with {{ and } with }}, let me know if sounds good to you. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will replace { with {{ and } with }} -- this is done and updated the test case. |
||
} | ||
|
||
if (node.Text == null && | ||
this.run.Tool.Driver.GlobalMessageStrings?.TryGetValue(node.Id, out formatString) == true) | ||
{ | ||
node.Text = node.Arguments?.Count > 0 | ||
? string.Format(CultureInfo.CurrentCulture, formatString.Text, node.Arguments.ToArray()) | ||
|
||
: formatString?.Text; | ||
} | ||
} | ||
return base.VisitMessage(node); | ||
} | ||
|
||
// Merge properties from a source to a target, preferring the existing properties | ||
// on the target if there are any duplicates. | ||
private static void MergeProperties(PropertyBagHolder target, PropertyBagHolder source) | ||
|
@@ -169,10 +172,7 @@ private static void MergeProperties(PropertyBagHolder target, PropertyBagHolder | |
if (source.Properties != null) | ||
{ | ||
// If so, make sure there's someplace to put them. | ||
if (target.Properties == null) | ||
{ | ||
target.Properties = new Dictionary<string, SerializedPropertyInfo>(); | ||
} | ||
target.Properties ??= new Dictionary<string, SerializedPropertyInfo>(); | ||
|
||
target.Properties = target.Properties.MergePreferFirst(source.Properties); | ||
} | ||
|
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.
Good release note item but let me add a bit more detail, try this:
--normalize-for-github
argument to therewrite
command to ensure rewritten SARIF is compatible with GitHub Advanced Security ingestion requirements. #2581 #ClosedThere 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.
thanks, fixed