diff --git a/docs/detectors/linux.md b/docs/detectors/linux.md index 87789f8a9..d6acc11e4 100644 --- a/docs/detectors/linux.md +++ b/docs/detectors/linux.md @@ -11,20 +11,6 @@ Linux detection depends on the following: Linux package detection is performed by running [Syft](https://github.com/anchore/syft) and parsing the output. The output contains the package name, version, and the layer of the container in which it was found. -### Scanner Scope - -By default, this detector invokes Syft with the `all-layers` scanning scope (i.e. the Syft argument `--scope all-layers`). - -Syft has another scope, `squashed`, which can be used to scan only files accessible from the final layer of an image. - -The detector argument `Linux.ImageScanScope` can be used to configure this option as `squashed` or `all-layers` when invoking Component Detection. - -For example: - -```sh ---DetectorArgs Linux.ImageScanScope=squashed -``` - ## Known limitations - Windows container scanning is not supported diff --git a/src/Microsoft.ComponentDetection.Detectors/linux/ILinuxScanner.cs b/src/Microsoft.ComponentDetection.Detectors/linux/ILinuxScanner.cs index 078211863..adbf67a9c 100644 --- a/src/Microsoft.ComponentDetection.Detectors/linux/ILinuxScanner.cs +++ b/src/Microsoft.ComponentDetection.Detectors/linux/ILinuxScanner.cs @@ -19,7 +19,6 @@ public interface ILinuxScanner /// The collection of Docker layers that make up the container image. /// The number of layers that belong to the base image, used to distinguish base image layers from application layers. /// The set of component types to include in the scan results. Only components matching these types will be returned. - /// The scope for scanning the image. See for values. /// A token to monitor for cancellation requests. The default value is . /// A task that represents the asynchronous operation. The task result contains a collection of representing the components found in the image and their associated layers. public Task> ScanLinuxAsync( @@ -27,7 +26,6 @@ public Task> ScanLinuxAsync( IEnumerable containerLayers, int baseImageLayerCount, ISet enabledComponentTypes, - LinuxScannerScope scope, CancellationToken cancellationToken = default ); } diff --git a/src/Microsoft.ComponentDetection.Detectors/linux/LinuxContainerDetector.cs b/src/Microsoft.ComponentDetection.Detectors/linux/LinuxContainerDetector.cs index 81ca7ac57..fdf19a4bf 100644 --- a/src/Microsoft.ComponentDetection.Detectors/linux/LinuxContainerDetector.cs +++ b/src/Microsoft.ComponentDetection.Detectors/linux/LinuxContainerDetector.cs @@ -28,8 +28,6 @@ ILogger logger { private const string TimeoutConfigKey = "Linux.ScanningTimeoutSec"; private const int DefaultTimeoutMinutes = 10; - private const string ScanScopeConfigKey = "Linux.ImageScanScope"; - private const LinuxScannerScope DefaultScanScope = LinuxScannerScope.AllLayers; private readonly ILinuxScanner linuxScanner = linuxScanner; private readonly IDockerService dockerService = dockerService; @@ -79,8 +77,6 @@ public async Task ExecuteDetectorAsync( return EmptySuccessfulScan(); } - var scannerScope = GetScanScope(request.DetectorArgs); - using var timeoutCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); timeoutCts.CancelAfter(GetTimeout(request.DetectorArgs)); @@ -100,7 +96,6 @@ public async Task ExecuteDetectorAsync( results = await this.ProcessImagesAsync( imagesToProcess, request.ComponentRecorder, - scannerScope, timeoutCts.Token ); } @@ -142,26 +137,6 @@ private static TimeSpan GetTimeout(IDictionary detectorArgs) : defaultTimeout; } - /// - /// Extracts and returns the scan scope from detector arguments. - /// - /// The arguments provided by the user. - /// The to use for scanning. Defaults to if not specified. - private static LinuxScannerScope GetScanScope(IDictionary detectorArgs) - { - if (detectorArgs == null || !detectorArgs.TryGetValue(ScanScopeConfigKey, out var scopeValue)) - { - return DefaultScanScope; - } - - return scopeValue?.ToUpperInvariant() switch - { - "ALL-LAYERS" => LinuxScannerScope.AllLayers, - "SQUASHED" => LinuxScannerScope.Squashed, - _ => DefaultScanScope, - }; - } - private static IndividualDetectorScanResult EmptySuccessfulScan() => new() { ResultCode = ProcessingResultCode.Success }; @@ -204,7 +179,6 @@ private static void RecordImageDetectionFailure(Exception exception, string imag private async Task> ProcessImagesAsync( IEnumerable imagesToProcess, IComponentRecorder componentRecorder, - LinuxScannerScope scannerScope, CancellationToken cancellationToken = default ) { @@ -275,7 +249,6 @@ await this.dockerService.InspectImageAsync(image, cancellationToken) internalContainerDetails.Layers, baseImageLayerCount, enabledComponentTypes, - scannerScope, cancellationToken ); diff --git a/src/Microsoft.ComponentDetection.Detectors/linux/LinuxScanner.cs b/src/Microsoft.ComponentDetection.Detectors/linux/LinuxScanner.cs index f9bdd864a..38817916c 100644 --- a/src/Microsoft.ComponentDetection.Detectors/linux/LinuxScanner.cs +++ b/src/Microsoft.ComponentDetection.Detectors/linux/LinuxScanner.cs @@ -27,14 +27,12 @@ public class LinuxScanner : ILinuxScanner private static readonly IList CmdParameters = [ "--quiet", + "--scope", + "all-layers", "--output", "json", ]; - private static readonly IList ScopeAllLayersParameter = ["--scope", "all-layers"]; - - private static readonly IList ScopeSquashedParameter = ["--scope", "squashed"]; - private static readonly SemaphoreSlim ContainerSemaphore = new SemaphoreSlim(2); private static readonly int SemaphoreTimeout = Convert.ToInt32( @@ -98,7 +96,6 @@ public async Task> ScanLinuxAsync( IEnumerable containerLayers, int baseImageLayerCount, ISet enabledComponentTypes, - LinuxScannerScope scope, CancellationToken cancellationToken = default ) { @@ -112,16 +109,6 @@ public async Task> ScanLinuxAsync( var stdout = string.Empty; var stderr = string.Empty; - var scopeParameters = scope switch - { - LinuxScannerScope.AllLayers => ScopeAllLayersParameter, - LinuxScannerScope.Squashed => ScopeSquashedParameter, - _ => throw new ArgumentOutOfRangeException( - nameof(scope), - $"Unsupported scope value: {scope}" - ), - }; - using var syftTelemetryRecord = new LinuxScannerSyftTelemetryRecord(); try @@ -133,7 +120,6 @@ public async Task> ScanLinuxAsync( { var command = new List { imageHash } .Concat(CmdParameters) - .Concat(scopeParameters) .ToList(); (stdout, stderr) = await this.dockerService.CreateAndRunContainerAsync( ScannerImage, diff --git a/src/Microsoft.ComponentDetection.Detectors/linux/LinuxScannerScope.cs b/src/Microsoft.ComponentDetection.Detectors/linux/LinuxScannerScope.cs deleted file mode 100644 index 164bd71ee..000000000 --- a/src/Microsoft.ComponentDetection.Detectors/linux/LinuxScannerScope.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Microsoft.ComponentDetection.Detectors.Linux; - -/// -/// Defines the scope for scanning Linux container images. -/// -public enum LinuxScannerScope -{ - /// - /// Scan files from all layers of the image. - /// - AllLayers, - - /// - /// Scan only the files accessible from the final layer of the image. - /// - Squashed, -} diff --git a/test/Microsoft.ComponentDetection.Detectors.Tests/LinuxContainerDetectorTests.cs b/test/Microsoft.ComponentDetection.Detectors.Tests/LinuxContainerDetectorTests.cs index 472afa29c..07aa3235d 100644 --- a/test/Microsoft.ComponentDetection.Detectors.Tests/LinuxContainerDetectorTests.cs +++ b/test/Microsoft.ComponentDetection.Detectors.Tests/LinuxContainerDetectorTests.cs @@ -73,7 +73,6 @@ public LinuxContainerDetectorTests() It.IsAny>(), It.IsAny(), It.IsAny>(), - It.IsAny(), It.IsAny() ) ) @@ -278,7 +277,6 @@ public async Task TestLinuxContainerDetector_SameImagePassedMultipleTimesAsync() It.IsAny>(), It.IsAny(), It.IsAny>(), - It.IsAny(), It.IsAny() ), Times.Once @@ -309,48 +307,6 @@ public async Task TestLinuxContainerDetector_TimeoutParameterSpecifiedAsync() await action.Should().NotThrowAsync(); } - [TestMethod] - [DataRow("all-layers", LinuxScannerScope.AllLayers)] - [DataRow("squashed", LinuxScannerScope.Squashed)] - [DataRow("ALL-LAYERS", LinuxScannerScope.AllLayers)] - [DataRow("SQUASHED", LinuxScannerScope.Squashed)] - [DataRow(null, LinuxScannerScope.AllLayers)] // Test default behavior - [DataRow("", LinuxScannerScope.AllLayers)] // Test empty string default - [DataRow("invalid-value", LinuxScannerScope.AllLayers)] // Test invalid input defaults to AllLayers - public async Task TestLinuxContainerDetector_ImageScanScopeParameterSpecifiedAsync(string scopeValue, LinuxScannerScope expectedScope) - { - var detectorArgs = new Dictionary { { "Linux.ImageScanScope", scopeValue } }; - var scanRequest = new ScanRequest( - new DirectoryInfo(Path.GetTempPath()), - (_, __) => false, - this.mockLogger.Object, - detectorArgs, - [NodeLatestImage], - new ComponentRecorder() - ); - - var linuxContainerDetector = new LinuxContainerDetector( - this.mockSyftLinuxScanner.Object, - this.mockDockerService.Object, - this.mockLinuxContainerDetectorLogger.Object - ); - - await linuxContainerDetector.ExecuteDetectorAsync(scanRequest); - - this.mockSyftLinuxScanner.Verify( - scanner => - scanner.ScanLinuxAsync( - It.IsAny(), - It.IsAny>(), - It.IsAny(), - It.IsAny>(), - expectedScope, - It.IsAny() - ), - Times.Once - ); - } - [TestMethod] public async Task TestLinuxContainerDetector_HandlesScratchBaseAsync() { diff --git a/test/Microsoft.ComponentDetection.Detectors.Tests/LinuxScannerTests.cs b/test/Microsoft.ComponentDetection.Detectors.Tests/LinuxScannerTests.cs index 6a1e98515..eaa2c2bb4 100644 --- a/test/Microsoft.ComponentDetection.Detectors.Tests/LinuxScannerTests.cs +++ b/test/Microsoft.ComponentDetection.Detectors.Tests/LinuxScannerTests.cs @@ -1,7 +1,6 @@ #nullable disable namespace Microsoft.ComponentDetection.Detectors.Tests; -using System; using System.Collections.Generic; using System.Linq; using System.Threading; @@ -289,8 +288,7 @@ await this.linuxScanner.ScanLinuxAsync( }, ], 0, - enabledTypes, - LinuxScannerScope.AllLayers + enabledTypes ) ) .First() @@ -337,8 +335,7 @@ await this.linuxScanner.ScanLinuxAsync( }, ], 0, - enabledTypes, - LinuxScannerScope.AllLayers + enabledTypes ) ) .First() @@ -387,8 +384,7 @@ await this.linuxScanner.ScanLinuxAsync( }, ], 0, - enabledTypes, - LinuxScannerScope.AllLayers + enabledTypes ) ) .First() @@ -437,8 +433,7 @@ await this.linuxScanner.ScanLinuxAsync( }, ], 0, - enabledTypes, - LinuxScannerScope.AllLayers + enabledTypes ) ) .First() @@ -527,8 +522,7 @@ public async Task TestLinuxScanner_SupportsMultipleComponentTypes_Async() new DockerLayer { LayerIndex = 1, DiffId = "sha256:layer2" }, ], 0, - enabledTypes, - LinuxScannerScope.AllLayers + enabledTypes ); var allComponents = layers.SelectMany(l => l.Components).ToList(); @@ -628,8 +622,7 @@ public async Task TestLinuxScanner_FiltersComponentsByEnabledTypes_OnlyLinux_Asy new DockerLayer { LayerIndex = 1, DiffId = "sha256:layer2" }, ], 0, - enabledTypes, - LinuxScannerScope.AllLayers + enabledTypes ); var allComponents = layers.SelectMany(l => l.Components).ToList(); @@ -714,8 +707,7 @@ public async Task TestLinuxScanner_FiltersComponentsByEnabledTypes_OnlyNpmAndPip new DockerLayer { LayerIndex = 1, DiffId = "sha256:layer2" }, ], 0, - enabledTypes, - LinuxScannerScope.AllLayers + enabledTypes ); var allComponents = layers.SelectMany(l => l.Components).ToList(); @@ -730,61 +722,4 @@ public async Task TestLinuxScanner_FiltersComponentsByEnabledTypes_OnlyNpmAndPip var pipComponent = allComponents.OfType().Single(); pipComponent.Name.Should().Be("requests"); } - - [TestMethod] - [DataRow(LinuxScannerScope.AllLayers, "all-layers")] - [DataRow(LinuxScannerScope.Squashed, "squashed")] - public async Task TestLinuxScanner_ScopeParameter_IncludesCorrectFlagAsync( - LinuxScannerScope scope, - string expectedFlag - ) - { - this.mockDockerService.Setup(service => - service.CreateAndRunContainerAsync( - It.IsAny(), - It.IsAny>(), - It.IsAny() - ) - ) - .ReturnsAsync((SyftOutputNoAuthorOrLicense, string.Empty)); - - var enabledTypes = new HashSet { ComponentType.Linux }; - await this.linuxScanner.ScanLinuxAsync( - "fake_hash", - [new DockerLayer { LayerIndex = 0, DiffId = "sha256:layer1" }], - 0, - enabledTypes, - scope - ); - - this.mockDockerService.Verify( - service => - service.CreateAndRunContainerAsync( - It.IsAny(), - It.Is>(cmd => - cmd.Contains("--scope") && cmd.Contains(expectedFlag) - ), - It.IsAny() - ), - Times.Once - ); - } - - [TestMethod] - public async Task TestLinuxScanner_InvalidScopeParameter_ThrowsArgumentOutOfRangeExceptionAsync() - { - var enabledTypes = new HashSet { ComponentType.Linux }; - var invalidScope = (LinuxScannerScope)999; // Invalid enum value - - Func action = async () => - await this.linuxScanner.ScanLinuxAsync( - "fake_hash", - [new DockerLayer { LayerIndex = 0, DiffId = "sha256:layer1" }], - 0, - enabledTypes, - invalidScope - ); - - await action.Should().ThrowAsync(); - } }