From 029389545ab69e4713bcfebf241519e8c089247c Mon Sep 17 00:00:00 2001 From: Eddy Nakamura Date: Fri, 16 Oct 2020 08:04:16 -0300 Subject: [PATCH 1/4] Adding command policy to multitool --- .../ApplyPolicyCommand.cs | 65 ++++++++++++++ .../ApplyPolicyOptions.cs | 13 +++ src/Sarif.Multitool/Program.cs | 2 + .../ApplyPolicyCommandTests.cs | 88 +++++++++++++++++++ ...t.UnitTests.Sarif.Multitool.Library.csproj | 2 + .../ApplyPolicyCommand/WithPolicy.sarif | 52 +++++++++++ .../ApplyPolicyCommand/WithPolicy2.sarif | 64 ++++++++++++++ 7 files changed, 286 insertions(+) create mode 100644 src/Sarif.Multitool.Library/ApplyPolicyCommand.cs create mode 100644 src/Sarif.Multitool.Library/ApplyPolicyOptions.cs create mode 100644 src/Test.UnitTests.Sarif.Multitool.Library/ApplyPolicyCommandTests.cs create mode 100644 src/Test.UnitTests.Sarif.Multitool.Library/TestData/ApplyPolicyCommand/WithPolicy.sarif create mode 100644 src/Test.UnitTests.Sarif.Multitool.Library/TestData/ApplyPolicyCommand/WithPolicy2.sarif diff --git a/src/Sarif.Multitool.Library/ApplyPolicyCommand.cs b/src/Sarif.Multitool.Library/ApplyPolicyCommand.cs new file mode 100644 index 000000000..ee068186b --- /dev/null +++ b/src/Sarif.Multitool.Library/ApplyPolicyCommand.cs @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Diagnostics; +using Microsoft.CodeAnalysis.Sarif.Driver; +using Newtonsoft.Json; + +namespace Microsoft.CodeAnalysis.Sarif.Multitool +{ + public class ApplyPolicyCommand : CommandBase + { + private readonly IFileSystem _fileSystem; + + public ApplyPolicyCommand(IFileSystem fileSystem = null) + { + _fileSystem = fileSystem ?? FileSystem.Instance; + } + + public int Run(ApplyPolicyOptions applyPolicyOptions) + { + try + { + Console.WriteLine($"Applying policy '{applyPolicyOptions.InputFilePath}' => '{applyPolicyOptions.OutputFilePath}'..."); + Stopwatch w = Stopwatch.StartNew(); + + bool valid = ValidateOptions(applyPolicyOptions); + if (!valid) { return FAILURE; } + + SarifLog actualLog = ReadSarifFile(_fileSystem, applyPolicyOptions.InputFilePath); + + actualLog.ApplyPolicies(); + + string fileName = CommandUtilities.GetTransformedOutputFileName(applyPolicyOptions); + + Formatting formatting = applyPolicyOptions.PrettyPrint + ? Formatting.Indented + : Formatting.None; + + WriteSarifFile(_fileSystem, actualLog, fileName, formatting); + + w.Stop(); + Console.WriteLine($"Rewrite completed in {w.Elapsed}."); + } + catch (Exception ex) + { + Console.WriteLine(ex); + return FAILURE; + } + + return SUCCESS; + } + + private bool ValidateOptions(ApplyPolicyOptions applyPolicyOptions) + { + bool valid = true; + + valid &= applyPolicyOptions.Validate(); + + valid &= DriverUtilities.ReportWhetherOutputFileCanBeCreated(applyPolicyOptions.OutputFilePath, applyPolicyOptions.Force, _fileSystem); + + return valid; + } + } +} \ No newline at end of file diff --git a/src/Sarif.Multitool.Library/ApplyPolicyOptions.cs b/src/Sarif.Multitool.Library/ApplyPolicyOptions.cs new file mode 100644 index 000000000..b539dc330 --- /dev/null +++ b/src/Sarif.Multitool.Library/ApplyPolicyOptions.cs @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using CommandLine; +using Microsoft.CodeAnalysis.Sarif.Driver; + +namespace Microsoft.CodeAnalysis.Sarif.Multitool +{ + [Verb("apply-policy", HelpText = "Apply policies from SARIF log.")] + public class ApplyPolicyOptions : SingleFileOptionsBase + { + } +} diff --git a/src/Sarif.Multitool/Program.cs b/src/Sarif.Multitool/Program.cs index 3ec226a8d..090df87a3 100644 --- a/src/Sarif.Multitool/Program.cs +++ b/src/Sarif.Multitool/Program.cs @@ -13,6 +13,7 @@ internal static class Program public static int Main(string[] args) { return Parser.Default.ParseArguments< + ApplyPolicyOptions, ExportValidationConfigurationOptions, ExportValidationDocumentationOptions, ExportValidationRulesMetadataOptions, @@ -29,6 +30,7 @@ public static int Main(string[] args) ResultMatchSetOptions, FileWorkItemsOptions>(args) .MapResult( + (ApplyPolicyOptions options) => new ApplyPolicyCommand().Run(options), (ExportValidationConfigurationOptions options) => new ExportValidationConfigurationCommand().Run(options), (ExportValidationDocumentationOptions options) => new ExportValidationDocumentationCommand().Run(options), (ExportValidationRulesMetadataOptions options) => new ExportValidationRulesMetadataCommand().Run(options), diff --git a/src/Test.UnitTests.Sarif.Multitool.Library/ApplyPolicyCommandTests.cs b/src/Test.UnitTests.Sarif.Multitool.Library/ApplyPolicyCommandTests.cs new file mode 100644 index 000000000..524020022 --- /dev/null +++ b/src/Test.UnitTests.Sarif.Multitool.Library/ApplyPolicyCommandTests.cs @@ -0,0 +1,88 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using FluentAssertions; +using Moq; +using System; +using System.IO; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.CodeAnalysis.Sarif.Multitool +{ + public class ApplyPolicyCommandTests + { + private static readonly ResourceExtractor Extractor = new ResourceExtractor(typeof(ApplyPolicyCommandTests)); + + [Fact] + public void WhenOutputFormatOptionsAreInconsistent_Fails() + { + const string InputFilePath = "AnyFile.sarif"; + + var mockFileSystem = new Mock(); + mockFileSystem.Setup(_ => _.FileExists(InputFilePath)).Returns(true); + + var options = new ApplyPolicyOptions + { + InputFilePath = InputFilePath, + Inline = true, + PrettyPrint = true, + Minify = true + }; + + int returnCode = new ApplyPolicyCommand(mockFileSystem.Object).Run(options); + + returnCode.Should().Be(1); + + mockFileSystem.Verify(_ => _.FileExists(InputFilePath), Times.Once); + mockFileSystem.VerifyNoOtherCalls(); + } + + [Fact] + public void WhenInputContainsOnePolicy_ShouldSucceed() + { + string path = "WithPolicy.sarif"; + File.WriteAllText(path, Extractor.GetResourceText($"ApplyPolicyCommand.{path}")); + + // Verify log loads, has correct Result count, and spot check a Result + SarifLog log = ExecuteTest(path); + log.Runs[0].Results.Count.Should().Be(1); + log.Runs[0].Results[0].Level.Should().Be(FailureLevel.Error); + + File.Delete(path); + } + + [Fact] + public void WhenInputContainsMultiplePolicies_ShouldSucceed() + { + string path = "WithPolicy2.sarif"; + File.WriteAllText(path, Extractor.GetResourceText($"ApplyPolicyCommand.{path}")); + + // Verify log loads, has correct Result count, and spot check a Result + SarifLog log = ExecuteTest(path); + log.Runs[0].Results.Count.Should().Be(1); + log.Runs[0].Results[0].Level.Should().Be(FailureLevel.Note); + + File.Delete(path); + } + + private SarifLog ExecuteTest(string path) + { + var options = new ApplyPolicyOptions + { + InputFilePath = path, + OutputFilePath = path, + Force = true + }; + + // Verify command returned success + int returnCode = new ApplyPolicyCommand().Run(options); + returnCode.Should().Be(0); + + // Verify SARIF output log exists + File.Exists(path).Should().BeTrue(); + + return SarifLog.Load(path); + } + } +} diff --git a/src/Test.UnitTests.Sarif.Multitool.Library/Test.UnitTests.Sarif.Multitool.Library.csproj b/src/Test.UnitTests.Sarif.Multitool.Library/Test.UnitTests.Sarif.Multitool.Library.csproj index 576e9b8eb..f35719565 100644 --- a/src/Test.UnitTests.Sarif.Multitool.Library/Test.UnitTests.Sarif.Multitool.Library.csproj +++ b/src/Test.UnitTests.Sarif.Multitool.Library/Test.UnitTests.Sarif.Multitool.Library.csproj @@ -30,6 +30,8 @@ + + diff --git a/src/Test.UnitTests.Sarif.Multitool.Library/TestData/ApplyPolicyCommand/WithPolicy.sarif b/src/Test.UnitTests.Sarif.Multitool.Library/TestData/ApplyPolicyCommand/WithPolicy.sarif new file mode 100644 index 000000000..77e3cd544 --- /dev/null +++ b/src/Test.UnitTests.Sarif.Multitool.Library/TestData/ApplyPolicyCommand/WithPolicy.sarif @@ -0,0 +1,52 @@ +{ + "$schema": "http://json.schemastore.org/sarif-2.1.0-rtm.1", + "version": "2.1.0", + "runs": [ + { + "tool": { + "driver": { + "name": "Test", + "version": "1.0.0", + "rules": [ + { + "id": "TEST0001", + "name": "Test", + "shortDescription": { + "text": "Test description." + }, + "messageStrings": { + "default": { + "text": "Test description." + } + } + } + ] + } + }, + "results": [ + { + "ruleId": "TEST0001", + "ruleIndex": 0, + "message": { + "text": "Test text." + } + } + ], + "columnKind": "utf16CodeUnits", + "policies": [ + { + "name": "TEST Policy", + "version": "1.0.0", + "rules": [ + { + "id": "TEST0001", + "defaultConfiguration": { + "level": "error" + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/Test.UnitTests.Sarif.Multitool.Library/TestData/ApplyPolicyCommand/WithPolicy2.sarif b/src/Test.UnitTests.Sarif.Multitool.Library/TestData/ApplyPolicyCommand/WithPolicy2.sarif new file mode 100644 index 000000000..c10342f52 --- /dev/null +++ b/src/Test.UnitTests.Sarif.Multitool.Library/TestData/ApplyPolicyCommand/WithPolicy2.sarif @@ -0,0 +1,64 @@ +{ + "$schema": "http://json.schemastore.org/sarif-2.1.0-rtm.1", + "version": "2.1.0", + "runs": [ + { + "tool": { + "driver": { + "name": "Test", + "version": "1.0.0", + "rules": [ + { + "id": "TEST0001", + "name": "Test", + "shortDescription": { + "text": "Test description." + }, + "messageStrings": { + "default": { + "text": "Test description." + } + } + } + ] + } + }, + "results": [ + { + "ruleId": "TEST0001", + "ruleIndex": 0, + "message": { + "text": "Test text." + } + } + ], + "columnKind": "utf16CodeUnits", + "policies": [ + { + "name": "TEST Policy", + "version": "1.0.0", + "rules": [ + { + "id": "TEST0001", + "defaultConfiguration": { + "level": "error" + } + } + ] + }, + { + "name": "TEST Policy 2", + "version": "1.0.0", + "rules": [ + { + "id": "TEST0001", + "defaultConfiguration": { + "level": "note" + } + } + ] + } + ] + } + ] +} \ No newline at end of file From a5ae12e1fde028b7611468d98b34c537284560b8 Mon Sep 17 00:00:00 2001 From: Eddy Nakamura Date: Fri, 16 Oct 2020 08:06:16 -0300 Subject: [PATCH 2/4] updating changelog --- src/ReleaseHistory.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ReleaseHistory.md b/src/ReleaseHistory.md index 0bc8ef08d..1d0a6b03c 100644 --- a/src/ReleaseHistory.md +++ b/src/ReleaseHistory.md @@ -11,6 +11,7 @@ * FEATURE: The Multitool `query` command can now evaluate properties in the result and rule property bags, for example `sarif query "properties.confidence:f > 0.95 AND rule.properties.category == 'security'"` * FEATURE: The validation rule `SARIF1004.ExpressUriBaseIdsCorrectly` now verifies that if an `artifactLocation.uri` is a relative reference, it does not begin with a slash. [#2090](https://github.com/microsoft/sarif-sdk/issues/2090) * BUGFIX: GitHub policy should not turn off any note level rules. [#2089](https://github.com/microsoft/sarif-sdk/issues/2089) +* FEATURE: Add `apply-policy` command to Multitool. [#2118](https://github.com/microsoft/sarif-sdk/pull/2118) ## **v2.3.6** [Sdk](https://www.nuget.org/packages/Sarif.Sdk/2.3.6) | [Driver](https://www.nuget.org/packages/Sarif.Driver/2.3.6) | [Converters](https://www.nuget.org/packages/Sarif.Converters/2.3.6) | [Multitool](https://www.nuget.org/packages/Sarif.Multitool/2.3.6) | [Multitool Library](https://www.nuget.org/packages/Sarif.Multitool.Library/2.3.6) * BUGFIX: Restore multitool client app package build. From ceef2e8ae5e5ad3be83a5096d3837e3d73f4dbc6 Mon Sep 17 00:00:00 2001 From: Eddy Nakamura Date: Fri, 16 Oct 2020 15:43:07 -0300 Subject: [PATCH 3/4] Larry's code review - 1 --- .../ApplyPolicyCommandTests.cs | 32 +------------------ 1 file changed, 1 insertion(+), 31 deletions(-) diff --git a/src/Test.UnitTests.Sarif.Multitool.Library/ApplyPolicyCommandTests.cs b/src/Test.UnitTests.Sarif.Multitool.Library/ApplyPolicyCommandTests.cs index 524020022..c63cea2dd 100644 --- a/src/Test.UnitTests.Sarif.Multitool.Library/ApplyPolicyCommandTests.cs +++ b/src/Test.UnitTests.Sarif.Multitool.Library/ApplyPolicyCommandTests.cs @@ -3,10 +3,8 @@ using FluentAssertions; using Moq; -using System; using System.IO; using Xunit; -using Xunit.Abstractions; namespace Microsoft.CodeAnalysis.Sarif.Multitool { @@ -14,30 +12,6 @@ public class ApplyPolicyCommandTests { private static readonly ResourceExtractor Extractor = new ResourceExtractor(typeof(ApplyPolicyCommandTests)); - [Fact] - public void WhenOutputFormatOptionsAreInconsistent_Fails() - { - const string InputFilePath = "AnyFile.sarif"; - - var mockFileSystem = new Mock(); - mockFileSystem.Setup(_ => _.FileExists(InputFilePath)).Returns(true); - - var options = new ApplyPolicyOptions - { - InputFilePath = InputFilePath, - Inline = true, - PrettyPrint = true, - Minify = true - }; - - int returnCode = new ApplyPolicyCommand(mockFileSystem.Object).Run(options); - - returnCode.Should().Be(1); - - mockFileSystem.Verify(_ => _.FileExists(InputFilePath), Times.Once); - mockFileSystem.VerifyNoOtherCalls(); - } - [Fact] public void WhenInputContainsOnePolicy_ShouldSucceed() { @@ -48,12 +22,10 @@ public void WhenInputContainsOnePolicy_ShouldSucceed() SarifLog log = ExecuteTest(path); log.Runs[0].Results.Count.Should().Be(1); log.Runs[0].Results[0].Level.Should().Be(FailureLevel.Error); - - File.Delete(path); } [Fact] - public void WhenInputContainsMultiplePolicies_ShouldSucceed() + public void WhenInputContainsMultiplePolicies_ShouldApplyPoliciesInOrder() { string path = "WithPolicy2.sarif"; File.WriteAllText(path, Extractor.GetResourceText($"ApplyPolicyCommand.{path}")); @@ -62,8 +34,6 @@ public void WhenInputContainsMultiplePolicies_ShouldSucceed() SarifLog log = ExecuteTest(path); log.Runs[0].Results.Count.Should().Be(1); log.Runs[0].Results[0].Level.Should().Be(FailureLevel.Note); - - File.Delete(path); } private SarifLog ExecuteTest(string path) From 804d8ec25e2fb3687e5c1dd19dc54baaa00c6479 Mon Sep 17 00:00:00 2001 From: Eddy Nakamura Date: Wed, 21 Oct 2020 14:03:11 -0300 Subject: [PATCH 4/4] fixing ordering --- .../ApplyPolicyCommandTests.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Test.UnitTests.Sarif.Multitool.Library/ApplyPolicyCommandTests.cs b/src/Test.UnitTests.Sarif.Multitool.Library/ApplyPolicyCommandTests.cs index c63cea2dd..2b3349e9d 100644 --- a/src/Test.UnitTests.Sarif.Multitool.Library/ApplyPolicyCommandTests.cs +++ b/src/Test.UnitTests.Sarif.Multitool.Library/ApplyPolicyCommandTests.cs @@ -1,9 +1,8 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using FluentAssertions; -using Moq; using System.IO; +using FluentAssertions; using Xunit; namespace Microsoft.CodeAnalysis.Sarif.Multitool