Skip to content

Commit

Permalink
Merge branch 'main' into users/ferojo/alignVerification
Browse files Browse the repository at this point in the history
  • Loading branch information
FernandoRojo authored Dec 2, 2024
2 parents c48ff65 + 9f24dfc commit 1efb54e
Show file tree
Hide file tree
Showing 66 changed files with 5,858 additions and 605 deletions.
4 changes: 2 additions & 2 deletions docs/detectors/nuget.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ NuGet Detection is performed by parsing any `*.nuspec`, `*.nupkg`, `*.packages.c

## Known Limitations

- The NuGet detector is currently overreporting because the global NuGet cache gets searched. This is because of NuGet's [restore behaviour][4] which downloads all possible dependencies before [resolving the final dependency graph][5]. To solve this overreporting a new NuGet Detector approach will be rolled out. This new approach will now only parse `*.packages.config` and `*.project.assets` (`*.csproj`) files. This means any components that are only found in `*.nuspec` or `*.nupkg` files will not be detected with the new NuGet Detector approach.
- There are also dependencies from the .NET SDK that are underreported. The list of dependencies can be found [here][6].
- Any components that are only found in `*.nuspec` or `*.nupkg` files will not be detected with the latest NuGet Detector approach, because the NuGet detector that scans `*.nuspec` or `*.nupkg` files overreports. This is due to of NuGet's [restore behaviour][4] which downloads all possible dependencies before [resolving the final dependency graph][5].
- Dependencies from the .NET SDK that are underreported. The list of dependencies can be found [here][6].

[4]: https://learn.microsoft.com/en-us/nuget/consume-packages/package-restore#package-restore-behavior
[5]: https://learn.microsoft.com/en-us/nuget/concepts/dependency-resolution
Expand Down
39 changes: 30 additions & 9 deletions docs/update-syft.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,40 @@ To do this:
```
2. Find the [latest version of Syft][2]
3. Install [Skopeo][3]
4. Use [`skopeo`][4] to copy the manifest and images to our Azure Container Registry:
3. Pull the latest container image
```
skopeo copy --all docker://docker.io/anchore/syft:{LATEST} docker://governancecontainerregistry.azurecr.io/syft:{LATEST}
$ docker pull docker.io/anchore/syft:v{LATEST}
v0.53.4: Pulling from anchore/syft
0d60d5ab2113: Pull complete
26136f3e3dd3: Pull complete
497aa7f04842: Pull complete
Digest: sha256:37e85e8efdeaabb1b6f65c5bc175b664cb05d1aaddd0d922130b8e25d6e49726
Status: Downloaded newer image for anchore/syft:v{LATEST}
docker.io/anchore/syft:v{LATEST}
```
5. Update the container reference in [`LinuxScanner`][5]
6. Update [the models][6] that map the Syft output
4. Retag the container image
```
$ docker tag docker.io/anchore/syft:v{LATEST} governancecontainerregistry.azurecr.io/syft:v{LATEST}
```
5. Push the new image to the registry
```
$ docker push governancecontainerregistry.azurecr.io/syft:v{LATEST}
The push refers to repository [governancecontainerregistry.azurecr.io/syft]
9c858c120b14: Pushed
840f3b941d62: Pushed
21ce82bb7448: Pushed
v{LATEST}: digest: sha256:04ed9c717a814fdccf52758b67333632a0ff16840fc393f5fba5864285eaebbe size: 945
```
6. Update the container reference in [`LinuxScanner`][3]
7. Update [the models][4] that map the Syft output
[1]: https://github.com/anchore/syft
[2]: https://github.com/anchore/syft/releases/latest
[3]: https://github.com/containers/skopeo/blob/main/install.md
[4]: https://github.com/containers/skopeo
[5]: https://github.com/microsoft/component-detection/blob/aaf865e38112fb2448f5866ab06d5898358403f6/src/Microsoft.ComponentDetection.Detectors/linux/LinuxScanner.cs#L20
[6]: https://github.com/microsoft/component-detection/blob/main/src/Microsoft.ComponentDetection.Detectors/linux/Contracts/SyftOutput.cs
[3]: https://github.com/microsoft/component-detection/blob/aaf865e38112fb2448f5866ab06d5898358403f6/src/Microsoft.ComponentDetection.Detectors/linux/LinuxScanner.cs#L20
[4]: https://github.com/microsoft/component-detection/blob/main/src/Microsoft.ComponentDetection.Detectors/linux/Contracts/SyftOutput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ public void RegisterUsage(
bool isExplicitReferencedDependency = false,
string parentComponentId = null,
bool? isDevelopmentDependency = null,
DependencyScope? dependencyScope = null)
DependencyScope? dependencyScope = null,
string targetFramework = null)
{
ArgumentNullException.ThrowIfNull(detectedComponent);

Expand All @@ -186,6 +187,12 @@ public void RegisterUsage(
lock (this.registerUsageLock)
{
storedComponent = this.detectedComponentsInternal.GetOrAdd(componentId, detectedComponent);

if (!string.IsNullOrWhiteSpace(targetFramework))
{
storedComponent.TargetFrameworks.Add(targetFramework.Trim());
}

this.AddComponentToGraph(this.ManifestFileLocation, detectedComponent, isExplicitReferencedDependency, parentComponentId, isDevelopmentDependency, dependencyScope);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,6 @@ public class ScannedComponent
public IEnumerable<int> ContainerDetailIds { get; set; }

public IDictionary<int, IEnumerable<int>> ContainerLayerIds { get; set; }

public ISet<string> TargetFrameworks { get; set; }
}
63 changes: 63 additions & 0 deletions src/Microsoft.ComponentDetection.Contracts/ConcurrentHashSet.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
namespace Microsoft.ComponentDetection.Contracts;

using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;

/// <summary>Represents a thread-safe set of values.</summary>
/// <typeparam name="T">The type of elements in the hash set.</typeparam>
public class ConcurrentHashSet<T> : IEnumerable<T>
{
private readonly ConcurrentDictionary<T, byte> dictionary;

// Create different constructors for different equality comparers
public ConcurrentHashSet() => this.dictionary = new ConcurrentDictionary<T, byte>();

public ConcurrentHashSet(IEqualityComparer<T> comparer) => this.dictionary = new ConcurrentDictionary<T, byte>(comparer);

/// <summary>Adds the specific element to the <see cref="ConcurrentHashSet{T}"/> object.</summary>
/// <param name="item">The element to add to the set.</param>
/// <returns>true if element was added to <see cref="ConcurrentHashSet{T}"/> object; false, if item was already present.</returns>
public bool Add(T item)
{
return this.dictionary.TryAdd(item, 0);
}

/// <summary>Removes the specific element to the <see cref="ConcurrentHashSet{T}"/> object.</summary>
/// <param name="item">The element to be removed from the set.</param>
/// <returns>true if element was successfully found and removed; otherwise, false.</returns>
public bool Remove(T item)
{
return this.dictionary.TryRemove(item, out _);
}

/// <summary>Determines whether the <see cref="ConcurrentHashSet{T}"/> contains the specified element.</summary>
/// <param name="item">The element to locate in the <see cref="ConcurrentHashSet{T}"/> object.</param>
/// <returns>true if the <see cref="ConcurrentHashSet{T}"/> object contains the specified element; otherwise, false.</returns>
public bool Contains(T item)
{
return this.dictionary.ContainsKey(item);
}

/// <summary>Removes all elements from a <see cref="ConcurrentHashSet{T}"/> object.</summary>
public void Clear() => this.dictionary.Clear();

public ISet<T> ToHashSet()
{
return new HashSet<T>(this.dictionary.Keys);
}

/// <summary>Returns an enumerator that iterates through the <see cref="ConcurrentHashSet{T}"/>.</summary>
/// <returns>An enumerator for the <see cref="ConcurrentHashSet{T}"/>.</returns>
public IEnumerator<T> GetEnumerator()
{
return this.dictionary.Keys.GetEnumerator();
}

/// <summary>Returns an enumerator that iterates through the <see cref="ConcurrentHashSet{T}"/>.</summary>
/// <returns>An enumerator for the <see cref="ConcurrentHashSet{T}"/>.</returns>
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public DetectedComponent(TypedComponent.TypedComponent component, IComponentDete
this.DetectedBy = detector;
this.ContainerDetailIds = [];
this.ContainerLayerIds = new Dictionary<int, IEnumerable<int>>();
this.TargetFrameworks = [];

if (containerDetailsId.HasValue)
{
this.ContainerDetailIds.Add(containerDetailsId.Value);
Expand Down Expand Up @@ -62,6 +64,9 @@ public DetectedComponent(TypedComponent.TypedComponent component, IComponentDete
/// <summary> Gets or sets Dependency Scope of the component.</summary>
public DependencyScope? DependencyScope { get; set; }

/// <summary> Gets Target Frameworks where the component was consumed.</summary>
public ConcurrentHashSet<string> TargetFrameworks { get; set; }

private string DebuggerDisplay => $"{this.Component.DebuggerDisplay}";

/// <summary>Adds a filepath to the FilePaths hashset for this detected component.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,22 @@ public interface ISingleFileComponentRecorder
IDependencyGraph DependencyGraph { get; }

/// <summary>
/// Add or Update a component. In case that a parent componentId is specified
/// an edge is created between those components in the dependency graph.
/// Add or Update a component. In case that a parent componentId is specified an edge is created between those components in the dependency graph.
/// Metadata provided to this method specifies how the component was consumed, not uniquely identifying details about the component itself.
/// </summary>
/// <param name="detectedComponent">Component to add.</param>
/// <param name="isExplicitReferencedDependency">The value define if the component was referenced manually by the user in the location where the scanning is taking place.</param>
/// <param name="parentComponentId">Id of the parent component.</param>
/// <param name="isDevelopmentDependency">Boolean value indicating whether or not a component is a development-time dependency. Null implies that the value is unknown.</param>
/// <param name="dependencyScope">Enum value indicating scope of the component. </param>
/// <param name="targetFramework">Optional value to determine the framework where the component was consumed.</param>
void RegisterUsage(
DetectedComponent detectedComponent,
bool isExplicitReferencedDependency = false,
string parentComponentId = null,
bool? isDevelopmentDependency = null,
DependencyScope? dependencyScope = null);
DependencyScope? dependencyScope = null,
string targetFramework = null);

/// <summary>
/// Register that a package was unable to be processed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ namespace Microsoft.ComponentDetection.Detectors.Ivy;
/// in the project's build.xml, or if they use any file inclusion mechanism, it will fail.
///
/// The file written out by the custom Ant task is a simple JSON file representing a series of calls to be made to
/// the <see cref="ISingleFileComponentRecorder.RegisterUsage(DetectedComponent, bool, string, bool?, DependencyScope?)"/> method.
/// the <see cref="ISingleFileComponentRecorder.RegisterUsage(DetectedComponent, bool, string, bool?, DependencyScope?, string)"/> method.
/// </remarks>
public class IvyDetector : FileComponentDetector, IExperimentalDetector
{
Expand Down
Loading

0 comments on commit 1efb54e

Please sign in to comment.