Skip to content
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

Create template tool task #600

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions src/Microsoft.Sbom.Targets/GenerateSbom.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Microsoft.Sbom.Targets;

using System;
using System.Collections.Generic;
using System.Diagnostics.Tracing;
using Microsoft.Build.Framework;

/// <summary>
/// This partial class defines and sanitizes the arguments that will be passed
/// into the SBOM API and CLI tool for generation.
/// </summary>
public partial class GenerateSbom
{
/// <summary>
/// Gets or sets the path to the drop directory for which the SBOM will be generated.
/// </summary>
[Required]
public string BuildDropPath { get; set; }

/// <summary>
/// Gets or sets the supplier of the package the SBOM represents.
/// </summary>
[Required]
public string PackageSupplier { get; set; }

/// <summary>
/// Gets or sets the name of the package the SBOM represents.
/// </summary>
[Required]
public string PackageName { get; set; }

/// <summary>
/// Gets or sets the version of the package the SBOM represents.
/// </summary>
[Required]
public string PackageVersion { get; set; }

/// <summary>
/// Gets or sets the base path of the SBOM namespace uri.
/// </summary>
[Required]
public string NamespaceBaseUri { get; set; }
vpatakottu marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// Gets or sets the path to the directory containing build components and package information.
/// For example, path to a .csproj or packages.config file.
/// </summary>
public string BuildComponentPath { get; set; }

/// <summary>
/// Gets or sets a unique URI part that will be appended to NamespaceBaseUri.
/// </summary>
public string NamespaceUriUniquePart { get; set; }

/// <summary>
/// Gets or sets the path to a file containing a list of external SBOMs that will be appended to the
/// SBOM that is being generated.
/// </summary>
public string ExternalDocumentListFile { get; set; }

/// <summary>
/// Indicates whether licensing information will be fetched for detected packages.
/// </summary>
public bool FetchLicenseInformation { get; set; }

/// <summary>
/// Indicates whether to parse licensing and supplier information from a packages metadata file.
/// </summary>
public bool EnablePackageMetadataParsing { get; set; }

/// <summary>
/// Gets or sets the verbosity level for logging output.
/// </summary>
public string Verbosity { get; set; }

/// <summary>
/// Gets or sets a list of names and versions of the manifest format being used.
/// </summary>
public string ManifestInfo { get; set; }

/// <summary>
/// Indicates whether the previously generated SBOM manifest directory should be deleted
/// before generating a new SBOM in the directory specified by ManifestDirPath.
/// Defaults to true.
/// </summary>
public bool DeleteManifestDirIfPresent { get; set; } = true;

/// <summary>
/// Gets or sets the path where the SBOM will be generated.
/// </summary>
public string ManifestDirPath { get; set; }

/// <summary>
/// Gets or sets the path to the SBOM CLI tool
/// </summary>
public string SbomToolPath { get; set; }

/// <summary>
/// Gets or sets the path to the generated SBOM directory.
/// </summary>
[Output]
public string SbomPath { get; set; }
}
88 changes: 2 additions & 86 deletions src/Microsoft.Sbom.Targets/GenerateSbomTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,98 +27,14 @@ namespace Microsoft.Sbom.Targets;
/// <summary>
/// MSBuild task for generating SBOMs from build output.
/// </summary>
public class GenerateSbomTask : Task
public partial class GenerateSbom : Task
{
/// <summary>
/// The path to the drop directory for which the SBOM will be generated.
/// </summary>
[Required]
public string BuildDropPath { get; set; }

/// <summary>
/// Supplier of the package the SBOM represents.
/// </summary>
[Required]
public string PackageSupplier { get; set; }

/// <summary>
/// Name of the package the SBOM represents.
/// </summary>
[Required]
public string PackageName { get; set; }

/// <summary>
/// Version of the package the SBOM represents.
/// </summary>
[Required]
public string PackageVersion { get; set; }

/// <summary>
/// The base path of the SBOM namespace uri.
/// </summary>
[Required]
public string NamespaceBaseUri { get; set; }

/// <summary>
/// The path to the directory containing build components and package information.
/// For example, path to a .csproj or packages.config file.
/// </summary>
public string BuildComponentPath { get; set; }

/// <summary>
/// A unique URI part that will be appended to NamespaceBaseUri.
/// </summary>
public string NamespaceUriUniquePart { get; set; }

/// <summary>
/// The path to a file containing a list of external SBOMs that will be appended to the
/// SBOM that is being generated.
/// </summary>
public string ExternalDocumentListFile { get; set; }

/// <summary>
/// If true, it will fetch licensing information for detected packages.
/// </summary>
public bool FetchLicenseInformation { get; set; }

/// <summary>
/// If true, it will parse licensing and supplier information from a packages metadata file.
/// </summary>
public bool EnablePackageMetadataParsing { get; set; }

/// <summary>
/// Determines how detailed the outputed logging will be.
/// </summary>
public string Verbosity { get; set; }

/// <summary>
/// A list of the name and version of the manifest format being used.
/// </summary>
public string ManifestInfo { get; set; }

/// <summary>
/// If true, it will delete the previously generated SBOM manifest directory before
/// generating a new SBOM in ManifestDirPath.
/// </summary>
public bool DeleteManifestDirIfPresent { get; set; } = true;

/// <summary>
/// The path where the SBOM will be generated.
/// </summary>
public string ManifestDirPath { get; set; }

/// <summary>
/// The path to the generated SBOM directory.
/// </summary>
[Output]
public string SbomPath { get; set; }

private ISBOMGenerator Generator { get; set; }

/// <summary>
/// Constructor for the GenerateSbomTask.
/// </summary>
public GenerateSbomTask()
public GenerateSbom()
{
var host = Host.CreateDefaultBuilder()
.ConfigureServices((host, services) =>
Expand Down
30 changes: 29 additions & 1 deletion src/Microsoft.Sbom.Targets/Microsoft.Sbom.Targets.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

<PropertyGroup>
<AssemblyName>Microsoft.Sbom.Targets</AssemblyName>
<TargetFrameworks>net8.0;net472</TargetFrameworks>
vpatakottu marked this conversation as resolved.
Show resolved Hide resolved
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64</RuntimeIdentifiers>
<IsPublishable>true</IsPublishable>
<IsPackable>true</IsPackable>
Expand All @@ -10,13 +11,15 @@
<Title>GenerateSbomTask</Title>
<Description>Tasks and targets for running the SBOM tool.</Description>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<SbomCLIToolTargetFramework>net8.0</SbomCLIToolTargetFramework>

<!-- This target will run when MSBuild is collecting the files to be packaged, and we'll implement it below. This property controls the dependency list for this packaging process, so by adding our custom property we hook ourselves into the process in a supported way. -->
<TargetsForTfmSpecificBuildOutput>
$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage
</TargetsForTfmSpecificBuildOutput>
<!-- This property tells MSBuild where the root folder of the package's build assets should be. Because we are not a library package, we should not pack to 'lib'. Instead, we choose 'tasks' by convention. -->
<BuildOutputTargetFolder>tasks</BuildOutputTargetFolder>
<IncludeBuildOutput>true</IncludeBuildOutput>
<!-- NuGet does validation that libraries in a package are exposed as dependencies, but we _explicitly_ do not want that behavior for MSBuild tasks. They are isolated by design. Therefore we ignore this specific warning. -->
<NoWarn>NU5100</NoWarn>
<!-- Suppress NuGet warning NU5128. -->
Expand All @@ -39,6 +42,19 @@
</ItemGroup>
</Target>

<!-- Include the SBOM CLI Tool to the .NET Framework package folder. -->
<Target Name="AddSbomToolToPackage" AfterTargets="Build">
vpatakottu marked this conversation as resolved.
Show resolved Hide resolved
<MSBuild Projects="..\Microsoft.Sbom.Tool\Microsoft.Sbom.Tool.csproj" Properties="TargetFramework=$(SbomCLIToolTargetFramework)" Targets="Publish" />
<ItemGroup>
<Content Include="..\Microsoft.Sbom.Tool\bin\$(Configuration)\$(SbomCLIToolTargetFramework)\publish\*" Pack="true">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<PackageCopyToOutput>true</PackageCopyToOutput>
<PackagePath>\tasks\net472\sbom-tool\</PackagePath>
<Visible>true</Visible>
</Content>
</ItemGroup>
</Target>

<ItemGroup>
<!-- these lines pack the build props/targets files to the `build` folder in the generated package.
by convention, the .NET SDK will look for build\<Package Id>.props and build\<Package Id>.targets
Expand All @@ -52,6 +68,18 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Microsoft.Sbom.Extensions.DependencyInjection\Microsoft.Sbom.Extensions.DependencyInjection.csproj" />
<ProjectReference Condition="'$(TargetFramework)'=='net8.0'" Include="..\Microsoft.Sbom.Extensions.DependencyInjection\Microsoft.Sbom.Extensions.DependencyInjection.csproj" PrivateAssets="all" />
<ProjectReference Condition="'$(TargetFramework)'=='net8.0'" Include="..\Microsoft.Sbom.Tool\Microsoft.Sbom.Tool.csproj" PrivateAssets="all" IncludeAssets="output" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net472'">
<Compile Remove="**/*.*" />
<Compile Include="GenerateSbom.cs" />
<Compile Include="SbomCLIToolTask.cs" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' != 'net472'">
<Compile Remove="SbomCLIToolTask.cs" />
</ItemGroup>

</Project>
28 changes: 18 additions & 10 deletions src/Microsoft.Sbom.Targets/Microsoft.Sbom.Targets.targets
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- TODO remove hardcoded str, reference this assembly using MSBuild props instead -->
<!-- TODO remove hardcoded str, reference this assembly using MSBuild props instead -->

<!--TODO we will eventaully want to replace or remove `AfterTargets="Build"`.
<!--TODO we will eventaully want to replace or remove `AfterTargets="Build"`.
Including this line means that this code will run at the end of `dotnet build`s of any project that this .targets
file is imported to (see line 24 of Microsoft.Sbom.Targets.csproj as an example of importing this file). This is
good for testing purposes, but not the behavior we ultimately want.
We will need to discuss with the .NET SDK team if they want this target to be automatically included after any
target and if so, which one. They likely know of a nuget packaging target that it would make sense to hook this in with.-->

<PropertyGroup>
<GenerateSbomTask_TFM Condition=" '$(TargetFramework)' == 'net6.0' ">net6.0</GenerateSbomTask_TFM>
<GenerateSbomTask_TFM Condition=" '$(TargetFramework)' == 'net8.0' ">net8.0</GenerateSbomTask_TFM>
<GenerateSbom_TFM Condition=" '$(MSBuildRuntimeType)' == 'Full' ">net472</GenerateSbom_TFM>
<GenerateSbom_TFM Condition=" '$(MSBuildRuntimeType)' == 'Core' ">net8.0</GenerateSbom_TFM>

<!--Set the SBOM CLI Tool path. This variable is only used in SbomCLIToolTask.cs-->
<SbomToolPath Condition=" '$(MSBuildRuntimeType)' == 'Full'">$(MSBuildThisFileDirectory)\..\tasks\$(GenerateSbom_TFM)\sbom-tool</SbomToolPath>
</PropertyGroup>
<UsingTask TaskName="Microsoft.Sbom.Targets.GenerateSbomTask" AssemblyFile="$(MSBuildThisFileDirectory)\..\tasks\$(GenerateSbomTask_TFM)\Microsoft.Sbom.Targets.dll" />

<!--Based on the MSBuild runtime, GenerateSbom will either pull the GenerateSbomTask or SbomCLIToolTask logic-->
<UsingTask TaskName="Microsoft.Sbom.Targets.GenerateSbom" AssemblyFile="$(MSBuildThisFileDirectory)\..\tasks\$(GenerateSbom_TFM)\Microsoft.Sbom.Targets.dll" />

<Import Project="$(MSBuildThisFileDirectory)\Microsoft.Sbom.Targets.props" />

<Target Name="GenerateSbomTarget" AfterTargets="Build" Condition=" '$(GenerateSBOM)' == 'true' And '$(MSBuildRuntimeType)' == 'Core'">
<GenerateSbomTask
<Target Name="GenerateSbomTarget" AfterTargets="Build" Condition=" '$(GenerateSBOM)' == 'true'">
<!--TODO: Add arguments for ToolTask-->
<GenerateSbom
BuildDropPath="$(SbomGenerationBuildDropPath)"
BuildComponentPath="$(SbomGenerationBuildComponentPath)"
PackageSupplier="$(SbomGenerationPackageSupplier)"
Expand All @@ -30,9 +37,10 @@
Verbosity="$(SbomGenerationVerbosity)"
ManifestInfo="$(SbomGenerationManifestInfo)"
DeleteManifestDirIfPresent="$(SbomGenerationDeleteManifestDirIfPresent)"
ManifestDirPath="$(SbomGenerationManifestDirPath)">
<Output TaskParameter="SbomPath" PropertyName="SbomPathResult" />
</GenerateSbomTask>
ManifestDirPath="$(SbomGenerationManifestDirPath)"
SbomToolPath="$(SbomToolPath)">
<Output TaskParameter="SbomPath" PropertyName="SbomPathResult" />
</GenerateSbom>
<Message Importance="High" Text="Task result: $(SbomPathResult)" />

<!-- Include the generated SBOM contents within the consumer's nuget package -->
Expand Down
43 changes: 43 additions & 0 deletions src/Microsoft.Sbom.Targets/SbomCLIToolTask.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Microsoft.Sbom.Targets;

using System.IO;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

/// <summary>
/// MSBuild ToolTask for generating an SBOM using the SBOM CLI tool
/// </summary>
public partial class GenerateSbom : ToolTask
{
protected override string ToolName => "Microsoft.Sbom.Tool";
vpatakottu marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// Get full path to SBOM CLI tool.
/// </summary>
/// <returns></returns>
protected override string GenerateFullPathToTool()
{
return Path.Combine(this.SbomToolPath, $"{this.ToolName}.exe");
}

/// <summary>
/// Return a formatted list of arguments for the SBOM CLI tool.
/// </summary>
/// <returns>string list of args</returns>
protected override string GenerateCommandLineCommands()
{
return "Command";
}

/// <summary>
/// Validates the SBOM CLI tool parameters
/// </summary>
/// <returns></returns>
protected override bool ValidateParameters()
{
return true;
}
}
Loading