diff --git a/src/Microsoft.Sbom.Api/Config/Args/GenerationArgs.cs b/src/Microsoft.Sbom.Api/Config/Args/GenerationArgs.cs
index 3d87b243..914e213f 100644
--- a/src/Microsoft.Sbom.Api/Config/Args/GenerationArgs.cs
+++ b/src/Microsoft.Sbom.Api/Config/Args/GenerationArgs.cs
@@ -116,6 +116,15 @@ public class GenerationArgs : GenerationAndValidationCommonArgs
[ArgDescription("If set to true, we will attempt to fetch license information of packages detected in the SBOM from the ClearlyDefinedApi.")]
public bool? FetchLicenseInformation { get; set; }
+ ///
+ /// Specifies the timeout in seconds for fetching the license information. Defaults to 30 seconds. Has no effect if
+ /// FetchLicenseInformation (li) argument is false or not provided.
+ ///
+ [ArgShortcut("lto")]
+ [ArgDescription("Specifies the timeout in seconds for fetching the license information. Defaults to 30 seconds. " +
+ "Has no effect if the FetchLicenseInformation (li) argument is false or not provided. ")]
+ public int? LicenseInformationTimeout { get; set; }
+
///
/// If set to true, we will attempt to parse license and supplier info from the packages metadata file.
///
diff --git a/src/Microsoft.Sbom.Api/Executors/ComponentDetectionBaseWalker.cs b/src/Microsoft.Sbom.Api/Executors/ComponentDetectionBaseWalker.cs
index d4240c50..e0e1ca5f 100644
--- a/src/Microsoft.Sbom.Api/Executors/ComponentDetectionBaseWalker.cs
+++ b/src/Microsoft.Sbom.Api/Executors/ComponentDetectionBaseWalker.cs
@@ -137,7 +137,15 @@ async Task Scan(string path)
{
licenseInformationRetrieved = true;
- var apiResponses = await licenseInformationFetcher.FetchLicenseInformationAsync(listOfComponentsForApi);
+ List apiResponses;
+ if (configuration.LicenseInformationTimeout is null)
+ {
+ apiResponses = await licenseInformationFetcher.FetchLicenseInformationAsync(listOfComponentsForApi);
+ }
+ else
+ {
+ apiResponses = await licenseInformationFetcher.FetchLicenseInformationAsync(listOfComponentsForApi, configuration.LicenseInformationTimeout.Value);
+ }
foreach (var response in apiResponses)
{
diff --git a/src/Microsoft.Sbom.Api/Executors/ILicenseInformationFetcher.cs b/src/Microsoft.Sbom.Api/Executors/ILicenseInformationFetcher.cs
index b5e7a719..c0f28f93 100644
--- a/src/Microsoft.Sbom.Api/Executors/ILicenseInformationFetcher.cs
+++ b/src/Microsoft.Sbom.Api/Executors/ILicenseInformationFetcher.cs
@@ -17,12 +17,16 @@ public interface ILicenseInformationFetcher
///
List ConvertComponentsToListForApi(IEnumerable scannedComponents);
+ /// >
+ Task> FetchLicenseInformationAsync(List listOfComponentsForApi);
+
///
/// Calls the ClearlyDefined API to get the license information for the list of components.
///
/// A list of strings formatted into a list of strings that can be used to call the batch ClearlyDefined API.
+ /// Timeout in seconds to use when making web requests
///
- Task> FetchLicenseInformationAsync(List listOfComponentsForApi);
+ Task> FetchLicenseInformationAsync(List listOfComponentsForApi, int timeout);
///
/// Gets the dictionary of licenses that were fetched from the ClearlyDefined API.
diff --git a/src/Microsoft.Sbom.Api/Executors/ILicenseInformationService.cs b/src/Microsoft.Sbom.Api/Executors/ILicenseInformationService.cs
index 675c4613..2b09a65c 100644
--- a/src/Microsoft.Sbom.Api/Executors/ILicenseInformationService.cs
+++ b/src/Microsoft.Sbom.Api/Executors/ILicenseInformationService.cs
@@ -9,4 +9,6 @@ namespace Microsoft.Sbom.Api.Executors;
public interface ILicenseInformationService
{
public Task> FetchLicenseInformationFromAPI(List listOfComponentsForApi);
+
+ public Task> FetchLicenseInformationFromAPI(List listOfComponentsForApi, int timeout);
}
diff --git a/src/Microsoft.Sbom.Api/Executors/LicenseInformationFetcher.cs b/src/Microsoft.Sbom.Api/Executors/LicenseInformationFetcher.cs
index 47dc6f7d..59ed5a70 100644
--- a/src/Microsoft.Sbom.Api/Executors/LicenseInformationFetcher.cs
+++ b/src/Microsoft.Sbom.Api/Executors/LicenseInformationFetcher.cs
@@ -84,7 +84,12 @@ public List ConvertComponentsToListForApi(IEnumerable
public async Task> FetchLicenseInformationAsync(List listOfComponentsForApi)
{
- return await licenseInformationService.FetchLicenseInformationFromAPI(listOfComponentsForApi);
+ return await FetchLicenseInformationAsync(listOfComponentsForApi, 30);
+ }
+
+ public async Task> FetchLicenseInformationAsync(List listOfComponentsForApi, int timeout)
+ {
+ return await licenseInformationService.FetchLicenseInformationFromAPI(listOfComponentsForApi, timeout);
}
// Will attempt to extract license information from a clearlyDefined batch API response. Will always return a dictionary which may be empty depending on the response.
diff --git a/src/Microsoft.Sbom.Api/Executors/LicenseInformationService.cs b/src/Microsoft.Sbom.Api/Executors/LicenseInformationService.cs
index c2a2a150..ee435f34 100644
--- a/src/Microsoft.Sbom.Api/Executors/LicenseInformationService.cs
+++ b/src/Microsoft.Sbom.Api/Executors/LicenseInformationService.cs
@@ -20,7 +20,6 @@ public class LicenseInformationService : ILicenseInformationService
private readonly ILogger log;
private readonly IRecorder recorder;
private readonly HttpClient httpClient;
- private const int ClientTimeoutSeconds = 30;
public LicenseInformationService(ILogger log, IRecorder recorder, HttpClient httpClient)
{
@@ -30,6 +29,11 @@ public LicenseInformationService(ILogger log, IRecorder recorder, HttpClient htt
}
public async Task> FetchLicenseInformationFromAPI(List listOfComponentsForApi)
+ {
+ return await FetchLicenseInformationFromAPI(listOfComponentsForApi, 30);
+ }
+
+ public async Task> FetchLicenseInformationFromAPI(List listOfComponentsForApi, int timeout)
{
var batchSize = 500;
var responses = new List();
@@ -38,7 +42,7 @@ public async Task> FetchLicenseInformationFromAPI(List list
var uri = new Uri("https://api.clearlydefined.io/definitions?expand=-files");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
- httpClient.Timeout = TimeSpan.FromSeconds(ClientTimeoutSeconds);
+ httpClient.Timeout = TimeSpan.FromSeconds(timeout);
for (var i = 0; i < listOfComponentsForApi.Count; i += batchSize)
{
diff --git a/src/Microsoft.Sbom.Common/Config/Configuration.cs b/src/Microsoft.Sbom.Common/Config/Configuration.cs
index b7cfd621..3dd94ab1 100644
--- a/src/Microsoft.Sbom.Common/Config/Configuration.cs
+++ b/src/Microsoft.Sbom.Common/Config/Configuration.cs
@@ -47,6 +47,7 @@ public class Configuration : IConfiguration
private static readonly AsyncLocal> generationTimestamp = new();
private static readonly AsyncLocal> followSymlinks = new();
private static readonly AsyncLocal> fetchLicenseInformation = new();
+ private static readonly AsyncLocal> licenseInformationTimeout = new();
private static readonly AsyncLocal> enablePackageMetadataParsing = new();
private static readonly AsyncLocal> deleteManifestDirIfPresent = new();
private static readonly AsyncLocal> failIfNoPackages = new();
@@ -309,6 +310,14 @@ public ConfigurationSetting FetchLicenseInformation
set => fetchLicenseInformation.Value = value;
}
+ ///
+ [DefaultValue(30)]
+ public ConfigurationSetting LicenseInformationTimeout
+ {
+ get => licenseInformationTimeout.Value;
+ set => licenseInformationTimeout.Value = value;
+ }
+
///
[DefaultValue(false)]
public ConfigurationSetting EnablePackageMetadataParsing
diff --git a/src/Microsoft.Sbom.Common/Config/IConfiguration.cs b/src/Microsoft.Sbom.Common/Config/IConfiguration.cs
index b2ecdc35..1da7b892 100644
--- a/src/Microsoft.Sbom.Common/Config/IConfiguration.cs
+++ b/src/Microsoft.Sbom.Common/Config/IConfiguration.cs
@@ -194,6 +194,12 @@ public interface IConfiguration
///
ConfigurationSetting FetchLicenseInformation { get; set; }
+ ///
+ /// Specifies the timeout in seconds for fetching the license information. Defaults to 30 seconds. Has no effect if
+ /// FetchLicenseInformation (li) argument is false or not provided.
+ ///
+ ConfigurationSetting LicenseInformationTimeout { get; set; }
+
///
/// If set to true, we will attempt to locate and parse package metadata files for additional information to include in the SBOM such as .nuspec/.pom files in the local package cache.
///
diff --git a/src/Microsoft.Sbom.Common/Config/InputConfiguration.cs b/src/Microsoft.Sbom.Common/Config/InputConfiguration.cs
index f0102229..384c0c83 100644
--- a/src/Microsoft.Sbom.Common/Config/InputConfiguration.cs
+++ b/src/Microsoft.Sbom.Common/Config/InputConfiguration.cs
@@ -141,6 +141,10 @@ public class InputConfiguration : IConfiguration
[DefaultValue(false)]
public ConfigurationSetting FetchLicenseInformation { get; set; }
+ ///
+ [DefaultValue(30)]
+ public ConfigurationSetting LicenseInformationTimeout { get; set; }
+
[DefaultValue(false)]
public ConfigurationSetting EnablePackageMetadataParsing { get; set; }